# Salted CX Help Center
> Documentation for Salted CX, the AI-native customer-service and contact-center platform where AI agents and people operate conversations together.

URL: https://help.salted.cx


## Conversations SDK

Source: https://help.salted.cx/en/collections/1770448935-conversations-sdk


Category description here

The Open Source Salted CX Conversations SDK is the easiest way to build and maintain automated conversations. The Conversation SDK seamlessly integrates with Salted CX’s Your Logic and leverages all features available in Salted CX, including handover to agents and powerful analytics.

![](https://media.notiondesk.so/upload/698601e3debc0197370730.png)

Salted CX brings Conversations as Code to seamlessly fuse rule-based logic with the power of generative AI and guidelines described in the knowledge bases. Your Conversations as a Code are in a single place that fuses all your knowledge and business rules with the customer experience.

## [](#your-first-conversation)Your First Conversation

You can use your favorite programming language to respond to customer and agent activity. In the code snippet below we show example of reposting to a customer. For more details on how Conversations as a Code look like see [Your First Conversation article](/2d85d3a2a8dc80118bf1cc340cc3fcb2).

```java
// if there is already a human agent, do nothing
if (isAgentEngaged())
	return;

// if the converastion waits for an agent, just let the customer know
if (isWaitingForAgent()) {
	tell("Give us a few moments. My human colleague will join soon.");
	return;
}

// otherwise tell out bot is new here ...
tell("I am new here and still learning. Let me tranfer you to my human colleague. 😉");
	
// ... and ask human agents for help
askForHelp();
```

Example on how to use programming language to respond to the customer## [](#bridge-between-business-and-engineering-worlds)Bridge Between Business and Engineering Worlds

Conversations SDK aims to provide an API that is easy to read, even for business people without strong technical skills, so they have visibility into their processes as they really are. The programming language can naturally hide complexity behind methods, exposing the right amount of information at the right level.

### [](#exact-rules)Exact Rules

You can use exact rules to make decisions when handling the conversation. These are not different from programming in any other language. While the rules can be on the highest level, the complexity of the actions can be hidden in methods.

```java
if (refundValue < 100)
  issueRefund();
else
	askForHelp();
```





In English

If the customer requests refund for item that is less than $100, issue the refund. Otherwise escalate to an agent.







### [](#maintain-state)Maintain State

You can easily remember what happened in the conversation in the past and use it later in the conversation, so you do not have to re-retrieve data.

```java
if (message.isAbusive()) {
	badBehavior.increment();
	
	if (badBehavior.get() >= 3) {
		tell(Reply.End_due_to_Abuse);
		muteConversation();
	}
} 
```





In English

If the customer sends 3 or more abusive messages, use the canned reply telling them the conversation will not continue. Then no longer react to the conversation.







### [](#reasoning)Reasoning

We strongly encourage using exact rules for decisions whenever possible to make conversations faster, cheaper and more predictable. However, sometimes you need to understand what the customer says to make a decision.

```java
if (askYesNo("Is there a high risk the customer will cancel the contract?") 
	|| askYesNo("Does customer mention a potential legal issue?")) {
	
  askForHelp();
}
```





In English

If there is a high risk of the customer to cancel a contract or the customer implies there might be a legal issue, then escalate the conversation to an agent.







### [](#choose-knowledge-for-response)Choose Knowledge for Response

If your bot mostly provides an information

```java
// for every conversation we include refund policy if most of the covnersations are about refunds
usePage("https://demoadventures.com/refund-policy");

// we include information about pricing based on country
if ("US".equals(country)) {
	use("The prices do not include taxes.");
else
	use("The prices include taxes.");

// we include special instructions for treating VIP customers if the customer is VIP
if (vipCustomer)
	useNotion("https://notion.com/demoadventures/");
	
// this tries to use the provided knowledge so far and tries to respond to the customer based on the conversation
var attempt = tryToRespond();

// if the attempt to respond based on the provided content is not successful, we escalate to agents
if (attempt.notSuccessful())
	askForHelp();
```

### [](#hidden-complexity)Hidden Complexity

Conversations SDK provides implementation for commonly used patterns in the contact center, so you do not have to reinvent the wheel. For example, `tryRespondUsingKnowledgeBase` tries to determine which questions were not answered yet using an LLM. Then queries the knowledge base for content that may be related to the questions. Then it uses the LLM to formulate the answers to the questions.

```java
var attempt = tryRespondUsingKnowlegeBase();

if (attempt.allQuestionsAnswered())
	askQuestion(Confirm_Resolution);
else
  askForHelp();
```





In English

Try to respond to all the customer questions using our knowledge base.

If you answer all questions using the knowledge base, then ask customer the question to confirm resolution.

Otherwise escalate to an agent.







## [](#slower-growth-in-implementation-complexity)Slower Growth in Implementation Complexity

We always highly encourage reducing your business and process complexity before implementing anything, including your bot. However, there is often a point in reducing your process complexity that you cannot go beyond. This can be caused by objective factors, but also by differing opinions of stakeholders.

![](https://media.notiondesk.so/upload/698601ee85520488188523.png)

Conversations SDK is built on top of Live Conversations and Your Logic, providing additional convenience features so you do not have to work with JSON or process individual events. You can focus on delivering the best customer experience and the most efficient, automated business processes.

![](https://media.notiondesk.so/upload/698601f158248474641984.png)

Conversations SDK and the entire stack underneath are designed for people who are not senior DevOps engineers. We empower engineers to focus on their code and remove as much operational complexity as we can.

Features provided by Live Conversations and Your Logic:

- Fallback to agents. When your bot does not know what to do next it is very easy to ask agents to take over the conversation. Salted CX also automatically asks agents for help if your implementation experiences issues or is unavailable.

- Web chat widget. Web chat widget to talk to your customers that handles all the major browsers, remembers sessions and gets updated with new updates of major operating systems and browsers so you do not have to care.

- Unification of channels. You handle conversations in a unified way no matter whether they are web chats, emails, WhatsApp, etc. All the complexities of the individual channels and platforms are handled by us. You can have different business behavior for individual channels but technically you handle them in a unified way.

- Translations. You focus on handling conversations in a single language. Incoming and outgoing messages get automatically translated.

- Stateless-friendly. Your code that handles the conversations can be completelly stateless if you want. You can store state data related to conversation to Salted CX and you will receive them when a next action happens.

- Survive short downtimes in your implementation. Your Logic helps you survive short unavailability of your code for a brief period of time. This enables you to do application updates even without complex support for downtime-free upgrades.

- Sequencing of events for conversations. You do not have to care about complexity of processing two customer messages in the same conversation in parallel.

Features provided by Conversations SDK on top of the above:

- Converting JSON data to convenient objects and vice versa. You do not have to parse and process JSONs. Instead you have convenient objects that have features that you most commonly need to handle teh customer conversations.

- Integration with AI. The Conversations SDK provides easy and natural integration with AI so you can take naturally integrate reasoning with deterministic rules and you can combine static polished messages with generated ones.

- Glass Box. The Conversations SDK does as little or as much for you as you want and enables you to customize its behavior on every level. You have a great starting point to get a bot out of the gate quickly with absolute freedom where to take from there. No strings attached.

- Integration into runnable environments. Conversations SDK enableys you to quickly get a runnable implementation of Your Logic information. You can use lightweight server or easily deploy the conversation to AWS Lambda.

- Logging and data collection.

## [](#use-your-engineering-talent-and-environment)Use Your Engineering Talent and Environment

Conversations SDK enables you to write Conversations as a Code in major programming languages such as TypeScript and Java. This enables you to build the customer experience using the engineers you already have in the development and runtime environment you already have.

Version Control. You can use your existing version control system, such as GIT, to manage changes, perform rollbacks, and work on new versions of your conversations.

Code Reviews. You can use your existing workflow for ensuring code quality, such as code reviews.

Continuous Integration. You can run a battery of tests before deploying each change to ensure there are no significant regressions or that the new functionality behaves as expected.

## [](#use-ai-to-build-ai)Use AI to Build AI

The AI is getting better in coding every day. Take advantage of AI to kickstart building your conversation. AI can quickly convert your description of the customer experience into robust code that ensures consistent execution of automated conversations in Salted CX.

## [](#testing-toolkit)Testing Toolkit

Unlike traditional code that is always deterministic, AI responses are not. The Conversation SDK provides testing utilities to help you test AI and reduce the risk of unexpected behavior and regressions.

You can test whether the change of your AI model, your change of prompts, or flow changes has not caused a regression in the test suite you have. Whenever you encounter AI behavior that is unsatisfactory, and you want it improved in the future, add it to the test suite to ensure it is resolved in the next release and does not regress.

```java
public class DemoAdventurelInsuranceTest extends SingleConversationTest {

	public DemoAdventurelInsuranceTest() {
		super(10, // Number of attempts
				  90, // Required success rate in percentages
				  DemoAdventuresConversation::new, // Conversation we will test
					transcript() // Create a mock conversation
							.bot("Hello, how can I help you?")
							.customer("Hello, is the travel insurance included?"));
	}

	protected void testResponse(TestedResponse response) {
	  // we want to ensure bot has not escalated to agent
	  assertFalse(response.needsHelp());
	  
		// we want bot to reply in a single message
		assertEquals(1, response.messages().count());
		
		// we want bot to start with clear answer, followed by explanation (thus space in after period)
		assertTrue(response.messages().startsWith("Yes. "));
		
		// we want to be sure that the answer explicitly contains "included"
		assertTrue(response.messages().containsAllIgnoreCase("included"));
		
		// we can also use the AI to double check the AI
		assertTrue(response.askYesNo("The bot confirmed that the insurance is included in the price."));
	}
}
```

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

As generative AI is inherently non-deterministic, even when you have some buffer in the number of successes, the test may still occasionally fail. You should balance the number of required successes with the time you want to invest in reviewing the failed tests. Note that the boundaries are primarily intended to detect significant performance degradation.





## [](#bring-your-own-ai)Bring Your Own AI

The Conversation SDK lets you choose which AI model or service to use. You can even use multiple AI models for different use cases to balance response speed, cost, and reliability. You can use a sequence of LLMs.

```java
AISetup.easyTasks(new Fallback(
	new Ollama(Ollama.PHI), 
	new OpenAI("SECRET_TOKEN", "gpt-4.1-mini"));
AISetup.normalTasks(new OpenAI("SECRET_TOKEN", "gpt-4.1-mini"));
AISetup.complexTasks(new OpenAI("SECRET_TOKEN", "gpt-5.1"));
```

## [](#provide-the-response-piece-by-piece)Provide the Response Piece by Piece

You can contribute to the reply to the customer in multiple parts of the conversation.

```java
// add greeting if we know we have not greeted yet
if (!greeted.get()) {
	greeted.true();
	tell("Hello?");
}

// if we do not know what customer is asking
if (!theCustomerRequestIsKnown())
	tell("How can help you?");
else {
	// depending on the metadata we tell what knowledge we will use to respond to customer questions
	if (product.category == TOYS_UNDER_14)
		use(Knowledge.ToysUnder14);
	
	if (product.country == US)
		use(Knowledge.ProductsInUs);
	else
		use(Knowledge.ProductsInternational);
	
	var attempt = tryAnsweringUsingContent();
}
```

## [](#start-easily)Start Easily

The Conversation SDK is designed to handle common conversation patterns with ease, offering complete flexibility for future conversation handling.

```java
public void customerMessage(Message message) {
	// a message towards the customer
	tell("Hello, I am new here and need more time to be useful. I will ask my human colleagues for help. Please give them few moments to join.");
	
	// a note visible only to agents
	note("Please help the customer.");
	
	// ask agents to join the conversation and attend to the customer
	askForHelp();
	
	// tell we do not want to be notified about future activity in the conversation
	disengage();
}
```

Example code responding to a customer message```java
if (allCustomerQuestionsAreAnswered()) {
	// we answered everyhing, lets ask the customer it is really the case
	askQuestion(Questions.Have_We_Resolved_Your_Request);
}
else {
	// still some work to do
}
```

Convenience methods for most common patterns```java
if (customer.isAngry()) {
	// we ask for a human agent to be engaged
	askForHelp(); 
}
```

This example uses AI to determine whether the customer is not happy```java
var nextStep = tryRespondUsingContent(
									webPage("https://help.company.com/article/123");
if (nextStep == Retry) {
	// fallback when the answer is on the web page
}
```

Convenience methods for complex implementations let you focus on the customer experience```java
var questions = customer.unansweredQuestions();
note("The customer questions that still need and answer:" 
			+ newLine() 
			+ unorderedList(questions));
askForHelp();
```

Get a list of questions that were not yet answered and pass them to the agent## [](#your-logic-only-versus-conversations-sdk)Your Logic Only versus Conversations SDK

The world is complex, the business is complex.

| Feature | Your Logic Only | With Conversations SDK |
|---|---|---|
| Programming Language | Any | Java, TypeScript (NodeJS) |
| Programming Interface | JSON events over HTTP | Language-specific fluent API |
| Channel Unification | Yes | Yes |
| Translations | Yes | Yes |
| Fault Tolerance | Yes | Yes |
| Fallback to Live Agents | Yes | Yes |
| Designed for Stateless | Yes | Yes |
| Integration |  |  |
| Integrations with LLM | No | Yes |
| REST API Convenience | No | Yes |
| Built-in Content |  |  |
| Canned Replies | No | Yes |
| Canned Questions | No | Yes |
| Knowledge Integration |  |  |
| Downloading Web Page Content | No | Yes |
| Notion | No | Yes |
| Google Drive | No | Yes |
| Caching Content | No | Yes |
| Reply based on provided content | No | Yes |
| Visibility |  |  |
| Logging | No | Yes |
| Reporting LLM Usage | No | Yes |



### [](#request-handling-in-your-logic)Request Handling in Your Logic

![](https://media.notiondesk.so/upload/698601f4c76f7279276988.png)

### [](#request-using-conversations-sdk)Request Using Conversations SDK

If using the Conversations SDK, much more work is done for you.

![](https://media.notiondesk.so/upload/698601f7767c4326477366.png)

## [](#knowledge-base-and-web-content)Knowledge Base and Web Content

The Conversation SDK offers built-in support for connecting to a knowledge base, enabling RAG (Retrieval Augmented Generation) to respond to customers based on a vast volume of knowledge specific to your business.

Using knowledge bases and content from your website or other web-based applications enables you to resolve a large volume of customer requests without using a complex rule-based logic. This lets you focus on cases that are hard to describe in your knowledge base or require interaction.

```java
var responseAttempt = tryRespondingUsingKnowledgeBase();

if (responseAttempt.unableToAnswerCustomerQuestion()) {
	// alternative handling of the conversation
}
```

## [](#full-power-of-your-programming-language)Full Power of Your Programming Language

Conversation SDK empowers you without restricting you to a proprietary tool or language that has numerous limitations. You can use your programming language to integrate with your services, querying them for information or triggering actions.

```java
var availableTimeSlots = yourCompanyBookingService.listFreeTimeslots();

question("Please pick the timeslot that works for you.", availableTimeSlots);
```

Example code that retrieves data from a custom service and uses Salted CX to ask customers to pick one## [](#easy-to-read-for-stakeholders)Easy to Read for Stakeholders

While the Conversation SDK is targeted at engineers, we also aimed to make it readable for other stakeholders so they can understand why the bot behaves the way it does. This enables closer collaboration among engineers, product managers, customer experience professionals, and others.

You can involve other stakeholders to modify canned responses and AI instructions.

```java
public enum CannedReplies implements Expression {

	// Unwanted behavior
	Hacking_Attempt_Reply("To continue your hacking attempts please share your credit card details so we step up the game! :)"),

	// Esclalations
	Talk_to_Agent_Refuse("I'm sorry. Our agents are busy attending to customers who need help with their bought."),

	// Deal Conversation
	No_Answer_in_Knowledge_Base("Unfortunatelly, I could not find the answer for your question. Try to contact the merchant directly."),

	// Give up resolution
	Give_Up("I am trying, but I have trouble helping you. Please reach directly to the travel agent."),

	// Feedback to agent
	Note_Action_Not_Supported("The action is currently not supported.")
	;
	
	// the rest of the code is here
}
```

Example of code that contains canned replies that can be edited by non-technical users```java
Instruction.Abusive = "";
```

## [](#versioning)Versioning

You can manage Conversations as Code using powerful existing tools such as Git. This enables you to iterate on the user experience with confidence, knowing that you can always roll back. You can also establish a process for publishing changes that includes code reviews. You can use branches to develop major upgrades in parallel to doing small increments on the existing experience.

## [](#optimizing-resources)Optimizing Resources

The Conversations SDK uses aggressive caching and enables you to use different AI model for different tasks based on their complexity to shield you from the chore of managing costs.

Optimizing the use of resources also improves response times and enables handling more conversations on the same hardware.

## [](#raw-your-logic-vs-conversations-sdk)Raw Your Logic vs. Conversations SDK

Both Your Logic and Conversations SDK are useful for handling conversations with customers. As Conversations SDK is built on top of Your Logic, it provides everything Your Logic provides, plus extra features to get you started.

Conversations SDK is a great way to jump-start your development and have your first production-ready bot today.

## [](#message-consolidation)Message Consolidation

When you try to respond to the customer, you can have multiple items you would like to tell the customer. However, there might be complex logic under which circumstances you want to tell something.

# [](#content-selection)Content Selection

When AI generates replies to answer customer questions, it needs information that provides answers to the questions. Ideally, the AI receives as input the minimum information possible while not missing content that is important for answering the customer's question.

Missing information makes it impossible for AI to answer the customer question and increases the chance of hallucinations. Providing high volume of unnecessary information makes it harder for AI to answer the specific questions. Often it is not possible to provide all information because it is simply too many.

## [](#rule-based-content)Rule-Based Content

You can use conversation metadata to choose which content to provide for a reply attempt.

Pros:

- Very fast decisions on what to include

Cons:

- Rules for knowledge inclusion may be complex and require manual maintenance

- Does not take into consideration the customer question

### [](#static-content)Static Content

You can use

```java
if (purchases.containsCustomizedItem())
	use("Customized items cannot be refunded. Customer is warned before purchase as these products cannot be sold to somebody else.");
else
	use("All purchases can be refunded without stating a reason within 14 days since the purchase.");
```

Even when using static content we recommend to store these statements in a separate file as variables to have all knowledge easy to locate and manage in a single place.

```java
if (customer.isVIP())
	use(Knowledge.Info_for_VIP_Customers);
```

### [](#web-page-content)Web Page Content

You can use content from a publicly accessible web page.

```java
usePage("https://demoadventures.com/refund-policy");

if ("US".equals(customer.region))
	usePage("https://demoadventures.com/privacy-us");
else
	usePage("https://demoadventures.com/privacy-international");
```

### [](#knowledge-base-content)Knowledge Base Content

You can also use the content from an internal knowledge base. Currently, Conversations SDK supports Notion.

```java
use(knowledge.content("article-123"));
```

Specifically for Notion

## [](#search-based-content)Search-Based Content

You can use the knowledge base to search for content

```java
useKnowledgeBase(knowledgeBase, search);
```

---

## Glossary

Source: https://help.salted.cx/en/collections/1755246965-glossary


Category description here

---

## Technical

Source: https://help.salted.cx/en/collections/1755269138-technical


Category description here

---

## Integrations

Source: https://help.salted.cx/en/collections/1755256026-integrations


Category description here

Salted CX provides support for the following contact center platforms.

| Platform | Details |
|---|---|
| Aircall | Support for voice conversations. |
| [Amazon Connect](https://help.salted.cx/en/articles/integration-amazon-connect) | Support for conversation metadata, agent statuses, and chat content. With Amazon Lens enables Salted CX also downloads voice transcripts and sentiment for both chat and voice transcripts. |
| [Freshdesk](https://help.salted.cx/en/articles/integration-freshdesk) | Support for importing tickets as agent engagements in Salted CX. |
| [Salesforce](https://help.salted.cx/en/articles/integration-salesforce) | Support for Salesforce Omni-Channel agent work and Salesforce tasks for metadata. Salted CX also imports transcripts for live chats and emails. |
| [ServiceNow](https://help.salted.cx/en/articles/integration-servicenow) | Support for importing incidents from ServiceNow including conversation content in them. |
| [Twilio Flex](https://help.salted.cx/en/articles/integration-flex) | Support for Twilio Flex (TaskRouter) tasks and agent statuses, contents of Twilio Messaging conversations, and Twilio Studio for IVR engagements. |
| [Webex CC](https://help.salted.cx/en/articles/integration-webex) | Support for Webex CC |
| [Zendesk](https://help.salted.cx/en/articles/integration-zendesk) | Support for Zendesk tickets and chat. |
| [Zingtree](https://help.salted.cx/en/articles/integration-zingtree) | Support for self-service sessions that customers went through. Individual steps customers take through the menu are shown in the customer journey. You can also report on what menu paths the customers often use and whether they are resolving their requests. |



## [](#adding-supported-platform)Adding Supported Platform

Salted CX adds support for contact center platforms based on demand. If your platform is missing in the above list please reach us at <help@salted.cx> to check when we can support your platform.

---

## Users

Source: https://help.salted.cx/en/collections/1755201097-users


Category description here

All users log in to Salted CX via Single Sign On using your identity provider. This centralizes your user management and ensures that you know who has access to Salted CX.

## [](#recommended-requirements)Recommended Requirements

Since Salted CX can store verbatim customer conversations and contact information, ensure your identity provider enforces strict user authentication requirements. We recommend following the latest recommendations based on the [National Institute of Standards and Technology (NIST)](https://pages.nist.gov/800-63-4/sp800-63b.html).

### [](#password-strength)Password Strength

Minimum length of 15 characters (recommend users to use a strange phrase with grammar errors and some extra, missing or duplicate characters that is easy to remember)



If the identity provider supports it, choose to block common or compromised passwords



Do NOT force uppercase letters, number, special characters (change in the latest NIST recommendations)



Do NOT force password changes based on time (change in the latest NIST recommendations)



### [](#multi-factor-authentication-mfa)Multi-Factor Authentication (MFA)

Enable for all users



Require MFA at login



Use device biometrics, authenticator app or hardware key



Do NOT use SMS



### [](#login-protection)Login Protection

Lock out user after 5 failed login attempts



Notify the user on login from new device or new location



### [](#access-control)Access Control

Restrict access from unknown countries



Allow access only from trusted networks if applicable



### [](#monitoring-and-alerts)Monitoring and Alerts

Log and alert on the following activity:

Log login attempts



Suspicious activity (new devices, new countries)



User is locked out

---

## Application Settings

Source: https://help.salted.cx/en/collections/1755185945-application-settings


Category description here

---

## Ingest API

Source: https://help.salted.cx/en/collections/1755273563-ingest-api


Category description here

We provide Ingest API that enables you to enhance existing data in Salted CX with attributes and facts that are important for your business. You can also use the Ingest API to integrate Salted CX with a platform that is not supported out of the box by Salted CX.

## [](#before-you-start)Before You Start

Before you start it is good to have understanding of these topics:

- [Logical Model](https://help.salted.cx/en/collections/1755206106-logical-model) — enables you to understand the data structure expected by Salted CX. The Ingest API expects the data that matches the Logical Model and individual files uploaded to Salted CX represent items in individual data sets.

- [Ingest Data Format](https://help.salted.cx/en/articles/1755247563-ingest-data-format) — enables to understand file naming convention, file format and supported values in the uploaded file.

## [](#get-access-to-ingest-api)Get Access to Ingest API

Access to Ingest API requires these information that you need to ask us via <help@salted.cx>:

- Account ID — UUID that is unique identifier of the customer account and the associated domain

- Secret API Key — long random characters that authorize your code to upload the data

- Source ID — UUID that identifies the data source. We recommend to ask for separate Source IDs if you have multiple implementations that provide data via Ingest API from different sources.

The above information is all you need to upload data to Salted CX. Keep these information is a secure storage such as AWS Secrets Manager or its equivalent in a different infrastructure. Although Only Secret API Key is sensitive we recommend that you do not use any of these in you code and retrieve it via environmental variables or directly from a secrets management service.

## [](#upload-process)Upload Process

The upload process has these steps:

1. Prepare the data into a batch of compressed JSONL files to a single ZIP file. Check [ingest data format](https://help.salted.cx/en/articles/1755247563-ingest-data-format) for details on the format of the JSONL files.

2. Request upload link from the Ingest API. This requires passing the authorization token in the request headers.

```bash
curl --location 'https://api.eu.salted.cx/api/v1/ingest/upload-url' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <Secret API Key>' \
-d '{
          "ingestionSourceId":<Source ID>"
    }'
```

1. Upload the prepared ZIP file from step 1 to the upload link retrieved in step 2 using HTTP PUT method.

```bash
curl --location --request PUT '<Upload link from step 2>' \
--data-binary '@/<Path to ZIP file from step 1>'
```

## [](#uploading-media-for-attachments)Uploading Media for Attachments

Turns can reference attachments such as images, PDFs and other files (for example files attached to emails). If the attachment files are not already stored in an S3 bucket that Salted CX can read (see the Access to Recordings section below), or they are only available behind short-lived URLs or on-premise, you can upload them directly to Salted CX before ingesting the turns that reference them.

The media upload process has these steps:

1. Request a signed upload URL from the Ingest API for each file. Pass the authorization token in the request headers and the MIME type of the file in the body.

```bash
curl --location 'https://api.eu.salted.cx/api/v1/ingest/media/upload-url' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <Secret API Key>' \
-d '{
      "mimeType": "application/pdf"
    }'
```

The response contains the following fields:

- `url` — presigned URL to upload the file to using HTTP PUT.

- `mediaPid` — UUID identifying the media. Use it as the attachment `pid` when ingesting the turn.

- `path` — relative path of the file within your account storage. Use it as the attachment `path` when ingesting the turn.

```json
{
  "url": "https://<presigned-upload-url>",
  "mediaPid": "2e021b2e-c98d-4152-8a6c-34fe39dbcc2c",
  "path": "year=2026/month=03/day=12/2e021b2e-c98d-4152-8a6c-34fe39dbcc2c.pdf"
}
```

1. Upload the file to the presigned URL using HTTP PUT. Set the `Content-Type` header to the same MIME type you requested in step 1.

```bash
curl --location --request PUT '<url from step 1>' \
-H 'Content-Type: application/pdf' \
--data-binary '@/path/to/file.pdf'
```

1. Reference the uploaded media as an attachment of a turn in `turn.jsonl`. Use the returned `mediaPid` as the attachment `pid` and the returned `path` as the attachment `path`. See the Turn section in [Ingest Data Format](https://help.salted.cx/en/articles/1755247563-ingest-data-format) for the full attachment format.

ℹ️

The presigned upload URL is short lived. Request it shortly before uploading the file. You only need to upload a given file once — you can then reference the same `mediaPid`/`path` from multiple turns.





## [](#access-to-recordings)Access to Recordings

If you want users to playback recordings from the customer journey.

Salted CX needs permissions to read the files from S3.

Follow [AWS documentation](https://docs.aws.amazon.com/AmazonS3/latest/userguide/example-bucket-policies.html) to provide S3 folder permissions with Salted CX account.

## [](#best-practices)Best Practices

Use a dedicated account for testing purposes if your integration is not yet thoroughly tested. Currently the API supports only additive changes of data or modification of existing data. In case you need to delete data please reach to use <help@salted.cx>.

## [](#limits)Limits

The API has the following limits:

- Maximum size of a single batch is 1GB

- Maximum number batches per 15 minute is 1,000

- Total data size uploaded in 15 minutes is 10GB

## [](#pricing)Pricing

Adding data using Ingest API influences costs as it creates engagements and other data set items that may impact the overall price for Salted CX.

---

## Metrics

Source: https://help.salted.cx/en/collections/1755184743-metrics


Category description here

Metrics are calculations that calculate a numerical value on top of all engagements and other items in the [Logical Model](https://help.salted.cx/en/collections/1755206106-logical-model).

## [](#built-in-metrics)Built-in Metrics

Salted CX ships with a rich set of built-in metrics that you can use to build your own insights and dashboards. You can also use the built-in metrics to create your own metrics on top of them or as an inspiration to create your own metrics from scratch. The built-in insights and dashboards use the built-in metrics.

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

The set of built-in metrics available in every Salted CX account is the same. However whether the metrics provide results depends on platforms you connected Salted CX to and on additional data you load to Salted CX. Different platform provide different set of data.





Check [Metrics Reference](https://help.salted.cx/en/articles/1755225286-metrics-reference) for list of metrics available out of the box.

## [](#custom-metrics)Custom Metrics

Salted CX contains a metric editor that enables you build your own metrics based on any data point available in [Logical Model](https://help.salted.cx/en/collections/1755206106-logical-model). You can build your own metrics on top of the built-in metrics or create your metrics from scratch. You can use custom metrics to build new insights and dashboards. They offer the same flexibility as the built in metrics.

![](https://media.notiondesk.so/upload/68a70c542234d184656340.png)

---

## Agents

Source: https://help.salted.cx/en/collections/1755203486-agents


Category description here

Agent profile shows overview of a single agent performance. Agent profile collects reviews and coaching sessions associated with one agent.

On the left you have list of all currently active agents. You can use search to search for agents. Users who have restricted access to see only their engagements do not see the navigation. Instead the entire screen shows their profile.

You can use [permissions](https://help.salted.cx/en/articles/permissions) to give access to both team leader and agents to user profile. This enables both to have shared understanding of what is expected from the agent and tracking progress towards any goals.

## [](#agent-attributes)Agent Attributes

You can see key agent attributes on top of the agent profile to understand a bit more about the agent. These are the same attributes as available in [Agent](https://help.salted.cx/en/articles/model-agent) data set. You can use these attributes in reporting to filter or [segment](https://help.salted.cx/en/articles/visualization-segmentation) metrics.

Visible attributes are mostly to understand your organization hierarchy:

- Team in which the agent currently is.

- Department in which the agent team currently is.

- Location in which the agent currently is.

- Organization in which the agent currently is.

- Manager that the agent is associated with so you know who to reach to if you need to discuss anything about the agent.

- Role in which the agent currently. The role enables to categorize agents for example to those who are in on-boarding, personal improvement plan, senior agents, etc.

## [](#reviews)Reviews

Reviews show any review that is associated with any engagement handled by the current agent. You can view the most recent reviews the agent has received to get better view on their quality.

![](https://media.notiondesk.so/upload/68a70c550ef20684818872.png)

You can filter the reviews by the following attributes:

- Type — whether the review is on agent turn, customer turn or the entire engagement.

- Reviewed By — who created the review — Agent, Auto Reviewer, Customer, or Human Reviewer.

- Verification — whether the review got a verification or a dispute in from anyone.

### [](#acknowledge-and-dispute-reviews)Acknowledge and Dispute Reviews

In case the users have permission to acknowledge or dispute reviews they can click on the Not Verified button and acknowledge or dispute individual reviews.

Acknowledging reviews is useful mechanism that ensures explicit confirmation that an agent received the feedback and the feedback was considered accurate.

Disputing reviews is useful safety mechanism that enables agents to push back if they feel the feedback in not fair, or is not accurate. Disputing auto reviews also helps with training materials for auto reviewers that tells them that a given auto review was a false positive which helps to improve the [accuracy of auto reviewer](https://help.salted.cx/en/articles/1755254757-auto-reviews-accuracy).

## [](#coaching)Coaching

Coaching agents is critical for iterative improvements in agent overall performance. Timely and directed feedback makes a huge difference in driving behavior change when necessary and enforcing good practices.

![](https://media.notiondesk.so/upload/68a70c5b310a3810403014.png)

Agent Profile shows the list of the coaching sessions from the most recent. For each coaching session you can see what form was used, the date of the coaching session and who performed the coaching.

To create new coaching you need to have `coaching.session.manage` permission and follow these steps:

- Go to Coaching tab for the given agent

- Press New Coaching button

- Choose a form you would like to use for the coaching session. This will define what questions you will be asked to respond to. You have to have at least one [form created for coaching](https://help.salted.cx/en/articles/forms).

![](https://media.notiondesk.so/upload/68a70c5d5f625033613838.png)

- Answer the questions that are relevant for the coaching session. Note that the answers are saved as you answer even when you do not press Complete and the coaching is marked as in progress.

- Press Complete

---

## Search and Discover

Source: https://help.salted.cx/en/collections/1755269222-search-and-discover


Category description here

Semantic Search finds turns in conversations that happened in up the last 30 days that have similar meanings. Semantic Search uses AI to find turns that have similar meanings even when they do have not a single word in common.

![](https://media.notiondesk.so/upload/698d90f85307a178029324.png)

To use Semantic Search click on the search field in the top right corner of the application. Type the content of a message that you would like to find. Then click Search. Salted CX lists turns where a customer or an agent mentions something similar to what you search for. You need at least two words to

Each turn shows the following information:

- Who is the author of the turn

- When the turn happened

- The color shows whether the turn is a customer, human agent, or a bot turn

You can choose whether you want to search in agent or customer turns or in both.

Click any turn in the search results to open the Customer Journey in which the turn happened.

## [](#supported-languages)Supported Languages

The list of currently supported languages in semantic search in alphabetical order:

Albanian, Arabic, Armenian, Bulgarian, Burmese, Catalan, Croatian, Czech, Danish, Dutch, English, Estonian, Finnish, French, Galician, Georgian, German, Greek, Gujarati, Hebrew, Hindi, Hungarian, Indonesian, Italian, Japanese, Korean, Kurdish, Latvian, Lithuanian, Macedonian, Malay, Marathi, Mongolian, Norwegian Bokmål, Persian, Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovenian, Spanish, Swedish, Thai, Turkish, Ukrainian, Urdu, Vietnamese

The returned results will differ depending on the language combination, how close the languages are and how much training data are available for the individual languages.

---

## Logical Model

Source: https://help.salted.cx/en/collections/1755206106-logical-model


Category description here

A Logical Model is the way the data in Salted CX are organized, making them easy to use for a wide range of analytical needs. The Logical Model is designed to be easy to understand for people without deep technical knowledge. Understanding the logical model is helpful for creating custom metrics, building reports, and designing dashboards.

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

The data available in the Logical Model varies depending on the connected data sources and their configuration. The Logical Model can work perfectly fine if the data are not complete. A subset of metrics will be available.





## [](#data-sets)Data Sets

Data sets represent different kinds of items stored in the logical model. Salted CX uses a limited set of data sets that enable users to quickly navigate in it.

![](https://media.notiondesk.so/upload/68a70c55a5ecf498249477.png)

Each data set has a set of attributes, facts, and references to related data sets.

| Entity | Description |
|---|---|
| [Activity](https://help.salted.cx/en/articles/model-activity) | Detailed break down of agent load and activity. |
| [Agent](https://help.salted.cx/en/articles/model-agent) | The person or a service that interacts with customers on behalf of the company. Each engagement is associated with one agent. |
| [Customer](https://help.salted.cx/en/articles/model-customer) | The person that the company engages with during the conversation. We recommend that all engagements in a single conversation be associated with a single customer although it is technically possible to have conversation where multiple customers are involved. |
| [Engagement](https://help.salted.cx/en/articles/model-engagement) | Individual engagements between agents and customers. Multiple engagements can be grouped into one conversation. |
| [External Agent](https://help.salted.cx/en/articles/model-external-agent) | Person or an organization outside of your company that can engage with the customers in the conversations. |
| [Question](https://help.salted.cx/en/articles/model-question) | Question that was answered in a review. |
| [Review](https://help.salted.cx/en/articles/model-review) | Review represents individual responses, comments and tags associated with Engagements. Reviews contain feedback from customers, agents, reviewers and automatic reviews. |
| [Reviewer](https://help.salted.cx/en/articles/model-reviewer) | Person or a service that provides Reviews for Engagements. |
| [Service](https://help.salted.cx/en/articles/model-service) | Service (or product) primarily associated with the conversation. This dataset enables you to attribute conversations to specific, products and eventually partners on whose behalf you engage in conversations with customer. |
| [Transaction](https://help.salted.cx/en/articles/model-transaction) | Transactions that happened during this engagements. Transactions can have associated revenue and costs to enable reporting on financial aspects of the engagements. There can be multiple transactions for a single Engagement. |
| [Turn](https://help.salted.cx/en/articles/model-turn) | Granular breakdown of individual engagements. Turns represent different events in different types of engagements. In messaging they represent a single message sent by a participant, in voice conversation, they represent a single talk by one of the participants, in menu engagements they represent individual menu steps, etc. Turns are not available for reporting. They are visible in the customer journey. |



## [](#attributes)Attributes

An Attribute is a property of a Data Set that can be used for segmentation and filtering of data visible in the reports and dashboards.

![](https://www.notion.so/icons/warning_yellow.svg?mode=light)

Attribute and label values are limited to 100 characters. If an attribute or label value is longer than 100 characters, the value is trimmed. Whenever a value is trimmed, the event is reported to the Technical Log as a warning. We recommend monitoring trimmed values, as they may lead to skewed reporting. If multiple values share the same first 100 characters and differ only after those characters, segmenting by such attributes will merge metrics from these two distinct values into a single segment.





## [](#enumerations)Enumerations

Enumerations are special types of attributes that can contain only values allowed by Salted CX. Unsupported values cause the data to fail to load using our [Ingest API](https://help.salted.cx/en/collections/1755273563-ingest-api).

## [](#entities)Entities

Entities are very simple Data Sets. Unlike Data Sets, they have only one [attribute](https://help.salted.cx/en/collections/1755206106-logical-model?v=24f5d3a2a8dc81f49249000c3e502787#2565d3a2a8dc80b4a012f2965acc2b09) with two labels and no [facts](https://help.salted.cx/en/collections/1755206106-logical-model?v=24f5d3a2a8dc81f49249000c3e502787#2565d3a2a8dc80189ad1cb926fd85828). Every entity has the same set of one attribute and two [labels](https://help.salted.cx/en/collections/1755206106-logical-model?v=24f5d3a2a8dc81f49249000c3e502787#2565d3a2a8dc801684edeb3e8e714fb3) for that attribute.

| Property | Type | Description |
|---|---|---|
| &lt;Entity Name&gt; | [PID](https://help.salted.cx/en/collections/1755206106-logical-model?v=24f5d3a2a8dc81f49249000c3e502787#2565d3a2a8dc8010b907f9c8aeac496e) | Permanent identifier generated by Salted CX and uniquely identified the item. The PID cannot be changed after the entity is created. |
| &lt;Entity Name&gt; ID | Label for &lt;Entity Name&gt; | ID that the entity has in a third-party system. Salted CX does not enforce any format for the ID. The ID has to fit into 100 characters as attributes have to. |
| &lt;Entity Name&gt; Name | Label for &lt;Entity Name&gt; | Name that is the default representation of the entity in the user interface. The name should be easy for users to read and understand. The name is also limited to 100 characters. |



Entities enable you to have a unique representation of important items in the contact center, with a human-friendly visualization. Entities also enable you to easily rename the items without breaking relationships between important data points.

![](https://media.notiondesk.so/upload/698d90e13a9d2117551890.png)Entity properties available when building a visualization

## [](#pid)PID

Each item in a dataset and every entity has a unique Permanent Identifier (PID). PID is a special type of attribute. PID is always a [UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier) that is either generated randomly or deterministically based on identifiers in the connected platform. Once a PID is generated for an item, it cannot be changed in the future.

## [](#labels)Labels

Labels are alternative visualizations for attributes. While you might use a hard-to-read value that you are certain is unique as an attribute value, the unique value may be very inconvenient for end users to read.

There might be two items with the same label but different underlying attribute values. If such a label is used in insights, you will see two different segments with the same name and different metric values.

![](https://www.notion.so/icons/warning_yellow.svg?mode=light)

Similarly to attributes, the label values are limited to 100 characters. If a label value exceeds 100 characters, it is trimmed. Whenever a value is trimmed, the event is reported to the Technical Log as a warning. Since labels are not directly used for segmentation and filtering, the trimmed labels have a lesser impact on data correctness. However, if there are two labels that have the same first 100 characters, the insights may be misleading - for example, you can see twice the same label value or accidentally filter for a different value.





## [](#facts)Facts

A Fact is a numeric value in the Logical Model. Facts can be used for arithmetic operations, aggregated, and ultimately form the foundation for creating metrics.

Metrics cannot be used for filtering in insights and dashboards. However, you can use fact values in metric filtering conditions.

![](https://www.notion.so/icons/warning_yellow.svg?mode=light)

When you load custom data and provide a non-numeric value where a fact is expected, the value is ignored and the event is reported in the Technical Log as a warning. The number in quotes is also not considered a fact.





## [](#date-time-and-duration)Date, Time, and Duration

All dates and times in the logical model have one-minute granularity. There are multiple dates and times in the Logical Model.

All durations in the logical model are in seconds.

## [](#technical-items-in-data-sets)Technical items in data sets

Some data sets have technical values. Technical values have an attribute `Type` set to value `Technical`. You can use this attribute to filter the technical items in the data sets.

Technical items are stored by default in the Agent, Customer, and Engagement data sets.

# [](#data-not-in-logical-model)Data not in logical model

The logical model does not contain the following data:

- Conversation content, such as transcripts or voice recordings. It may, however, contain metadata extracted from the content, such as discussed topics, sentiment, and other features extracted from the content. The content is stored separately and displayed only when users drill down to the [customer journey](https://help.salted.cx/en/collections/1755250527-customer-journey) and have permission to view the conversation content.

- Customer's personally identifiable data. Customer's personally identifiable data is removed and replaced by identifiers from the customer profile. We do not expose personally identifiable information in analytics or in the [customer journey](https://help.salted.cx/en/collections/1755250527-customer-journey). To display personal identifiable information, the user must have a dedicated permission and click on a specific masked value to view it.

![](https://www.notion.so/icons/warning_yellow.svg?mode=light)

Technically, you can provide pieces of conversation content and personally identifiable data in attributes and labels when loading custom data to Salted CX. However, we strongly discourage you from doing that as it bypasses compliance enforcement in Salted CX.

---

## Customer Journey

Source: https://help.salted.cx/en/collections/1755250527-customer-journey


Category description here

Customer Journey provides a view of all conversations with a customer from the first to the last engagement the customer had with you. Customer Journey enables you to better understand the end-to-end experience of your customers, your products, and services they use.

![](https://media.notiondesk.so/upload/698d90a020c56719200530.png)

Customer Journey view is split into 3 vertical scrollable panes from left to right:

- [Navigation Pane](https://help.salted.cx/en/collections/1755250527-customer-journey?v=24f5d3a2a8dc81f49249000c3e502787#2565d3a2a8dc80baaf6adca55352ad59) ❶ — High-level overview of the Customer Journey that helps to understand how often the customer contacts you, by using what channels, and what was outcome of the conversations. Useful for navigation in the entire customer experience.

- [Conversations Pane](https://help.salted.cx/en/collections/1755250527-customer-journey?v=24f5d3a2a8dc81f49249000c3e502787#2565d3a2a8dc8093bdafdffad9854039) ❷ — Detailed view of individual engagements including their content — transcripts. Useful for uncovering root causes behind issues and identifying opportunities.

- [Action Pane](https://help.salted.cx/en/collections/1755250527-customer-journey?v=24f5d3a2a8dc81f49249000c3e502787#2565d3a2a8dc80f98ef4f8f47111344e) ❸ — Pane that enables you to work with findings in the Conversation Pane.

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

The number of engagements in a single customer journey is limited to the 500 most recent.





## [](#navigation-pane)Navigation Pane

The leftmost pane shows all Conversations and Engagements on the high level.

- The empty channel symbol represents an Engagement handled without human intervention.

- The full channel symbol represents an Engagement handled by a human.

Click any Engagement in the Customer Journey pane and the Conversations Pane scrolls to the point in the Customer Journey that you clicked.

Scroll the pane if there are many Conversations and Engagements with the customer.

### [](#conversations)Conversations

Each conversation win Customer Journey begins with the date when the conversation started and an icon indicating the conversation direction. Individual Conversations are split by a separator.

Each conversation lists engagements that happened in it. Each engagement shows its channel, queue (or agent if the queue name is not available), and the outcome (disposition code, wrap-up code) of the engagement.

Overview Pane shows a thin bar on the left side indicating which conversations are visible in the Conversations Pane. This simplifies navigation and understanding of the customer journey if the customer journey is long.

## [](#conversations-pane)Conversations Pane

The middle Conversations Pane shows detailed contents of all conversations with one customer. The customer journey is broken down into individual conversations sorted by the time when the conversations started. The oldest conversations are on top and the most recent conversations are at the bottom. If two conversations overlap then there is a small notification that another conversation started. You can click the notification to scroll to that conversation.

### [](#engagements)Engagements

Each conversation shows all agent engagements within that conversation. If there are multiple engagements in a single conversation — for example, two agents talk to the customer — the turns within the engagements are sorted chronologically so when multiple agents are talking to the customer you understand the flow of the conversation.

![](https://media.notiondesk.so/upload/698d90a315118581457578.png)

When a new engagement start customer journey shows who joined the conversation, the start time of the engagement, whether they are some reviews. You can also Ask about anything related to the engagement.

More details in article [Engagements in Customer Journey](https://help.salted.cx/en/articles/customer-journey-engagement).

### [](#turns)Turns

Turns represent a single message or action of participants in the conversation. The turns have colors depending on who performed them. Customers turns are green, human agents are blue and bot turns are purple.

On top of each turn you can see the following information:

- The channel is represented by an icon. As you can have multiple channels mixed in a single conversation the icon helps you identify what channel was used for that specific turn.

- Participant name which is either the agent name, bot name, or “Customer”. We do not show the customer's name or contact details to limit the exposure of the customer's personal information.

- Response time to the previous messages from another participant.

If there are multiple turns from the same participant within one minute they are grouped and do not contain repeat the above information.

![](https://media.notiondesk.so/upload/698d90a590492426781039.png)Example messages in Conversation Pane

## [](#action-pane)Action Pane

Action Pane provides a set of additional information and tools regarding the current customer journey and your selection.

### [](#prompting)Prompting

You can use prompting to ask any question about the selected engagement and chose from a concise or detailed answer. The last entered prompt is remembered so once you select a different engagement it will be automatically executed.

### [](#forms)Forms

This panel allows you to select a form created in the [Forms](https://help.salted.cx/en/articles/forms) editor. Each form has a property that designates if it can be displayed on the level of engagement, customer turn, agent turn or bot turn.

### [](#reviews)Reviews

Reviews enable you to view and provide your feedback for individual turns and entire engagements. For reviews generated by humans, you can provide feedback if you approve or dispute them. For AI generated reviews you can provide feedback if they are correct, incorrect or unclear.

### [](#similar-turns)Similar Turns

Displays turns in the conversations that are semantical similar. See more in [Similar Turns](https://help.salted.cx/en/articles/customer-journey-similar-turns).

---

## Visualizations

Source: https://help.salted.cx/en/collections/1755248079-visualizations


Category description here

Visualization are individual charts and tables. You can view the visualizations individually or you can put more of them into one [dashboard](https://help.salted.cx/en/collections/1755268670-dashboards). Visualizations enable you to browse charts and tables people have already created in your account and also [create a new visualization](https://help.salted.cx/en/articles/visualizations-custom).

![](https://media.notiondesk.so/upload/698b11605e72e814565655.png)

## [](#navigation)Navigation

On the left hand you have listed all the visualizations available in your account. You can use search ![:r1:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/cbece7ea-90d1-42be-b944-7d3a40472c0a/Circle_1.png) to search for visualizations by their name.

The visualizations are organized into these sections:

- Favorites ![:r2:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/828ec6f6-6da7-41e1-ab7d-81f376318b90/Circle_2.png) contain visualizations that you have marked as favorite using the star icon ![:r7:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/9e5e9e5f-9b80-4656-8d16-a78ef863eb57/Circle_7.png) in the toolbar. Favorites are individual for you and each use can have their own favorites.

- Shared ![:r3:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/6a0e6eb2-4742-4445-80a6-8be77bab104f/Circle_3.png) contain visualizations that were created by all users in your account.

- Salted CX ![:r4:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/49964e58-e0e9-40b5-b973-00c416e5d0bc/Circle_4.png) contain visualizations that are available out of the box with the Salted CX account.

You can create [your own visualization](https://help.salted.cx/en/articles/visualizations-custom) by pressing the New Visualization button ![:r5:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/a8d7fc85-01c2-4beb-ae57-18073a27a40e/Circle_5.png).

As all items in Salted CX each visualization has its unique web address. You can easily copy the address from the browser URL and send it to your colleagues so they can have a look on the visualization.

## [](#built-in-visualizations)Built-in Visualizations

You cannot edit nor delete built-in visualizations. You can use these visualizations to build [custom dashboards](https://help.salted.cx/en/articles/dashboards-custom) or use filters ![:r9:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/72b59471-92ba-446c-94f7-8d19849cfc6a/Circle_9.png) to focus on specific data. You can use all the view-only features depending on the visualization shows including [Ask](https://help.salted.cx/en/collections/1755248079-visualizations#2575d3a2a8dc80258f5cc37b3d8e5c9d) and [drill downs](https://help.salted.cx/en/collections/1755248079-visualizations#2575d3a2a8dc8003801efcee1edacb81) to the customer journey.

Press Save as new ![:r8:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/bd34cd7e-cbac-4650-9d97-2a4412a47520/Circle_8.png) to create your own visualization based on the built-in one. This enables you to use the built-in visualization as a starting point and modify it to better suit your business needs.

## [](#custom-visualizations)Custom Visualizations

Visualizations created by users in your account are automatically available to other users. Users with edit permission can also edit these visualizations.

![](https://media.notiondesk.so/upload/698b1163a27e2165219289.png)

Press Edit ![:r11:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/3ee86a8a-caf2-477b-accb-27c2e2a315ea/Circle_11.png) button to open the [visualization for editing](https://help.salted.cx/en/articles/visualizations-custom). For custom visualizations you can still create a copy with Save as new ![:r8:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/bd34cd7e-cbac-4650-9d97-2a4412a47520/Circle_8.png) option in the menu if you want to keep the current visualization intact.

You can delete the visualization by pressing the Delete ![:r14:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/6ffa2e34-8d07-42f5-a33e-f3cdb7891ba5/Circle_14.png) menu item.

## [](#drill-downs)Drill Downs

If any visualization contains individual customers, contacts, conversations, engagements, reviews or transactions you can click on the given item to open [customer journey](https://help.salted.cx/en/collections/1755250527-customer-journey) related to it. This enables you to quickly explore root causes behind different issues.

If any visualization contains list of individual agents you can click them to open their [agent profile](https://help.salted.cx/en/collections/1755203486-agents).

## [](#ask)Ask

If any visualization contains list of individual engagements or reviews you can click Ask about engagements ![:r10:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/39cc41d0-405c-4a91-bb9a-f1c584d8fb1a/Circle_10.png) or Ask about reviews button to ask questions about the content of the conversations or contents about the customer reviews.

## [](#save-selection)Save Selection

If any visualization contains list of individual engagements or reviews you can click Save engagements as selection ![:r13:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/ecf5bec7-0640-4f5a-928c-0f89d29f37ba/Circle_13.png) or Save reviews as selection. Saved selection enables you to store the list of engagements that are currently listed in the visualization (matching filtering criteria at the time when you save them) for later use.

![](https://media.notiondesk.so/upload/698b1166a8ee0301958581.png)

You can use selections to have a sample of conversations for training, testing automatic QA, etc.

---

## Dashboards

Source: https://help.salted.cx/en/collections/1755268670-dashboards


Category description here

Dashboards allow users to combine multiple visualizations on a single canvas and view them from various perspectives.

## [](#built-in-dashboards-filters)Built-in Dashboards Filters

Dashboards contain filters to focus report only on specific subset of engagements. Filters influence every visualization in the dashboard and override the filters on visualizations level.

Use filters to focus on specific set of teams, agents, conversations and reviews. Filters help you work on the specific subset of your contact center traffic that is the most relevant for you.

![](https://media.notiondesk.so/upload/698b115bb8616636106242.png)

On most dashboards these are the filters:

- Date. The date filter for when the engagements started.

- Source. The connected system or platform that the engagements are extracted from.

- Location. The location associated with the engagements.

- Direction. The direction of the conversations enables to choose whether you focus on Inbound, Outbound or Internal conversation.

- Channel. The communication channel of the engagements.

- Engaged Department. Department in which the agent was when engaged in the conversation.

- Queue. In which the customer was waiting before engaging with the agent.

- Engaged Team. Team in which the agent was when they engaged in the conversation.

- Agent. Agent engaged in the conversation.

- Outcome. Outcome of the engagement, often called disposition or wrap up code.

Some dashboards can contain different set of filters if they make sense for the use case the dashboards are intended for.

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

You cannot customize filters on the built-in dashboards. To use different filters create your own copy of the dashboard. Learn more about [Custom Dashboards](https://help.salted.cx/en/articles/dashboards-custom)





### [](#hidden-filters)Hidden Filters

Some dashboards may have hidden filters that influence the visualizations in that dashboards. Hidden filters can be used to focus the dashboard on the subset of data it is intended to be used for and avoid misinterpretation of the data. Hidden filters are a convenience feature, not a security feature.

### [](#locked-filters)Locked Filters

Locked filters are similar to hidden filters in that they are applied to the dashboard and cannot be changed. However these filters are

### [](#reset-filters)Reset Filters

You can click the reset filters button to set the filters to their default values for the current dashboard. This enables you to quickly start any of your explorations from the start again.

## [](#dashboard-views)Dashboard Views

You can save the current filters in dashboards for later use using saved views. This is useful to have dashboards filtered to what is the most important for each user. For example this can be their team, their department, agents that need more help, etc.

Each user has their own views. Views created by one user is not visible by other users.

### [](#save-filters)Save Filters

When you want to save your current filters:

1. Click My views in the top right corner of the dashboard

![](https://media.notiondesk.so/upload/698b115f35d74760955123.png)

1. Click Create view in the menu

2. Name your saved view so it is easy to remember what data it shows

![](https://media.notiondesk.so/upload/698b116256494835617939.png)

1. Check Save as default, if you want the newly created svaed view to be used by default when you open the dashboard

2. Click Save

From this point you can easily return to your filtering criteria with just two clicks.

### [](#use-saved-views)Use Saved Views

To load the saved filters:

1. Click My views

![](https://media.notiondesk.so/upload/698b116549a4e482542131.png)

1. Click any of the saved views in the menu

To choose which saved view is used by default when you visit the dashboard, click ❸ Set as default option that appears when you move pointer over the menu item.

To delete any saved view, click ❹ trash icon that appears when you move pointer over the menu item.

## [](#drill-downs)Drill Downs

The dashboards are interactive. You can click attributes and metrics in charts and tables to explore them further. Items that you can click are bold. When you click these items they can either take you to a specific dashboard or to [Customer Journey](https://help.salted.cx/en/collections/1755250527-customer-journey).

You can also add drill-downs to your custom dashboards. Learn more about [Drill Down from Dashboards](https://help.salted.cx/en/articles/dashboards-drill-down).

---

## Quality Assurance

Source: https://help.salted.cx/en/collections/1755201479-quality-assurance


Evaluate and improve customer service delivered by human agents, AI agents, and mixed human-AI workflows.

Quality Intelligence in Salted evaluates and improves customer service delivered by human agents, AI agents, and mixed human-AI workflows. Salted supports automated and manual reviews, configurable criteria, human verification, agent feedback, coaching, and conversation-level evidence.

AI can evaluate large volumes of eligible conversations while people acknowledge, dispute, or clarify individual findings. That human feedback helps align automated evaluation with business expectations and reveals changes needed in coaching, knowledge, policy, routing, workflows, or customer-facing automation.

## [](#more-reviews-that-matter)More Reviews that Matter

To get the most value from the time and effort you invest in reviews you have two high-level options:

- Focus on more interesting conversations. Reviewing these conversations is more likely to lead to actionable findings. You do this by selecting some criteria detected from metadata and content.

- Review more conversations. Spend less time on an individual conversation to maximize conversations reviewed per unit of time.

![](https://media.notiondesk.so/upload/68a70c6d53b96661548312.png)The example, how focus on conversations and speed helps to process more actionable conversations

The exact ratio between a number of actionable findings between the random sample reviews and reviews on focused and fast reviews depends on multiple factors:

- The percentage of actionable conversations out of total volume.

The table below contains the comparison of random sampling and focused reviews:

|  | Opportunity Discovery Approach | Random Sample Legacy Quality Assurance |
|---|---|---|
| Primary Goals | Discover opportunities how to improve key business metrics often with collaboration by other departments in the company. | Provide agents with a fair assessment of their performance that can be used to decide for calculating compensation and even make career decisions. Provide performance reports to a 3rd party or higher management to monitor how the contact center is doing. |
| Integration with AI | Quality Assurance captures focused examples that can be used to refine and validate the configured prompts and knowledge supporting automated reviews. | Engagement-wide feedback is less useful for refining automated reviews because it does not identify which part of the conversation caused the finding. This limitation becomes more significant for longer engagements. |
| Main Advantages | Focuses on resolving issues and uncovering opportunities that have the highest impact on the company's performance. A high ratio of reviewed conversations contains interesting moments you can act on. | Provides a benchmark value for a performance based on human feedback. |
| Main Disadvantages | Does not provide a fair assessment of agents’ performance. Depending on whether you focus on problems or highlights it can create a very skewed perception of performance. Requires constant changes to reflect the changing business goals and external factors. | Low number of reviewed conversations. A low percentage of actionable findings out of reviewed conversations (as in a well-managed contact center most conversations are OK). Sometimes it is hard to keep the customer perspective aligned with the watched quality score (for example quality scores are high while customer satisfaction is low). |
| Percentage of manually reviewed conversations | Typically around 5%. Depends on specific use case. | Typically around 1%. Depends on the duration/length of the conversations and complexity of the form used for reviews. |
| Choosing Conversations for Review | Conversations that are outliers in key metrics including but are not limited to customer satisfaction, engagement time, wrap-up time, etc. Conversations that were automatically reviewed by Salted CX AI and were tagged with a tag that indicates some behavior worth somebody’s attention. Conversations that contain specific content based on ad hoc [Semantic Search](https://help.salted.cx/en/collections/1755269222-search-and-discover). | Random sample. |
| Manual review process | Read through conversations in [Customer Journey](https://help.salted.cx/en/collections/1755250527-customer-journey) and use feedback forms to annotate turns and engagements whenever you find something worth attention. | Answer questions in a form by browsing a skimming conversations over and over. |
| Steps after the manual review | All the results are visible in dashboards within the next 15 minutes automatically. People who requested the review can take action on those review results. | Sharing quality score with management to keep track of the key quality identifiers. |



## [](#reviewing-conversations)Reviewing Conversations

Users review conversations based on findings.

![](https://media.notiondesk.so/upload/68a70c7122c07873311513.png)

## [](#how-to-manually-review-turns-and-engagements)How to Manually Review Turns and Engagements

After you drilled down to a customer journey.

- Navigate to the part of the customer journey that is relevant for your review. Drill-down from a dashboard often leads to a specific conversation or engagement. Discovery using [Semantic Search](https://help.salted.cx/en/collections/1755269222-search-and-discover) leads to a specific turn. You can use the summary on the left side to focus on conversations happening in a time frame you are interested in. You do not often need to review a complete customer journey.

- Read through the part of the customer journey relevant for your review. Whenever you find anything worth your attention. Use the Feedback panel on the right to tag it with a given behavior. Choose the best form for your review. You can use different forms for customer, agent, and bot turns and Salted CX remembers the choice for individual turns separately.

![](https://media.notiondesk.so/upload/698d91330de57037476327.png)

- You can use the Reviewed tag to mark the engagement as completely reviewed at the end.

Useful tags for general use:

Bookmark — marks the current turn or conversation for later use. So it is easy to discover.

Reviewed — marks entire engagement as reviewed in reports, counts toward coverage of agent engagements that were reviewed. Use this tag to show that you went through the entire engagement to make sure nothing important slips.

See the full list of [built-in tags and questions](https://help.salted.cx/en/articles/questions-built-in).

## [](#tags-and-questions-for-your-business)Tags and Questions for Your Business

Salted CX provides a rich set of [built-in tags and questions](https://help.salted.cx/en/articles/questions-built-in) that try to cover common use cases. These provide a great starting point.

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

Contact Salted CX to create tags and questions for you. This step cannot currently be done directly in the application.





## [](#auto-reviews)Auto Reviews

Auto reviews are similar to reviews people can provide in our Customer Journey using the feedback pane. However, auto reviews are provided by AI. They can also be associated with a specific turn

Auto reviews analyze 100% of conversations and attach reviews to them. These reviews are easy to distinguish from reviews provided by people. You can report on them and you can see them in our [Customer Journey](https://help.salted.cx/en/collections/1755250527-customer-journey).

How are auto-reviews useful:

- Watch the number of conversations that contain certain behaviors over time. Making sure the number grows (for positive tags) or declines (for negative tags).

- Identify agents, teams, or other clusters of conversations that contain unwanted behavior to have a look at the root cause.

- List conversations that have tags or a combination of tags for review by a person. For example, you might use auto reviews to find places where customers are unhappy and you want to walk through those conversations to learn what are the reasons and categorize those.

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

Contact Salted CX to start auto-reviewing using a specific tag. This step cannot currently be done directly in the application.





![](https://www.notion.so/icons/warning_yellow.svg?mode=light)

The accuracy of auto reviews depends on the use case and the clarity of the configured prompts, knowledge, criteria, and manual-review examples. These materials may be refined to improve future reviews, but customer data is not used to train or fine-tune the underlying AI models.

---

## Your Logic

Source: https://help.salted.cx/en/collections/1755764337-your-logic


Configuration and technical reference for Your Logic, Salted's name for the automation interface that receives conversation events and returns actions.

In Salted configuration and technical documentation, the automation interface connected to a customer conversation is called Your Logic. Salted sends ordered conversation events to the configured Your Logic implementation. Your Logic returns the actions Salted should perform.

The underlying automation logic can combine code, AI, business rules, workflow tools, and internal systems. Your Logic is the exact configuration and technical name for that interface, not a separate Salted product, platform, or framework.

Typical use cases for Your Logic:

- Operate a customer-facing AI agent grounded in your knowledge and policies

- Query and update internal systems, perform permitted actions, and report the result to the customer

- Ask a human agent for guidance or approval before a consequential action

- Route conversations and set priority, reason, outcome, customer attributes, or external case references

- Provide human agents with suggested replies, information panels, notes, and contextual actions

- Invite an external expert or partner into a selected conversation

- Keep context while a human is involved and continue after the human contribution ends

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

You can use only one endpoint for Your Logic. In case you have multiple services that need to receive events from Your Logic you have to implement this distribution mechanism into Your Logic endpoint.





![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

Only communication that happens via Salted CX Live Conversations integrates with Your Logic. You cannot connect Your Logic to conversations that we ingest from 3rd party systems into analytics.





## [](#high-level-architecture)High-Level Architecture

Your Logic plugs into the Conversation Management that notifies you about important events. Your Logic tells us what we should do next.

![](https://media.notiondesk.so/upload/68d3d964d0a32274299279.png)

## [](#separation-of-concerns)Separation of Concerns

What Salted CX does for you:

- Connection to multiple channels such as web chat, WhatsApp, etc.

- Unification of multiple channels to a unified format

- Queue events in individual conversations so Your Logic can tackle them one by one

- Preprocessing of messages — language detection, translation, etc.

- Keeping conversation context data

- Fallback in case Your Logic is unresponsive

- Escalation to agents in Live Conversations

What you SHOULD do:

- Integrate with your systems in Your Logic to obtain data and perform actions

- Use Salted CX protocol ([requests](https://help.salted.cx/en/articles/your-logic-requests), [responses](https://help.salted.cx/en/articles/your-logic-actions)) process received events from Salted CX

- Scale Your Logic to handle the expected volume of conversations and respond within set timeouts

![](https://www.notion.so/icons/warning_yellow.svg?mode=light)

Your Logic has to be able to handle multiple parallel conversations from the same customer. While we ensure that we will sequence all requests for individual conversations, we do not sequence requests for customers. Customers can be involved in multiple conversations by simply emailing you and chatting at the same time. This may impact you when modifying customer-related data in your system. One conversation can update customer information that may influence other conversations.





## [](#prerequisites)Prerequisites

Contact Salted CX to get Your Logic ready for your account:

- Provide Salted CX with your Salted CX account domain and endpoint that should receive requests from Your Logic

- Get Shared Secret from Salted CX that enables you to verify requests sent to your endpoint are authentic and authenticate your responses

## [](#your-logic-tech-stack)Your Logic Tech Stack

Salted CX does not force you into adopting any specific tools, technology, infrastructure nor programming language for Your Logic implementation. We define and enforce the communication protocol between Salted CX and Your Logic. You can choose your preferred technological stack to implement Your Logic to take advantage of the people and skills you already have in your company.

You have many solutions to pick from, including but not limited to:

- NodeJS server — provides ultimate flexibility as you can code in any behavior that you want. You can use AWS Lambda or Kubernetes to enable Your Logic to scale.

- [n8n](https://n8n.io/) — universal workflow editor with large community and large set of built-in integrations.

## [](#authorization)Authorization

Salted CX uses shared secret authorization to ensure both sides can verify that the HTTP communication is sent by their counterparty.

### [](#ip-addresses)IP Addresses

Salted CX sends all Your Logic events from the following IP addresses:

```java
52.19.189.176/32
52.208.82.70/32
99.81.60.250/32
```

### [](#authorization-of-your-logic-requests)Authorization of Your Logic Requests

You can check that requests are sent from Salted CX by checking the Authorization header in every HTTP request for the shared secret. You SHOULD not process requests that lack a header or have an unexpected value.

```plain
Authorization: Bearer <shared secret>
```

### [](#authorization-of-your-logic-responses)Authorization of Your Logic Responses

Your Logic implementation sends the request to `https://api.eu.salted.cx/api/v1/live/your-logic` endpoint that contains account ID and conversation PID.

```plain
https://api.eu.salted.cx/api/v1/live/your-logic/accounts/{accountId}/conversations/{conversationPid}
```

Each call to this endpoint MUST contain shared secret in the `Authorization` header. Each response that does not contain the header or contains unexpected value is ignored and no action is taken.

```plain
Authorization: Bearer <shared secret>
```

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

Reach to Salted CX to retrieve the token for your account.









## [](#requests-from-salted)Requests from Salted

Whenever an action happens in a conversation, Salted CX notifies you on your webhook. Salted CX sequences requests for individual conversations so you have time to respond. Each event, such as a sent message, goes through multiple stages when processed by Salted CX before it is shown to the other participants. Your Logic receives requests from one conversation in sequential order. Your Logic waits for Your Logic to respond to a request before sending another.

![](https://media.notiondesk.so/upload/68d3d97122707378764617.png)

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

Actions returned by Your Logic do not cause subsequent calls to Your Logic. They are directly shown to all participants. Post-processing may involve translation and other operations necessary.





Your Logic SHOULD send at most one response to one request. First response is accepted, all subsequent responses to the same request are ignored.

Activity Your Logic does not receive notifications about:

- Typing (and similar activity) indicators

## [](#action-stages)Action Stages

Each action, such as sending a message, undergoes multiple stages from the moment it is performed by a participant until it becomes visible to other participants. The following table describes the stages in chronological order.

| Action Stage | Description |
|---|---|
| Action Stored | Salted CX received the action from a participant. The action is visible only to that original participant. Nobody else can see effect of the action (for example a message). |
| Preprocessing | Salted CX processes the captured action and tries to provide Your Logic with the best possible input. The exact processing depends on action type. For messaging the pre-processing includes language detection and language translation. |
| Ready for Your Logic | Salted CX is ready to send the information about the action to Your Logic. In case there is no request related to this conversation in Your Logic Salted CX sends the request with this action to Your Logic. If Your Logic is still processing a previous request related to the conversation the action is send after Your Logic responds together with other actions. See [Asynchronous Behavior in Your Logic](https://help.salted.cx/en/articles/your-logic-asynchronous) for more details. |
| Post-processing | Salted CX executes actions that Your Logic returned in its [response](https://help.salted.cx/en/articles/your-logic-actions). Part of the execution of the actions may be additional processing such as translation of messages to the customer language. At the end of this stage Salted CX can send to Your Logic a next request related to the conversation. |
| Ready for Participants | Salted CX shows the effect of the action (for example a message) to other participants. |



## [](#error-handling)Error Handling

We ensure fallback in case Your Logic is not available due to network error, the service is down or the service is too slow to respond. The fallback ensures the stability of the infrastructure and maintain certain level of service for your customers.

![](https://www.notion.so/icons/warning_yellow.svg?mode=light)

Common fallback action for messaging conversations is to ask human agents for help. Depending on the volume of your conversations this may be overwhelming for them and people might not be able to provide the same response times and quality of service under such load.





### [](#your-logic-is-not-available)Your Logic is Not Available

In case an event happens and Your Logic is not available we resort to performing a default action that would be done as if Your Logic was not setup at all. If the conversation has no engaged human agent then we mark the conversation with Needs Help flag which makes it appear in agents Live screen in Salted CX. The messages between participants continue to function normally.

### [](#your-logic-returns-an-error)Your Logic Returns an Error

If Your Logic returns an error we behave as if Your Logic was not available.

Possible errors handled by Salted CX:

- When calling your web hook Your Logic returns HTTPS response code outside of 2xx range

- Your Logic responds in unsupported format, corrupted file, etc.

### [](#your-logic-is-too-slow)Your Logic is Too Slow

If Your Logic does not respond in timeout in settings we behave also as if Your Logic was not available. Each request from Salted CX contains an expiration time in UTC that lets you know how much time Your Logic has to respond.

Salted CX may have additional grace period to accommodate for network delay and other potential issues. So it is possible that even responses after the timeout get accepted but there is no extra guarantee beyond the timeout. You can adjust the timeout in settings. We recommend to set the timeout as low as possible but with enough buffer for spikes during normal operations.

## [](#one-your-logic-per-account)One Your Logic per Account

You can have only one Your Logic webhook endpoint per account. We do not support calling multiple web hooks. In case you need to send [requests](https://help.salted.cx/en/articles/your-logic-requests) from Salted CX to multiple destinations, you have to implement this behavior in Your Logic.

## [](#additional-resources)Additional Resources

[Your Logic Requests](https://help.salted.cx/en/articles/your-logic-requests) — what you will receive from Salted CX

[Your Logic Responses](https://help.salted.cx/en/articles/your-logic-actions) — what you should send to Salted CX as a response to the requests

[Your Logic Data](https://help.salted.cx/en/articles/your-logic-response-examples) — what data are exchanged during Your Logic

[Asynchronous Behavior in Your Logic](https://help.salted.cx/en/articles/your-logic-asynchronous) — how to work with asynchronous communication

[Your Logic Implementation Tips](https://help.salted.cx/en/articles/your-logic-implementation-tips) — some tips on how to make Your Logic behave in a customer-friendly way

---

## Live Conversations

Source: https://help.salted.cx/en/collections/1755577083-live-conversations


Environment where AI agents, human agents, and external experts operate active customer conversations together.

Live Conversations is the environment where AI agents, human agents, and external experts operate active customer conversations together. It is not only the interface people see. Behind the interface, it coordinates conversation state, participants, routing, engagements, events, actions, handoffs, joining, leaving, and channel behavior.

AI can resolve eligible requests autonomously, ask a human for a bounded decision, invite a specialist, hand over when needed, or continue after human involvement. Human agents use the same conversation history and customer context rather than receiving a cold transfer. Authorized supervisors can also monitor ongoing AI-led conversations, open them without joining, and proactively join or take over customer communication when intervention is needed.

In this documentation, a live conversation is one active customer interaction. Live Conversations is the Salted product workspace used to operate those interactions. Learn more about [Handling Live Conversation](https://help.salted.cx/en/articles/live-conversations-agent).

![](https://media.notiondesk.so/upload/68d3c9184ab4c398938847.png)

## [](#how-work-moves-between-ai-and-people)How work moves between AI and people

Live Conversations supports several operating patterns, from self-service and AI-led resolution to bounded human guidance, external expertise, and full human ownership. Choose the least costly pattern that can produce a correct customer outcome, while keeping escalation and recovery available when uncertainty or policy requires a person:

- Customer self-service using menus. Enables a fast, predictable, 24/7 way to resolve common requests that do not require the customer to explain the issue in free text. Configured automation logic can offer dynamic questions at every step. Learn more about menus in [Build Menus using Your Logic](https://help.salted.cx/en/articles/your-logic-menus).

- Bot conversations. Enables to handle common requests by the customer using a different modality. The bot should typically support everything the self-service supports does and more. Bot also enables users who prefer describing their problem rather that choosing from menus to resolve their issues in their prefer modality. This is still an automated and relatively inexpensive as it does not require a human involvement unless escalated. Learn more about the technical Your Logic Implementation Tips in [Your Logic Implementation Tips](https://help.salted.cx/en/articles/your-logic-implementation-tips).

- External agent (partner) involvement. You can involve people who are not users in Salted CX to handle selected conversations. Your partners can help you to resolve customer request without need to consume your agents’ time. Partners can be also better equipped to handle some request as they may have better understanding of their products and service than your agents.

- Agent involvement. The most expensive option for most companies. Consumes your agents’ time. Live Conversations focus on helping agents with their efficiency and give them quality tools that enable responding to customers faster and in higher quality. Learn more about [Handling Live Conversation](https://help.salted.cx/en/articles/live-conversations-agent).

## [](#features)Features

Key features of Live Conversations:

- Connect your automation logic. You own the rules, AI, workflows, and system integrations that decide what happens next, including how automation behaves while a human is involved and whether it resumes afterward. In Salted configuration and technical documentation, this interface is called [Your Logic](https://help.salted.cx/en/collections/1755764337-your-logic). Salted does not require a specific technology stack, proprietary language, or workflow editor.

- Invite external agents. You can invite people that are not within your company and are not users in Salted CX to help with selected conversations. When invited they will receive a link with time-restricted access to one selected conversation. Configured automation logic can send invitations without first involving in-house agents, preserving their time for work that needs them.

- Collaborative customer care. All participants including your agents, external agents and AI work together on individual customer requests. AI can ask agents for help, invite specific people into conversations and take back conversations from live agents if it knows how to continue. Agents can delegate their work, invite specific colleagues in, or ask anybody for help.

- Complete customer journey. Salted CX unifies all conversations into one continuous [customer journey](https://help.salted.cx/en/collections/1755250527-customer-journey) even when the conversation does not happen in Salted CX. Salted CX collects relationships between contact information and uses [customer profile](https://help.salted.cx/en/articles/customer-profile) to build identity graph that links web chat sessions to emails and phone numbers. Agent can then see all prior conversations in a [single scrollable pane](https://help.salted.cx/en/articles/live-conversations-agent).

- Abstraction from communication channel details. Human agents and automation use a shared conversation model across supported channels. Of course you should take into consideration the channel specifics such as greetings and other conventions in emails.

- Multi-modal interaction. Automation logic can combine menus and free-text communication with seamless transitions between the modes. Learn about using [menus in chat](https://help.salted.cx/en/articles/your-logic-menus).

- Built-in integration with analytics. Every action taken by the participants goes into reporting. The concepts such conversations, engagements, agents and other directly match to analytics in our [Logical Model](https://help.salted.cx/en/collections/1755206106-logical-model). Conversations made in Salted CX Live Conversations are visible next to conversations from other contact center platforms.

## [](#channels)Channels

Live Conversations uses a channel-independent conversation model so participants and automation can work consistently across supported channels. Channel availability depends on account configuration and product maturity.

Digital operation includes Universal Chat, WhatsApp, email, and custom digital channels. Voice can be connected through supported voice configurations and integrations. Channel-specific behavior still matters, such as email threading, WhatsApp templates, and voice-call lifecycle. Confirm current production availability and limitations for your account before rollout.

See [Universal Chat](https://help.salted.cx/en/articles/universal-chat), [Custom Digital Channel](https://help.salted.cx/en/articles/custom-digital-channel), and [Setup Integration with ElevenLabs](https://help.salted.cx/en/articles/1781863332-setup-integration-with-elevenlabs).

## [](#navigation)Navigation

The navigation enables agents to jump between conversations that they are engaged in and join new conversations. When an agent joins a conversation, they can communicate with the customer. See [Handling Live Conversation](https://help.salted.cx/en/articles/live-conversations-agent) for more details.

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

Human agents without supervisory access must join a conversation before viewing and replying to it. Authorized supervisors can view in-progress conversations without joining so they can monitor the operation. Joining creates a human-agent engagement, enables customer communication, and makes the participation visible in analytics.





### [](#overview)Overview

Overview gives you visibility into how loaded are agents when handling conversations.

### [](#my-conversations)My Conversations

My conversations section contains all conversations in which the current user is engaged. These conversations are what the agent should currently focus on and try to resolve as soon as possible.

### [](#help-needed)Help Needed

Help needed section contains conversations that need help for any reason. Automation logic may flag conversations that need help when it lacks confidence, encounters a policy boundary or failure, or the customer asks to speak with a person. Human can also ask for help to involve additional people in case they do not know how to proceed.

A few examples how conversations can be flagged for needing help:

- Automation does not know what to answer to the customer.

- The automation implementation is unavailable, times out, or returns an invalid response.

- The customer explicitly asks for speaking with a live agent and your business process honors their wish and asks for help of the live agents.

### [](#recently-left)Recently Left

Recently left contains conversation in which the current user recently participated but no longer does. Agents can use Recently left section to return to conversations in case they left them accidentally or they have second thoughts of leaving the customer too early.

### [](#all-in-progress)All In Progress

Users with the current `liveConversations.view.allInProgress` permission can see all conversations that are currently in progress, including AI-led conversations with no human agent engaged and conversations waiting for a first response. Supervisors with the required access can open these conversations for monitoring without joining. Users with join permission can then proactively join, take over customer communication, or assign another human agent even when the conversation is not in Help Needed.

## [](#set-up-live-conversations)Set up Live Conversations

To use Live Conversations to its fullest, follow the [Live Conversation Setup](https://help.salted.cx/en/articles/live-conversations-settings) article to enable handling web chat and WhatsApp conversations.

---

## About Salted

Source: https://help.salted.cx/en/collections/1755256040-about-salted


Start here. Understand how Salted AI agents, human agents, and external experts operate and improve customer conversations together.

Salted CX is an AI-native customer-service and contact-center platform where AI agents, human agents, and external experts operate customer conversations together.

Salted combines customer-facing AI agents, Live Conversations, Agent Desktop, programmable automation, Quality Intelligence, coaching, and Conversation Intelligence in one system. It can run customer conversations directly or work alongside existing contact-center platforms.

## [](#the-salted-operating-model)The Salted operating model

### [](#operate-conversations)Operate conversations

AI agents can answer questions, collect information, use connected business systems, perform permitted actions, route work, and resolve eligible customer requests. Human agents operate in the same conversation environment when a person should lead the interaction. Authorized supervisors can monitor ongoing AI-led and human conversations, inspect them without joining, and then join or take over when intervention is needed.

### [](#add-human-judgment-without-losing-context)Add human judgment without losing context

When judgment is needed, an AI agent can ask a human for guidance or approval, invite a specific person or external expert, or hand over the conversation. The human sees the conversation and customer context. When the human contribution ends, AI can continue where the workflow allows it.

### [](#prove-and-improve-outcomes)Prove and improve outcomes

Salted connects conversation execution with automated and manual quality review, agent feedback, coaching, customer-journey context, search, Ask, and analytics. This helps teams improve human performance, AI behavior, knowledge, policies, routing, and operational workflows from the same evidence.

## [](#product-areas)Product areas

- AI Agents. Customer-facing automation that interprets requests, uses knowledge and tools, performs permitted actions, and operates conversations.

- Live Conversations. The environment where AI agents, human agents, and external experts operate active customer conversations together. It is not only the interface people see; behind the interface, it coordinates conversation state, participants, routing, engagements, events, actions, handoffs, joining, leaving, and channel behavior. See [Live Conversations](https://help.salted.cx/en/collections/1755577083-live-conversations).

- Agent Desktop. The human and supervisory workspace inside Live Conversations, with the transcript, customer context, replies, information, actions, and controls needed to monitor or work the conversation. Authorized supervisors can observe all in-progress conversations and proactively join or take over AI-led work.

- Automation logic. The rules, AI, workflows, and connected systems that decide what should happen next in a customer conversation and which actions Salted should perform. In Salted configuration and technical documentation, this automation logic is called Your Logic. See [Your Logic](https://help.salted.cx/en/collections/1755764337-your-logic).

- Quality Intelligence. Automated and human evaluation and improvement for service delivered by human agents, AI agents, and mixed human-AI workflows. See [Quality Assurance](https://help.salted.cx/en/collections/1755201479-quality-assurance) and [Agent Home](https://help.salted.cx/en/articles/1784371079-agent-home).

- Conversation Intelligence. Search, Ask, analytics, and customer-journey context for understanding what happened and what should change. See Ask.

## [](#replace-or-complement-an-existing-contact-center)Replace or complement an existing contact center

Salted can be adopted as the operating environment for customer conversations or as an intelligence and automation layer alongside existing platforms. The appropriate model depends on the channels, integrations, controls, and migration scope required by your organization.

## [](#terminology-used-in-this-documentation)Terminology used in this documentation

- A live conversation is an active customer interaction.

- Live Conversations is the Salted product workspace used to operate active customer interactions.

- An engagement represents one participant's period of involvement in a conversation.

- Resolution can mean several things. Individual articles should state whether it means conversation closure, customer confirmation, completion of the required action, or a quality-verified outcome.

## [](#availability)Availability

Capabilities, channels, deployment modes, and maturity can vary by account and integration. Use the relevant setup and reference articles to confirm current availability and limitations before production rollout.

---

## Agent Home

Source: https://help.salted.cx/en/articles/1784371079-agent-home


Article short description

Agent Home gives agents one place to understand how they are performing, review feedback, respond to evaluations, and open the related customer conversation for context.

![](https://pub-6e850a88e7c944bfb05bc715893a058d.r2.dev/Articles/Agents/Agent%20Home.png)

## [](#what-you-can-do-in-agent-home)What you can do in Agent Home:

### [](#agent-header)Agent header

See core information about agent, choose a time period, and change how Auto QA scores are displayed (with permission only).

### [](#key-metrics)Key Metrics

See current results, trends, targets, and team comparisons.

### [](#feedback-and-conversation-preview)Feedback and Conversation preview

Review Performance, Customer, Team Lead, and Auto Coach feedback and inspect the related conversation.

## [](#choose-an-agent-and-time-period)Choose an agent and time period

If your access is limited to your own data, Agent Home always shows your data only. Users who have permission (like Team Leads or Supervisors) can switch and view Home of other agents too. The agent name may be accompanied by team, department, and location information when those details are available.

Choose one of these periods:

- Today

- Yesterday

- Last 7 Days

The selected period controls the Key Metrics and the Performance and Customer feedback shown on the page. It is also used when you request new Auto Coaching.

Use Percent or Score to change how Auto QA metrics are presented. Percent shows normalized results, while Score shows the average answer score supported by the review question.

## [](#understand-key-metrics)Understand Key Metrics

The Key Metrics strip provides a compact view of the agent's current performance. Depending on account configuration, it can include operational metrics such as:

- Resolution Rate

- Avg Handle Time

- Avg CSAT

- Clarity

- Empathy

- Understanding

- Auto QA questions configured as metrics

Metrics based on AI evaluation are marked with an  AI  badge.

Each metric card can show:

- the result for the selected period

- the change from the preceding comparable period

- a configured target

- a comparison with the agent's team, when available

The direction of improvement depends on the metric. A higher result is usually better, but a lower value may be better for metrics such as Avg Handle Time.

Agent Home displays up to seven metrics. Required metrics are always included. When more optional metrics are selected than can fit, Agent Home prioritizes available high-performing and low-performing results so the strip remains useful for coaching.

## [](#choose-which-metrics-to-follow)Choose which metrics to follow

Select the metric settings control in the Key Metrics area to choose from the available operational and Auto QA metrics. At least four metrics must remain selected. Your selection is stored in your current browser. Selecting an Auto QA metric also makes feedback for that metric available in the Performance tab.

![](https://pub-6e850a88e7c944bfb05bc715893a058d.r2.dev/Articles/Agents/AgentHome_SelectMetrics.png)

## [](#work-with-feedback)Work with feedback

The Feedback area separates feedback by source:

- Performance - Auto QA evaluations

- Customer - customer ratings and comments

- Team Lead - coaching completed by a team lead or reviewer

- Auto Coach - AI-generated coaching

Select an item to open its conversation in the preview on the right. The preview keeps the selected review in context and provides an option to open the full Customer Journey in a new tab.

The selected feedback tab controls the content of the preview. When you move to another tab, select an item there to load its context.

## [](#performance-feedback)Performance feedback

The Performance tab shows a focused sample of Auto QA reviews for the selected period and selected Auto QA metrics. It is designed to surface useful positive and negative examples, not to list every evaluation completed for the agent.

Use the filters to show reviews with these states:

- New - not yet responded to

- Acknowledged - accepted by the agent

- Disputed - challenged by the agent

- Unclear - marked as needing clarification

New is selected by default. At least one filter must remain active.

The counters above the list summarize Acknowledged, Disputed, and Unclear reviews in the current scope, even when one of those states is not currently visible in the list.

## [](#customer-feedback)Customer feedback

The Customer tab surfaces a focused sample of recent positive and negative customer reviews for the agent. The selected time period determines which of the recent reviews are visible.

Customer feedback uses the same New, Acknowledged, Disputed, and Unclear filters as Performance feedback. Select a review to inspect the related conversation before responding.

When no matching customer feedback is available, Agent Home shows ‘No customer feedback yet’.

## [](#respond-to-an-individual-review)Respond to an individual review

Performance and Customer reviews provide these actions:

- Acknowledge
    - The review is clear and you accept it.
    
    
    - Your response is saved and the item becomes Acknowledged.

- Dispute
    - You believe the review, score, or interpretation is incorrect.
    
    
    - You must add a comment explaining the issue before the response is saved.

- Unclear
    - You cannot confidently acknowledge or dispute the review without clarification.
    
    
    - The item is saved as Unclear for follow-up.

After a response is saved, the current preview closes. Use the status filters to return to reviews you have already handled. For more detail, see [Acknowledge and Dispute Reviews](https://help.salted.cx/en/articles/1755230871-acknowledge-and-dispute-reviews).

## [](#team-lead-coaching)Team Lead coaching

The Team Lead tab shows the latest completed coaching session available for the agent.

Feedback is grouped by review question and answer. Comments can include references to specific conversations. Select a conversation reference to open it in the preview and examine the coaching in its original context.

Choose Acknowledge or Dispute for the coaching session. This response applies to the session as a whole and completes it in Agent Home.

When no completed coaching is available, Agent Home shows ‘No coaching sessions yet’.

## [](#auto-coach)Auto Coach

The Auto Coach tab shows the latest active AI-generated coaching session available for the agent.

If no session is available, select Get new coaching to request one. The selected Agent Home period is used to generate the coaching. Availability depends on your account setup and permissions.

Auto Coach feedback is grouped by question and answer. Select a conversation reference to open the supporting Customer Journey in the preview.

Choose Acknowledge or Dispute for the coaching session as a whole.

![](https://pub-6e850a88e7c944bfb05bc715893a058d.r2.dev/Articles/Agents/AgentHome_AutoCoach.png)

## [](#what-agent-home-remembers)What Agent Home remembers

To make repeat visits faster, Agent Home remembers several display choices:

- selected period

- Percent or Score display

- last selected agent, if you can view other agents

- Performance and Customer status filters

- selected Key Metrics in the current browser

## [](#how-agent-home-relates-to-pulse-check-and-vitals)How Agent Home relates to Pulse Check and Vitals

These features use related review data, but they serve different purposes:

- Agent Home
    - Gives an agent a personal performance summary, feedback, coaching, and conversation context.

- Pulse Check
    - Provides a targeted queue of engagements selected for a specific verification or review workflow.

- Vitals
    - Monitors Auto Reviewer health and alignment using aggregated review and verification signals.

Acknowledging or disputing an Auto QA review in Agent Home contributes the same kind of verification signal that can be analyzed in Vitals. Pulse Check can present reviews through a more targeted queue, while Agent Home presents feedback around the selected agent. See [Vitals](https://help.salted.cx/en/articles/1774997602-vitals) for more information about monitoring Auto Reviewer quality.

## [](#if-information-is-missing)If information is missing

- No metrics yet - the agent may not have handled enough conversations in the selected period, or the configured data source may not have produced a result.

- No feedback yet - no Auto QA review matches the selected period, metrics, and status filters.

- No customer feedback yet - no recent customer review matches the selected period and filters.

- No coaching sessions yet - no completed Team Lead coaching session is available.

- You cannot select another agent - your access is limited to your own Agent Home.

- An action cannot be completed - refresh the page and try again. If the problem continues, contact your Salted CX administrator to confirm your permissions and account configuration.

## [](#access-and-configuration)Access and configuration

What appears in Agent Home depends on account configuration and user permissions. Administrators control access to agent data, available Auto QA metrics, feedback sampling, and Auto Coach configuration.

Review responses can also require separate permissions. Contact your Salted CX administrator if an expected area or action is unavailable.

---

## Billing Units

Source: https://help.salted.cx/en/articles/1778863659-billing-units


Article short description

Salted CX uses billable items in the following table. The exact price per-billable item depends on the features enabled on the platform.

| Billed Items | Description |
|---|---|
| Platform fee | Fee for using the platform for any number of users. |
| Conversations | Number of conversations such as phone calls, email threads, chats, etc. |
| Lightweight Conversations | Number of conversations that put minimal stress on Salted CX Platform. |
| External Conversations | Number of conversations that are imported from an external system. |
| Voice Connectivity | Cost per minute for voice conversations when Salted also provides the phone connectivity for inbound and outbound calling. |
| Voice Services | Cost per minute of voice services such as conferencing, agent desktop voice connectivity, stereo call recording and high quality voice transcription. |



## [](#conversation-regular)Conversation (Regular)

Conversation is a series of exchanges between one customer and your company, where, based on metadata, Salted CX can detect that they are related to each other.

Example of conversations:

- Phone call including transfers

- One email thread

- Web chat session

Salted CX enables agents to switch channels during the conversation. When an agent switches channels and responds to a customer in a different channel, it is part of the original conversation because Salted CX has information about the relationship. For example, a chat conversation that turns into an email exchange would be counted as one conversation.

For continuous channels such as Phones, SMS, WhatsApp, and similar, where the customer continues with the next message or call, and it feels like a single continuous pane, we split conversation billing into 24-hour windows. So one conversation spanning 3 days is billed 3 times. For email conversations the billig windows is every 7 days to acomodate longer response times.

## [](#lightweight-conversation)Lightweight Conversation

Each conversation that does not contain free text from the customer side is considered lightweight. This covers all outbound emails, outbound SMSs, or inbound menu-only conversations (in which the agent only clicks buttons in a web chat). Once the customer replies in free text, the conversation is no longer lightweight.

---

## Custom Integration with Slack

Source: https://help.salted.cx/en/articles/custom-slack


# [](#custom-slack-integration-with-your-logic)Custom Slack Integration with Your Logic

How to connect a Slack workspace to Salted CX Your Logic without using any SDK — you receive the Your Logic event JSON on your own HTTP endpoint, you call the Slack Web API yourself, and you push results back into the conversation with plain HTTP.

Both use cases are started by a human agent pressing a button in the Salted CX agent desktop.That press arrives as an `ACTION` trigger — it is the cleanest entry point for a Slack integration, because the agent decides when the integration fires instead of the integration guessing from message content.

1. Announcement — the agent presses Announce in Slack; you post a static message with a link back to the conversation. Fire-and-forget, no callback.

2. Approve / Decline — the agent presses Request approval; you post an interactive card and resume the conversation when a second human presses a button. Requires a callback endpoint and a stateless round-trip.

---

## [](#table-of-contents)Table of contents

- 1. Architecture

- 2. What the customer must set up in Slack

- 3. What must be set up in Salted CX

- 4. The Your Logic wire contract

- 5. The agent desktop button

- 6. Receiving and authenticating a Your Logic event

- 7. Calling the Slack Web API

- Use case 1 — Announcement

- Use case 2 — Approve / Decline

- 8. Verifying inbound Slack requests

- 9. Carrying conversation state through Slack

- 10. Security checklist

- 11. Testing and troubleshooting

- 12. Reference tables

---

## [](#1-architecture)1. Architecture

There are three parties and two independent directions of traffic. Understanding that they are independent is the single most important thing in this document.

```plain
   agent presses a
   desktop button
         │
         ▼  (A) ACTION event                 (B) Web API call
  Salted CX  ─────────────────▶  Your service  ─────────────────▶  Slack
   (Your Logic)                   (any runtime)                    (workspace)
      ▲                                 ▲                             │
      │  (D) actions (HTTPS POST)       │  (C) interaction callback   │
      └─────────────────────────────────┴─────────────────────────────┘
```

| Leg | Direction | Transport | Auth |
|---|---|---|---|
| A | Salted CX → you | `POST` JSON to your Your Logic endpoint | `Authorization: Bearer <shared secret>` you chose |
| B | you → Slack | `POST https://slack.com/api/chat.postMessage` | `Authorization: Bearer xoxb-…` (bot token) |
| C | Slack → you | `POST` form-encoded to your interactivity endpoint | Slack request signature (HMAC-SHA256) |
| D | you → Salted CX | `POST` JSON to the conversation actions endpoint | `Authorization: Bearer <shared secret>` |



Leg A and leg C are two different HTTP endpoints, or one endpoint that branches on `Content-Type` (Your Logic is `application/json`, Slack interactivity is `application/x-www-form-urlencoded`). Either is fine; two paths is clearer.

Note the symmetry: a Salted CX button press is leg A, a Slack button press is leg C. Both are “a human clicked something”; they simply arrive from different systems, in different formats, with different authentication.

The critical consequence for use case 2: you cannot block a Your Logic turn waiting for a button press in Slack. Leg A must answer within seconds; the approver may take hours. Use case 2 is therefore split into two completely separate request lifecycles — post the card in leg A/B, resume the conversation in leg C/D. Nothing is held open in between, so this design survives serverless cold starts and process restarts.

---

## [](#2-what-the-customer-must-set-up-in-slack)2. What the customer must set up in Slack

These steps are performed once by someone with workspace admin rights (or someone who can get an admin to approve the app install). Everything happens at [api.slack.com/apps](https://api.slack.com/apps).

### [](#2-1-create-the-app)2.1 Create the app

1. Open [api.slack.com/apps](https://api.slack.com/apps) → Create New App → From scratch.

2. Name it (e.g. `Demo Adventures Support`) and pick the workspace.

Tip: if you want the app configuration to be reproducible, use From an app manifest and paste the manifest below.

### [](#2-2-add-bot-token-scopes)2.2 Add bot token scopes

OAuth &amp; Permissions → Scopes → Bot Token Scopes. Add exactly what you need:

| Scope | Needed for | Required by |
|---|---|---|
| `chat:write` | Posting messages and cards | Both use cases |
| `chat:write.public` | Posting into public channels the bot has not been invited to | Optional |
| `channels:read` | Resolving a channel name (`#support`) to an ID | Optional |
| `users:read` | Resolving the approver’s display name / email | Optional |
| `chat:write.customize` | Overriding the posting username / icon per message | Optional |



Do not add scopes “just in case” — every extra scope is shown to the admin at install time and lengthens the approval conversation.

### [](#2-3-install-the-app-and-copy-the-bot-token)2.3 Install the app and copy the bot token

OAuth &amp; Permissions → Install to Workspace → approve. Copy the Bot User OAuth Token — it starts with `xoxb-`. This is a secret; store it in your secret manager, never in source control.

> If the workspace requires admin approval for apps, the install request goes to the workspace admin and the token appears only after they approve.

### [](#2-4-copy-the-signing-secret)2.4 Copy the signing secret

Basic Information → App Credentials → Signing Secret → Show → copy. This is what you use to verify that inbound requests (leg C) genuinely came from Slack. Also a secret.

### [](#2-5-enable-interactivity-only-needed-for-use-case-2)2.5 Enable interactivity (only needed for use case 2)

Interactivity &amp; Shortcuts → Interactivity: On → Request URL = `https://your-service.example.com/slack/interactive`.

Slack immediately sends a test `POST` to this URL — your endpoint must already be deployed and return `200` within 3 seconds, or Slack refuses to save the URL.

### [](#2-6-invite-the-bot-to-the-channel)2.6 Invite the bot to the channel

In Slack, in the target channel: `/invite @Demo Adventures Support`.

Skip this only if you granted `chat:write.public` and the channel is public. Private channels always require an explicit invite, no scope substitutes for it.

Then copy the channel ID: click the channel name → About → bottom of the dialog → `C0123ABCDEF`. Prefer the ID over the `#name` — names get renamed, IDs never change.

### [](#2-7-app-manifest-copy-paste)2.7 App manifest (copy-paste)

Create New App → From an app manifest and paste:

```yaml
display_information:
name: Demo Adventures Support
description: Announcements and approvals from Demo Adventures customer conversations
background_color:"#1f2d3d"
features:
bot_user:
display_name: Demo Adventures Support
always_online:true
oauth_config:
scopes:
bot:
- chat:write
- chat:write.public
- users:read
settings:
interactivity:
is_enabled:true
request_url: https://your-service.example.com/slack/interactive
org_deploy_enabled:false
socket_mode_enabled:false
token_rotation_enabled:false
```

### [](#2-8-setup-summary-what-to-hand-to-the-developer)2.8 Setup summary — what to hand to the developer

| Value | Where the customer finds it | Example |
|---|---|---|
| Bot token | OAuth &amp; Permissions | `xoxb-1111-2222-aBcDeF…` |
| Signing secret | Basic Information → App Credentials | `8f14e45fceea167a5a36…` |
| Channel ID | Channel → About | `C0123ABCDEF` |



---

## [](#3-what-must-be-set-up-in-salted-cx)3. What must be set up in Salted CX

Requested from your Salted CX contact or configured in the admin console:

1. Your Logic endpoint URL — the HTTPS URL Salted CX will `POST` events to (`https://your-service.example.com/yourlogic`). It must be publicly reachable and serve a valid TLS certificate.

2. Shared secret — a random string you generate. Salted CX sends it as `Authorization: Bearer <secret>` on every event; you send the same value back on leg D. Generate with `openssl rand -hex 32`.

3. Account ID (`accountId`) and region (`region`) — these also arrive inside every event payload, so you can read them rather than configure them.

4. The custom agent actions — the desktop buttons that start these flows. This is the piece specific to this document; see below.

5. The `<span class="fw-bold">ACTION</span>` trigger enabled for the Your Logic endpoint, so button presses actually reach you.

### [](#3-1-custom-agent-actions-the-desktop-buttons)3.1 Custom agent actions (the desktop buttons)

Go to Settings → Live Conversations → Toolbar to set up buttons.

A custom agent action is a per-account button that appears in the agent’s conversation toolbar. Each one has a stable id and a display label. The id is what travels on the wire; the label is what the agent reads.

Ask your Salted CX contact to configure two:

| Id | Label the agent sees | Use case |
|---|---|---|
| `slack.announce` | Announce in Slack | 1 |
| `slack.approval` | Request approval in Slack | 2 |



Once configured, the buttons appear in the toolbar and each press produces an `ACTION` event on your Your Logic endpoint. Nothing else is needed on the Salted CX side.

The API base is derived from the region:

```plain
https://api.{region}.salted.cx
```

---

## [](#4-the-your-logic-wire-contract)4. The Your Logic wire contract

### [](#4-1-the-inbound-event-leg-a)4.1 The inbound event (leg A)

Every event has the same envelope. Only `trigger` varies. This is what an agent button presslooks like:

```json
{
  "requestId": "8b1f1d16-3f2a-4d8a-9a1e-2e0a1c4a77bd",
  "accountId": "a1b2c3d4-0000-1111-2222-333344445555",
  "time": "2026-07-24T10:15:30Z",
  "expires": "2026-07-24T10:16:00Z",
  "domain": "demo-adventures.salted.cx",
  "region": "eu",
  "trigger": {
    "type": "ACTION",
    "participantType": "AGENT",
    "time": "2026-07-24T10:15:29Z",
    "action": "slack.approval",
    "agent": "agt_3c9f10b2"
  },
  "customer": {
    "pid": "cus_7f3a2b19",
    "displayName": "Jana Novak",
    "contacts": [
      { "pid": "con_4e1a", "contact": "jana@example.com", "type": "Email" }
    ],
    "custom": {}
  },
  "conversation": {
    "pid": "cnv_5d9c8b7a",
    "startConversationTime": "2026-07-24T10:14:02Z",
    "brandId": "demo-adventures",
    "channelType": "Chat",
    "needsHelp": false,
    "status": "IN_PROGRESS",
    "defaultChannel": "web-chat",
    "direction": "INBOUND",
    "languageCustomer": "en",
    "agentDesktop": {
      "toolbar": [
        { "type": "action", "id": "slack.announce" },
        { "type": "action", "id": "slack.approval" }
      ]
    },
    "custom": { "orderId": "10042", "refundAmount": 129 }
  },
  "engagements": [
    {
      "pid": "eng_88a1",
      "time": "2026-07-24T10:14:40Z",
      "type": "AGENT",
      "status": "IN_PROGRESS",
      "agent": { "pid": "agt_3c9f10b2", "type": "HUMAN",
                 "name": "Petr Dvorak", "email": "petr@demo-adventures.example" }
    }
  ],
  "turns": []
}
```

Fields you will actually use:

| Field | Why it matters |
|---|---|
| `trigger.action` | Which button was pressed — the configured custom-action id |
| `trigger.agent` | Pid of the agent who pressed it |
| `trigger.participantType` | `AGENT` for an in-house agent, `EXTERNAL_AGENT` for a partner |
| `requestId` | Echo it back when responding in band to this event |
| `accountId`, `region` | Build the callback URL for leg D |
| `domain` | Tenant domain — used to build the conversation deep link |
| `conversation.pid` | Identifies the conversation for leg D |
| `conversation.custom` | Free-form per-conversation state you control — carries the order/amount |
| `engagements[]` | Where to look up the pressing agent’s name and email from their pid |
| `conversation.agentDesktop.toolbar` | Current state of the toolbar buttons |
| `expires` | After this instant Salted CX stops waiting for an in-band response |



> Forward compatibility. Treat `trigger.type` as an open set, and `trigger.action` too. Unknown values must be acknowledged with `200`/`202` and ignored, never rejected — both sets grow over time, and a button you do not handle is not an error.

### [](#4-2-the-response-legs-a-reply-and-d)4.2 The response (legs A-reply and D)

The response body is always the same shape:

```json
{
  "requestId": "8b1f1d16-3f2a-4d8a-9a1e-2e0a1c4a77bd",
  "actions": [
    { "type": "MESSAGE", "content": "Thanks — let me check that for you.", "attachments": [] },
    { "type": "NOTE", "content": "Approval card posted to #approvals." }
  ]
}
```

Two ways to deliver it — this is the part most integrations get wrong:

| Mode | When | Body | Endpoint |
|---|---|---|---|
| In band | Answering the event you are currently handling | includes `requestId` | `POST {api}/api/v1/live/your-logic/accounts/{accountId}/conversations/{conversationPid}` |
| Out of band | Any later moment (a Slack button click, a cron, a webhook) | omits `requestId` | same URL |



Both are HTTPS `POST` with `Content-Type: application/json` and the shared secret as a bearer token. Presence of `requestId` is the only difference: with it, the actions are attached to that turn; without it, they are applied to the conversation immediately.

Your HTTP response to leg A itself is just an acknowledgement — return `202 Accepted` with an empty body. The actions travel on the separate `POST` above. (Returning them inline in the HTTP response body is not the contract.)

---

## [](#5-the-agent-desktop-button)5. The agent desktop button

### [](#5-1-dispatching-on-the-press)5.1 Dispatching on the press

One endpoint, one switch. Everything in this document hangs off it:

```plain
if trigger.type != "ACTION"           → ignore, 202
if trigger.participantType not AGENT
   and not EXTERNAL_AGENT             → ignore, 202
switch trigger.action:
  "slack.announce" → use case 1
  "slack.approval" → use case 2
  default          → ignore, 202
```

Checking `participantType` matters: `ACTION` triggers can also be synthetic, injected by other integrations to route an external event back into a conversation. Only act on presses that came from a real agent, and only on action ids you own.

#### [](#javascript)JavaScript

```javascript
const ACTION_ANNOUNCE = process.env.SALTED_ACTION_ANNOUNCE ?? "slack.announce";
const ACTION_APPROVAL = process.env.SALTED_ACTION_APPROVAL ?? "slack.approval";

async function handleEvent(event) {
  const trigger = event.trigger;
  if (trigger.type !== "ACTION") return;
  if (trigger.participantType !== "AGENT" && trigger.participantType !== "EXTERNAL_AGENT") return;

  switch (trigger.action) {
    case ACTION_ANNOUNCE:
      return announce(event);
    case ACTION_APPROVAL:
      return requestApproval(event);
    default:
      console.info("action.ignored", { action: trigger.action });
  }
}
```

#### [](#typescript)TypeScript

```typescript
interface ActionTrigger {
  readonly type: "ACTION";
  readonly participantType: "AGENT" | "EXTERNAL_AGENT" | "CUSTOMER" | "BOT" | "UNKNOWN";
  readonly time: string;
  readonly action: string;
  readonly agent?: string | null;
}

const isAgentPress = (trigger: { type: string; participantType?: string }): boolean =>
  trigger.type === "ACTION" &&
  (trigger.participantType === "AGENT" || trigger.participantType === "EXTERNAL_AGENT");

export async function handleEvent(event: YourLogicEvent, env: Env): Promise<void> {
  if (!isAgentPress(event.trigger)) return;

  switch ((event.trigger as ActionTrigger).action) {
    case env.SALTED_ACTION_ANNOUNCE:
      return announce(event, env);
    case env.SALTED_ACTION_APPROVAL:
      return requestApproval(event, env);
    default:
      return; // an action id we do not own
  }
}
```

#### [](#python)Python

```python
import os

ACTION_ANNOUNCE = os.environ.get("SALTED_ACTION_ANNOUNCE", "slack.announce")
ACTION_APPROVAL = os.environ.get("SALTED_ACTION_APPROVAL", "slack.approval")
AGENT_PARTICIPANTS = {"AGENT", "EXTERNAL_AGENT"}


async def handle_event(event: dict) -> None:
    trigger = event["trigger"]
    if trigger.get("type") != "ACTION":
        return
    if trigger.get("participantType") not in AGENT_PARTICIPANTS:
        return

    action = trigger.get("action")
    if action == ACTION_ANNOUNCE:
        await announce(event)
    elif action == ACTION_APPROVAL:
        await request_approval(event)
```

### [](#5-2-naming-the-agent-who-pressed)5.2 Naming the agent who pressed

`trigger.agent` is a pid, not a name. Resolve it against `engagements[]`, which carries the full agent record — and fall back gracefully, because the engagement may not be present on every event.

```javascript
function pressedBy(event) {
  const pid = event.trigger.agent;
  const match = (event.engagements ?? []).find((e) => e.agent?.pid === pid);
  return match?.agent?.name ?? match?.agent?.email ?? pid ?? "an agent";
}
```

```typescript
export function pressedBy(event: YourLogicEvent): string {
  const pid = (event.trigger as ActionTrigger).agent;
  const match = event.engagements?.find((e) => e.agent?.pid === pid);
  return match?.agent?.name ?? match?.agent?.email ?? pid ?? "an agent";
}
```

```python
def pressed_by(event: dict) -> str:
    pid = event["trigger"].get("agent")
    for engagement in event.get("engagements") or []:
        agent = engagement.get("agent") or {}
        if agent.get("pid") == pid:
            return agent.get("name") or agent.get("email") or pid
    return pid or "an agent"
```

### [](#5-3-controlling-the-button-back)5.3 Controlling the button back

The bot can change the toolbar with a `CONVERSATION_UPDATE` action carrying `desktop.customActions`. Each entry addresses one button by id:

```json
{
  "actions": [
    {
      "type": "CONVERSATION_UPDATE",
      "desktop": {
        "customActions": [
          { "id": "slack.approval", "status": "Disabled", "title": "Approval pending…" }
        ]
      }
    }
  ]
}
```

| `status` | Effect |
|---|---|
| `Disabled` | Button greyed out — visible but not clickable |
| `Hidden` | Button removed from the toolbar |
| (omit the entry) | Clears any override, restoring the account default |



`title` overrides the configured label, which is how you turn the button itself into a status indicator.

This is the best de-duplication mechanism available to you — far better than guarding in code. Disable the button in the same response that posts to Slack, and an impatient agent physically cannot fire the flow twice. Re-enable it (by omitting the override) once the Slack round-trip resolves.

The inbound `conversation.agentDesktop.toolbar` reports the current state so you can read what the agent is looking at:

```json
{ "toolbar": [
  { "type": "action", "id": "slack.announce" },
  { "type": "action", "id": "slack.approval", "status": "Disabled" }
] }
```

An item with no `status` is shown and active.

---

## [](#6-receiving-and-authenticating-a-your-logic-event)6. Receiving and authenticating a Your Logic event

Three things, in order: reject non-`POST`, compare the bearer token, parse the body. Anything that fails is a `401` or `400` — never a `500`, and never a silent `200`.

### [](#javascript-node-express)JavaScript (Node + Express)

```javascript
import express from "express";

const app = express();
app.use(express.json({ limit: "1mb" }));

app.post("/yourlogic", async (req, res) => {
  const auth = req.get("authorization");
  if (auth !== `Bearer${process.env.YOURLOGIC_SHARED_SECRET}`) {
    return res.status(401).send("Unauthorized");
  }

  const event = req.body;

  // Acknowledge first, work afterwards — Salted CX must not wait on Slack.
  res.status(202).end();

  try {
    await handleEvent(event);
  } catch (err) {
    console.error("yourlogic.failed", { requestId: event.requestId, err });
  }
});

app.listen(8787);
```

### [](#typescript-fetch-style-runtime-cloudflare-workers-deno-bun)TypeScript (fetch-style runtime — Cloudflare Workers, Deno, Bun)

```typescript
interface YourLogicEvent {
  readonly requestId: string;
  readonly accountId: string;
  readonly region: string;
  readonly domain: string;
  readonly trigger: { readonly type: string; readonly participantType?: string };
  readonly conversation: {
    readonly pid: string;
    readonly channelType?: string | null;
    readonly languageCustomer?: string | null;
    readonly custom?: Record<string, unknown> | null;
  };
  readonly customer: { readonly pid: string; readonly displayName?: string | null };
  readonly engagements?: ReadonlyArray<{
    readonly agent?: { readonly pid: string; readonly name?: string | null; readonly email?: string | null } | null;
  }>;
}

export default {
  async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
    if (request.method !== "POST") return new Response("Method Not Allowed", { status: 405 });
    if (request.headers.get("Authorization") !== `Bearer${env.YOURLOGIC_SHARED_SECRET}`) {
      return new Response("Unauthorized", { status: 401 });
    }

    let event: YourLogicEvent;
    try {
      event = (await request.json()) as YourLogicEvent;
    } catch {
      return new Response("Bad Request", { status: 400 });
    }

    // Keep working after the response is returned.
    ctx.waitUntil(handleEvent(event, env));
    return new Response(null, { status: 202 });
  },
};
```

### [](#python-fastapi)Python (FastAPI)

```python
import hmac
import os

from fastapi import BackgroundTasks, FastAPI, Header, HTTPException, Request

app = FastAPI()
SHARED_SECRET = os.environ["YOURLOGIC_SHARED_SECRET"]


@app.post("/yourlogic", status_code=202)
async def your_logic(request: Request, background: BackgroundTasks, authorization: str = Header(None)):
    if not authorization or not hmac.compare_digest(authorization, f"Bearer{SHARED_SECRET}"):
        raise HTTPException(status_code=401, detail="Unauthorized")

    event = await request.json()
    background.add_task(handle_event, event)
    return {}
```

> Use a constant-time comparison (`hmac.compare_digest`, `crypto.timingSafeEqual`) for the shared secret. A naive `==` leaks the secret byte-by-byte through timing over enough requests.

---

## [](#7-calling-the-slack-web-api)7. Calling the Slack Web API

Every Slack Web API call in this document is the same shape:

```plain
POST https://slack.com/api/<method>
Authorization: Bearer xoxb-…
Content-Type: application/json; charset=utf-8
```

Slack returns HTTP 200 even on failure. The real result is `{"ok": false, "error": "…"}` in the body. Always check `ok`.

A minimal client you will reuse in both use cases:

```javascript
// JavaScript
async function slack(method, payload, botToken) {
  const response = await fetch(`https://slack.com/api/${method}`, {
    method: "POST",
    headers: {
      Authorization: `Bearer${botToken}`,
      "Content-Type": "application/json; charset=utf-8",
    },
    body: JSON.stringify(payload),
  });
  const body = await response.json();
  if (!body.ok) throw new Error(`Slack${method} failed:${body.error}`);
  return body;
}
```

```typescript
// TypeScript
interface SlackResult { ok: boolean; error?: string; ts?: string; channel?: string }

export async function slack<T extends SlackResult = SlackResult>(
  method: string,
  payload: Record<string, unknown>,
  botToken: string,
): Promise<T> {
  const response = await fetch(`https://slack.com/api/${method}`, {
    method: "POST",
    headers: {
      Authorization: `Bearer${botToken}`,
      "Content-Type": "application/json; charset=utf-8",
    },
    body: JSON.stringify(payload),
  });
  const body = (await response.json()) as T;
  if (!body.ok) throw new Error(`Slack${method} failed:${body.error ?? "unknown"}`);
  return body;
}
```

```python
# Python
import httpx

SLACK_API = "https://slack.com/api"


async def slack(method: str, payload: dict, bot_token: str) -> dict:
    async with httpx.AsyncClient(timeout=10) as client:
        response = await client.post(
            f"{SLACK_API}/{method}",
            json=payload,
            headers={"Authorization": f"Bearer{bot_token}"},
        )
    body = response.json()
    if not body.get("ok"):
        raise RuntimeError(f"Slack{method} failed:{body.get('error')}")
    return body
```

Common `error` values: `not_in_channel` (invite the bot), `channel_not_found` (wrong ID, or a private channel the bot cannot see), `invalid_auth` (bad/revoked token), `missing_scope` (reinstall with the scope added), `ratelimited` (honour the `Retry-After` header).

---

## [](#use-case-1-announcement)Use case 1 — Announcement

Goal: the agent presses Announce in Slack on a conversation; a static, non-interactive message lands in a Slack channel with a link back to that conversation. No reply is expected.

Typical use: a supervisor-visibility channel, a “this one needs eyes” ping, an escalation notice.

### [](#1-1-flow)1.1 Flow

```plain
agent presses "Announce in Slack"
         │
         ▼  ACTION trigger, action = "slack.announce"
  Salted CX ──▶ your service ──chat.postMessage──▶ #support
                      │
                      └── NOTE + button Disabled ──▶ Salted CX (in band)
```

Three things happen in one turn:

1. Post the message to Slack.

2. Write a `NOTE` on the conversation timeline so the other agents can see it was announced.

3. Disable the button so a second press cannot double-post.

All three are worth doing. The `NOTE` and the disabled button together make the integration visible in the agent desktop instead of being an invisible side effect.

### [](#1-2-the-conversation-deep-link)1.2 The conversation deep link

Build it from the event’s own `domain` and `conversation.pid`:

```plain
https://{domain}/conversations/{conversationPid}
```

> Confirm the exact agent-desktop path with your Salted CX contact — the tenant domain is authoritative but the path segment can differ per deployment. If the event carries `conversation.info[].url`, prefer that value: it is the link Salted CX itself considers canonical. Keep the construction in one function so a change is a one-line fix.

### [](#1-3-message-layout)1.3 Message layout

Plain `text` is enough, but a two-block layout reads far better in a busy channel — a headline section plus a context line with the metadata, including who pressed the button:

```json
{
  "channel": "C0123ABCDEF",
  "text": "Petr Dvorak flagged a conversation: Jana Novak",
  "blocks": [
    {
      "type": "section",
      "text": {
        "type": "mrkdwn",
        "text": "*Conversation flagged by Petr Dvorak*\nCustomer: Jana Novak — _Demo Adventures_\n<https://demo-adventures.salted.cx/conversations/cnv_5d9c8b7a|Open conversation>"
      }
    },
    {
      "type": "context",
      "elements": [
        { "type": "mrkdwn", "text": "Channel: Chat · Language: en · Order 10042" }
      ]
    }
  ]
}
```

Two rules that are easy to miss:

- Always send `<span class="fw-bold">text</span>` as well as `<span class="fw-bold">blocks</span>`. `text` is the notification preview on mobile and in the sidebar. Blocks-only messages show up as “This content can’t be displayed”.

- Slack link syntax is `<url|label>`, not Markdown `[label](url)`.

### [](#1-4-implementation)1.4 Implementation

#### [](#javascript)JavaScript

```javascript
const SLACK_BOT_TOKEN = process.env.SLACK_BOT_TOKEN;
const SLACK_CHANNEL_ID = process.env.SLACK_CHANNEL_ID;
const SHARED_SECRET = process.env.YOURLOGIC_SHARED_SECRET;

function conversationLink(event) {
  return `https://${event.domain}/conversations/${event.conversation.pid}`;
}

function escapeSlack(text) {
  return String(text).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
}

async function announce(event) {
  const agentName = escapeSlack(pressedBy(event));
  const who = escapeSlack(event.customer.displayName ?? "Unknown customer");
  const link = conversationLink(event);

  await slack("chat.postMessage", {
    channel: SLACK_CHANNEL_ID,
    text: `${agentName} flagged a conversation:${who}`,
    blocks: [
      {
        type: "section",
        text: {
          type: "mrkdwn",
          text: `*Conversation flagged by${agentName}*\nCustomer:${who}\n<${link}|Open conversation>`,
        },
      },
      {
        type: "context",
        elements: [
          {
            type: "mrkdwn",
            text: `Channel:${event.conversation.channelType ?? "Chat"} · Language:${event.conversation.languageCustomer ?? "n/a"}`,
          },
        ],
      },
    ],
  }, SLACK_BOT_TOKEN);

  // In band (echo the requestId): note it on the timeline and stop the button
  // being pressed a second time.
  await postActions(event, [
    { type: "NOTE", content: `Announced in Slack #support by${pressedBy(event)}.` },
    {
      type: "CONVERSATION_UPDATE",
      desktop: {
        customActions: [
          { id: ACTION_ANNOUNCE, status: "Disabled", title: "Announced in Slack" },
        ],
      },
    },
  ], event.requestId);
}

async function postActions(event, actions, requestId) {
  const url =
    `https://api.${event.region}.salted.cx/api/v1/live/your-logic` +
    `/accounts/${event.accountId}/conversations/${event.conversation.pid}`;

  const response = await fetch(url, {
    method: "POST",
    headers: {
      Authorization: `Bearer${SHARED_SECRET}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify(requestId ? { requestId, actions } : { actions }),
  });
  if (!response.ok) {
    throw new Error(`Salted CX rejected actions:${response.status}${await response.text()}`);
  }
}
```

#### [](#typescript)TypeScript

```typescript
const escapeSlack = (text: string): string =>
  text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");

function conversationLink(event: YourLogicEvent): string {
  return `https://${event.domain}/conversations/${event.conversation.pid}`;
}

export async function announce(event: YourLogicEvent, env: Env): Promise<void> {
  const agentName = escapeSlack(pressedBy(event));
  const who = escapeSlack(event.customer.displayName ?? "Unknown customer");

  await slack("chat.postMessage", {
    channel: env.SLACK_CHANNEL_ID,
    text: `${agentName} flagged a conversation:${who}`,
    blocks: [
      {
        type: "section",
        text: {
          type: "mrkdwn",
          text: `*Conversation flagged by${agentName}*\nCustomer:${who}\n<${conversationLink(event)}|Open conversation>`,
        },
      },
      {
        type: "context",
        elements: [{
          type: "mrkdwn",
          text: `Channel:${event.conversation.channelType ?? "Chat"} · Language:${event.conversation.languageCustomer ?? "n/a"}`,
        }],
      },
    ],
  }, env.SLACK_BOT_TOKEN);

  await postActions(event, [
    { type: "NOTE", content: `Announced in Slack by${pressedBy(event)}.` },
    {
      type: "CONVERSATION_UPDATE",
      desktop: {
        customActions: [{ id: env.SALTED_ACTION_ANNOUNCE, status: "Disabled", title: "Announced in Slack" }],
      },
    },
  ], { requestId: event.requestId, sharedSecret: env.YOURLOGIC_SHARED_SECRET });
}

export async function postActions(
  event: YourLogicEvent,
  actions: ReadonlyArray<Record<string, unknown>>,
  options: { readonly requestId?: string; readonly sharedSecret: string },
): Promise<void> {
  const url =
    `https://api.${event.region}.salted.cx/api/v1/live/your-logic` +
    `/accounts/${event.accountId}/conversations/${event.conversation.pid}`;

  const body = options.requestId ? { requestId: options.requestId, actions } : { actions };
  const response = await fetch(url, {
    method: "POST",
    headers: {
      Authorization: `Bearer${options.sharedSecret}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify(body),
  });
  if (!response.ok) {
    throw new Error(`Salted CX rejected actions:${response.status}${await response.text()}`);
  }
}
```

#### [](#python)Python

```python
import os

import httpx

SLACK_BOT_TOKEN = os.environ["SLACK_BOT_TOKEN"]
SLACK_CHANNEL_ID = os.environ["SLACK_CHANNEL_ID"]
SHARED_SECRET = os.environ["YOURLOGIC_SHARED_SECRET"]


def conversation_link(event: dict) -> str:
    return f"https://{event['domain']}/conversations/{event['conversation']['pid']}"


def escape_slack(text: str) -> str:
    return str(text).replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;")


async def announce(event: dict) -> None:
    agent_name = escape_slack(pressed_by(event))
    who = escape_slack(event["customer"].get("displayName") or "Unknown customer")
    link = conversation_link(event)
    conversation = event["conversation"]

    await slack(
        "chat.postMessage",
        {
            "channel": SLACK_CHANNEL_ID,
            "text": f"{agent_name} flagged a conversation:{who}",
            "blocks": [
                {
                    "type": "section",
                    "text": {
                        "type": "mrkdwn",
                        "text": f"*Conversation flagged by{agent_name}*\n"
                                f"Customer:{who}\n<{link}|Open conversation>",
                    },
                },
                {
                    "type": "context",
                    "elements": [{
                        "type": "mrkdwn",
                        "text": f"Channel:{conversation.get('channelType') or 'Chat'} · "
                                f"Language:{conversation.get('languageCustomer') or 'n/a'}",
                    }],
                },
            ],
        },
        SLACK_BOT_TOKEN,
    )

    await post_actions(event, [
        {"type": "NOTE", "content": f"Announced in Slack #support by{pressed_by(event)}."},
        {"type": "CONVERSATION_UPDATE",
         "desktop": {"customActions": [
             {"id": ACTION_ANNOUNCE, "status": "Disabled", "title": "Announced in Slack"},
         ]}},
    ], request_id=event["requestId"])


async def post_actions(event: dict, actions: list[dict], request_id: str | None = None) -> None:
    url = (
        f"https://api.{event['region']}.salted.cx/api/v1/live/your-logic"
        f"/accounts/{event['accountId']}/conversations/{event['conversation']['pid']}"
    )
    body: dict = {"actions": actions}
    if request_id:
        body["requestId"] = request_id

    async with httpx.AsyncClient(timeout=10) as client:
        response = await client.post(
            url, json=body, headers={"Authorization": f"Bearer{SHARED_SECRET}"}
        )
    response.raise_for_status()
```

### [](#1-5-things-to-get-right)1.5 Things to get right

- De-duplicate with the button, not with code. Disabling `slack.announce` in the same response is simpler and more honest than a flag, because the agent can see that it already happened. Keep a `custom` flag too if you re-enable the button later.

- Never let a Slack failure fail the conversation. Catch, log, move on. If the post failed, say so on the timeline (`NOTE: "Slack announcement failed — not posted."`) and leave the button enabled so the agent can retry. Silently disabling a button after a failed post is the worst of both worlds.

- Escape user-controlled text (`&`, `<`, `>`) before putting it in `mrkdwn`. A customer name containing `<` otherwise breaks the whole block.

- Rate limits. `chat.postMessage` is roughly 1 message per second per channel. Agent presses are human-paced so this rarely bites, but honour `Retry-After` on HTTP 429 anyway.

---

## [](#use-case-2-approve-decline)Use case 2 — Approve / Decline

Goal: the agent presses Request approval in Slack; you post a card with Approve and Decline buttons, and continue the conversation when a second human presses one — minutes or hours later.

This is the agent-in-the-loop pattern: the agent decides that approval is needed, a supervisor decides whether it is granted, and the customer is answered automatically either way.

### [](#2-1-flow)2.1 Flow

```plain
  ── Lifecycle 1 (leg A + B) ──────────────────────────────
  agent presses "Request approval in Slack"
         │  ACTION trigger, action = "slack.approval"
  Salted CX ──▶ your service ──chat.postMessage──▶ #approvals
                      │                              (card with 2 buttons,
                      ├── MESSAGE "checking…"           each carrying the
                      ├── NOTE                          conversation context)
                      └── button Disabled ──▶ Salted CX (in band, requestId)

  ── nothing is held open in between ──────────────────────

  ── Lifecycle 2 (leg C + D) ──────────────────────────────
  #approvals ──button click──▶ your service ──200 within 3s──▶ Slack
                                    │
                                    ├── chat.update ──▶ #approvals ("Approved by @petr")
                                    └── actions (out of band, NO requestId) ──▶ Salted CX
```

### [](#2-2-what-the-agent-press-gives-you)2.2 What the agent press gives you

The `ACTION` event carries no free-text payload — a button press is a bare signal. Everything the approver needs to make a decision must therefore come from the conversation itself:

| Source | Typical content |
|---|---|
| `conversation.custom` | The order id, the amount, the case reference — set earlier by the bot or by a prior integration |
| `customer.displayName` | Who is asking |
| `turns[]` | Recent conversation history, if you want to quote the customer’s request |
| `trigger.agent` → `engagements[]` | Which agent is asking for the approval |



If `conversation.custom` does not yet hold what you need, that is a flow design problem, not an integration problem — the bot (or the agent, via a form) must record it before the button is pressed. Fail loudly:

```javascript
const orderId = event.conversation.custom?.orderId;
const amount = event.conversation.custom?.refundAmount;
if (!orderId || typeof amount !== "number") {
  await postActions(event, [
    { type: "NOTE", content: "Cannot request approval: order id / refund amount missing on the conversation." },
  ], event.requestId);
  return;
}
```

A `NOTE` telling the agent why nothing happened is worth far more than a silent return — from the agent’s seat, a button that does nothing is indistinguishable from a broken integration.

### [](#2-3-posting-the-card)2.3 Posting the card

The two buttons differ only in `action_id`, label and style. Both carry the same `value`: an encoded snapshot of everything you need to find the conversation again.

```json
{
  "channel": "C0123ABCDEF",
  "text": "Approval needed: refund 129 EUR for order 10042",
  "blocks": [
    {
      "type": "section",
      "text": {
        "type": "mrkdwn",
        "text": "*Approval needed*\nRequested by *Petr Dvorak*\nRefund *129 EUR* for order *10042*\nCustomer: Jana Novak\n<https://demo-adventures.salted.cx/conversations/cnv_5d9c8b7a|Open conversation>"
      }
    },
    {
      "type": "actions",
      "block_id": "approval",
      "elements": [
        {
          "type": "button",
          "action_id": "approve",
          "style": "primary",
          "text": { "type": "plain_text", "text": "Approve" },
          "value": "eyJhY2NvdW50SWQiOiJhMWIyYzNkNCIsInJlZ2lvbiI6ImV1In0"
        },
        {
          "type": "button",
          "action_id": "decline",
          "style": "danger",
          "text": { "type": "plain_text", "text": "Decline" },
          "value": "eyJhY2NvdW50SWQiOiJhMWIyYzNkNCIsInJlZ2lvbiI6ImV1In0"
        }
      ]
    }
  ]
}
```

Constraints worth knowing before you design the payload:

| Limit | Value |
|---|---|
| Button `value` | 2000 characters max — the hard constraint on how much context you can carry |
| `action_id` | Must be unique within the message |
| Buttons per `actions` block | 25 |
| `text` in a button | `plain_text` only, no `mrkdwn` |
| Card must be re-postable | Slack does not de-duplicate; you must |



If your context does not fit in 2000 characters, put an opaque key in `value` and store the payload in your own database — but see §9 first: the self-contained approach is almost always better.

#### [](#javascript)JavaScript

```javascript
function encodeContext(context) {
  const json = JSON.stringify(context);
  return Buffer.from(json, "utf8").toString("base64url");
}

async function requestApproval(event) {
  const custom = event.conversation.custom ?? {};
  const orderId = custom.orderId;
  const amount = custom.refundAmount;
  if (!orderId || typeof amount !== "number") {
    await postActions(event, [
      { type: "NOTE", content: "Cannot request approval: order id / refund amount missing." },
    ], event.requestId);
    return;
  }

  const requestedBy = pressedBy(event);
  const question = `Refund *${amount} EUR* for order *${orderId}*`;

  const value = encodeContext({
    accountId: event.accountId,
    region: event.region,
    domain: event.domain,
    conversationPid: event.conversation.pid,
    customerPid: event.customer.pid,
    requestedBy,
    custom,
  });
  if (value.length > 2000) throw new Error("Approval context exceeds Slack's 2000-char button value limit");

  await slack("chat.postMessage", {
    channel: process.env.SLACK_APPROVAL_CHANNEL_ID,
    text: `Approval needed: refund${amount} EUR for order${orderId}`,
    blocks: [
      {
        type: "section",
        text: {
          type: "mrkdwn",
          text: `*Approval needed*\nRequested by *${escapeSlack(requestedBy)}*\n${question}\n` +
                `Customer:${escapeSlack(event.customer.displayName ?? "Unknown")}\n` +
                `<${conversationLink(event)}|Open conversation>`,
        },
      },
      {
        type: "actions",
        block_id: "approval",
        elements: [
          { type: "button", action_id: "approve", style: "primary",
            text: { type: "plain_text", text: "Approve" }, value },
          { type: "button", action_id: "decline", style: "danger",
            text: { type: "plain_text", text: "Decline" }, value },
        ],
      },
    ],
  }, SLACK_BOT_TOKEN);

  // In band: tell the customer, note it, and lock the button while it is pending.
  await postActions(event, [
    { type: "MESSAGE", content: "Let me check this with a colleague — one moment.", attachments: [] },
    { type: "NOTE", content: `Approval requested in Slack by${requestedBy}: refund${amount} EUR for order${orderId}.` },
    {
      type: "CONVERSATION_UPDATE",
      custom: { approvalPending: true },
      desktop: {
        customActions: [{ id: ACTION_APPROVAL, status: "Disabled", title: "Approval pending…" }],
      },
    },
  ], event.requestId);
}
```

#### [](#typescript)TypeScript

```typescript
export interface ApprovalContext {
  readonly accountId: string;
  readonly region: string;
  readonly domain: string;
  readonly conversationPid: string;
  readonly customerPid: string;
  readonly requestedBy?: string;
  readonly custom?: Record<string, unknown>;
}

const encodeContext = (context: ApprovalContext): string =>
  base64UrlEncode(new TextEncoder().encode(JSON.stringify(context)));

const decodeContext = (value: string): ApprovalContext | null => {
  try {
    const parsed = JSON.parse(new TextDecoder().decode(base64UrlDecode(value))) as Partial<ApprovalContext>;
    if (typeof parsed.accountId !== "string" || typeof parsed.region !== "string") return null;
    if (typeof parsed.conversationPid !== "string" || typeof parsed.customerPid !== "string") return null;
    return parsed as ApprovalContext;
  } catch {
    return null;
  }
};

function base64UrlEncode(bytes: Uint8Array): string {
  let binary = "";
  for (const byte of bytes) binary += String.fromCharCode(byte);
  return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
}

function base64UrlDecode(value: string): Uint8Array {
  const normalised = value.replace(/-/g, "+").replace(/_/g, "/");
  const padded = normalised + "===".slice((normalised.length + 3) % 4);
  const binary = atob(padded);
  const bytes = new Uint8Array(binary.length);
  for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
  return bytes;
}

export async function requestApproval(event: YourLogicEvent, env: Env): Promise<void> {
  const custom = event.conversation.custom ?? {};
  const orderId = custom["orderId"];
  const amount = custom["refundAmount"];
  if (typeof orderId !== "string" || typeof amount !== "number") {
    await postActions(event, [
      { type: "NOTE", content: "Cannot request approval: order id / refund amount missing." },
    ], { requestId: event.requestId, sharedSecret: env.YOURLOGIC_SHARED_SECRET });
    return;
  }

  const requestedBy = pressedBy(event);
  const value = encodeContext({
    accountId: event.accountId,
    region: event.region,
    domain: event.domain,
    conversationPid: event.conversation.pid,
    customerPid: event.customer.pid,
    requestedBy,
    custom,
  });
  if (value.length > 2000) throw new Error("Approval context exceeds Slack's 2000-char button value limit");

  const button = (actionId: string, label: string, style: "primary" | "danger") => ({
    type: "button",
    action_id: actionId,
    style,
    text: { type: "plain_text", text: label },
    value,
  });

  await slack("chat.postMessage", {
    channel: env.SLACK_APPROVAL_CHANNEL_ID,
    text: `Approval needed: refund${amount} EUR for order${orderId}`,
    blocks: [
      {
        type: "section",
        text: {
          type: "mrkdwn",
          text: `*Approval needed*\nRequested by *${escapeSlack(requestedBy)}*\n` +
                `Refund *${amount} EUR* for order *${escapeSlack(orderId)}*\n` +
                `<${conversationLink(event)}|Open conversation>`,
        },
      },
      { type: "actions", block_id: "approval",
        elements: [button("approve", "Approve", "primary"), button("decline", "Decline", "danger")] },
    ],
  }, env.SLACK_BOT_TOKEN);

  await postActions(event, [
    { type: "MESSAGE", content: "Let me check this with a colleague — one moment.", attachments: [] },
    { type: "NOTE", content: `Approval requested in Slack by${requestedBy}.` },
    {
      type: "CONVERSATION_UPDATE",
      custom: { approvalPending: true },
      desktop: {
        customActions: [{ id: env.SALTED_ACTION_APPROVAL, status: "Disabled", title: "Approval pending…" }],
      },
    },
  ], { requestId: event.requestId, sharedSecret: env.YOURLOGIC_SHARED_SECRET });
}
```

#### [](#python)Python

```python
import base64
import json
import os


def encode_context(context: dict) -> str:
    raw = json.dumps(context, separators=(",", ":")).encode("utf-8")
    return base64.urlsafe_b64encode(raw).decode("ascii").rstrip("=")


def decode_context(value: str) -> dict | None:
    try:
        padded = value + "=" * (-len(value) % 4)
        context = json.loads(base64.urlsafe_b64decode(padded))
    except Exception:
        return None
    required = ("accountId", "region", "conversationPid", "customerPid")
    if not all(isinstance(context.get(key), str) for key in required):
        return None
    return context


async def request_approval(event: dict) -> None:
    custom = event["conversation"].get("custom") or {}
    order_id = custom.get("orderId")
    amount = custom.get("refundAmount")
    if not order_id or not isinstance(amount, (int, float)):
        await post_actions(event, [
            {"type": "NOTE", "content": "Cannot request approval: order id / refund amount missing."},
        ], request_id=event["requestId"])
        return

    requested_by = pressed_by(event)
    value = encode_context({
        "accountId": event["accountId"],
        "region": event["region"],
        "domain": event["domain"],
        "conversationPid": event["conversation"]["pid"],
        "customerPid": event["customer"]["pid"],
        "requestedBy": requested_by,
        "custom": custom,
    })
    if len(value) > 2000:
        raise ValueError("Approval context exceeds Slack's 2000-char button value limit")

    def button(action_id: str, label: str, style: str) -> dict:
        return {
            "type": "button",
            "action_id": action_id,
            "style": style,
            "text": {"type": "plain_text", "text": label},
            "value": value,
        }

    await slack(
        "chat.postMessage",
        {
            "channel": os.environ["SLACK_APPROVAL_CHANNEL_ID"],
            "text": f"Approval needed: refund{amount} EUR for order{order_id}",
            "blocks": [
                {"type": "section",
                 "text": {"type": "mrkdwn",
                          "text": f"*Approval needed*\nRequested by *{escape_slack(requested_by)}*\n"
                                  f"Refund *{amount} EUR* for order *{escape_slack(order_id)}*\n"
                                  f"<{conversation_link(event)}|Open conversation>"}},
                {"type": "actions", "block_id": "approval",
                 "elements": [button("approve", "Approve", "primary"),
                              button("decline", "Decline", "danger")]},
            ],
        },
        SLACK_BOT_TOKEN,
    )

    await post_actions(event, [
        {"type": "MESSAGE", "content": "Let me check this with a colleague — one moment.",
         "attachments": []},
        {"type": "NOTE", "content": f"Approval requested in Slack by{requested_by}."},
        {"type": "CONVERSATION_UPDATE",
         "custom": {"approvalPending": True},
         "desktop": {"customActions": [
             {"id": ACTION_APPROVAL, "status": "Disabled", "title": "Approval pending…"},
         ]}},
    ], request_id=event["requestId"])
```

### [](#2-4-receiving-the-slack-button-click)2.4 Receiving the Slack button click

Slack `POST`s to your Interactivity Request URL as `application/x-www-form-urlencoded` with a single field, `payload`, holding JSON:

```json
{
  "type": "block_actions",
  "user": { "id": "U024BE7LH", "username": "petr", "name": "petr" },
  "channel": { "id": "C0123ABCDEF", "name": "approvals" },
  "message": { "ts": "1753351234.123456", "text": "Approval needed: refund 129 EUR" },
  "response_url": "https://hooks.slack.com/actions/T0001/12345/abcdef",
  "trigger_id": "13345224609.738474920.8088930838d88f008e0",
  "actions": [
    {
      "type": "button",
      "action_id": "approve",
      "block_id": "approval",
      "value": "eyJhY2NvdW50SWQiOiJhMWIyYzNkNCIsInJlZ2lvbiI6ImV1In0",
      "action_ts": "1753351299.000100"
    }
  ]
}
```

The 3-second rule. Slack shows the user a red error if you have not returned `200` within three seconds. Salted CX and Slack API calls can easily exceed that. So: acknowledge first, work afterwards. Every example below does exactly that.

### [](#2-5-the-full-callback-handler)2.5 The full callback handler

Order of operations, in every language:

1. Read the raw body as bytes/string — before any parsing. The signature is over raw bytes.

2. Verify the Slack signature (see §8). Reject with `401`.

3. Parse `payload`, ignore anything that is not `type: "block_actions"`.

4. Decode the button `value` into the conversation context; reject if it does not decode.

5. Return `<span class="fw-bold">200</span>` immediately.

6. In the background: `chat.update` the card into a resolved state, then post the actions to Salted CX out of band (no `requestId`) — including re-enabling the agent’s desktop button by clearing its override.

#### [](#javascript-node-express)JavaScript (Node + Express)

```javascript
import crypto from "node:crypto";
import express from "express";

const app = express();
// Raw body — the Slack signature is computed over the exact bytes.
app.use("/slack/interactive", express.raw({ type: "*/*" }));

app.post("/slack/interactive", (req, res) => {
  const rawBody = req.body.toString("utf8");

  if (!verifySlackSignature({
    signingSecret: process.env.SLACK_SIGNING_SECRET,
    timestamp: req.get("x-slack-request-timestamp"),
    signature: req.get("x-slack-signature"),
    body: rawBody,
  })) {
    return res.status(401).send("Invalid Slack signature");
  }

  const payload = JSON.parse(new URLSearchParams(rawBody).get("payload") ?? "{}");

  // Acknowledge inside the 3-second window; everything else is background work.
  res.status(200).end();

  if (payload.type !== "block_actions") return;
  handleBlockAction(payload).catch((err) => console.error("slack.action.failed", err));
});

async function handleBlockAction(payload) {
  const action = payload.actions?.[0];
  if (!action) return;
  if (action.action_id !== "approve" && action.action_id !== "decline") return;

  const context = decodeContext(action.value);
  if (!context) return console.error("slack.action.bad_context", { actionId: action.action_id });

  const approved = action.action_id === "approve";
  const decidedBy = payload.user?.username ?? payload.user?.id ?? "someone";

  // 1. Freeze the card so the decision cannot be taken twice.
  await slack("chat.update", {
    channel: payload.channel.id,
    ts: payload.message.ts,
    text: payload.message.text,
    blocks: [
      { type: "section", text: { type: "mrkdwn", text: payload.message.text } },
      { type: "context", elements: [{
        type: "mrkdwn",
        text: `${approved ? ":white_check_mark: *Approved*" : ":x: *Declined*"} by <@${payload.user.id}>` +
              (context.requestedBy ? ` · requested by${context.requestedBy}` : ""),
      }] },
    ],
  }, SLACK_BOT_TOKEN);

  // 2. Resume the conversation — out of band, so NO requestId.
  const outcome = approved
    ? [
        { type: "MESSAGE", content: "Good news — your refund has been approved and is on its way.", attachments: [] },
        { type: "NOTE", content: `Refund approved in Slack by${decidedBy}.` },
        { type: "CONVERSATION_COMPLETE" },
      ]
    : [
        { type: "MESSAGE", content: "I could not approve this automatically. A colleague will take over shortly.", attachments: [] },
        { type: "NOTE", content: `Refund declined in Slack by${decidedBy}.` },
        { type: "NEEDS_HELP", needsHelp: true },
      ];

  // 3. Clear the desktop button override so the agent can request again.
  outcome.push({
    type: "CONVERSATION_UPDATE",
    custom: { approvalPending: false, approvalDecided: true, approvalApproved: approved },
    desktop: { customActions: [] },
  });

  await applyConversationActions(context, outcome);
}

async function applyConversationActions(context, actions) {
  const url =
    `https://api.${context.region}.salted.cx/api/v1/live/your-logic` +
    `/accounts/${context.accountId}/conversations/${context.conversationPid}`;

  const response = await fetch(url, {
    method: "POST",
    headers: {
      Authorization: `Bearer${process.env.YOURLOGIC_SHARED_SECRET}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ actions }),  // no requestId — out of band
  });
  if (!response.ok) {
    throw new Error(`Salted CX rejected actions:${response.status}${await response.text()}`);
  }
}

function decodeContext(value) {
  try {
    const context = JSON.parse(Buffer.from(value, "base64url").toString("utf8"));
    const required = ["accountId", "region", "conversationPid", "customerPid"];
    return required.every((key) => typeof context[key] === "string") ? context : null;
  } catch {
    return null;
  }
}
```

#### [](#typescript-fetch-style-runtime)TypeScript (fetch-style runtime)

```typescript
interface BlockActionsPayload {
  readonly type: string;
  readonly user: { readonly id: string; readonly username?: string };
  readonly channel: { readonly id: string };
  readonly message: { readonly ts: string; readonly text: string };
  readonly actions: ReadonlyArray<{ readonly action_id: string; readonly value: string }>;
}

export async function handleSlackInteractive(
  request: Request,
  env: Env,
  ctx: ExecutionContext,
): Promise<Response> {
  const rawBody = await request.text();

  const verified = await verifySlackSignature({
    signingSecret: env.SLACK_SIGNING_SECRET,
    timestamp: request.headers.get("X-Slack-Request-Timestamp"),
    signature: request.headers.get("X-Slack-Signature"),
    body: rawBody,
  });
  if (!verified) return new Response("Invalid Slack signature", { status: 401 });

  const payloadJson = new URLSearchParams(rawBody).get("payload");
  if (!payloadJson) return new Response("", { status: 200 });

  const payload = JSON.parse(payloadJson) as BlockActionsPayload;
  if (payload.type === "block_actions") {
    // Ack now, work later — Slack's window is 3 seconds.
    ctx.waitUntil(handleBlockAction(payload, env));
  }
  return new Response("", { status: 200 });
}

type Decision = "approve" | "decline";

async function handleBlockAction(payload: BlockActionsPayload, env: Env): Promise<void> {
  const action = payload.actions[0];
  if (!action || (action.action_id !== "approve" && action.action_id !== "decline")) return;

  const context = decodeContext(action.value);
  if (!context) return;

  const decision = action.action_id as Decision;
  const decidedBy = payload.user.username ?? payload.user.id;

  await freezeCard(payload, decision, context, env);
  await applyConversationActions(context, actionsFor(decision, decidedBy, env), env);
}

function actionsFor(
  decision: Decision,
  decidedBy: string,
  env: Env,
): ReadonlyArray<Record<string, unknown>> {
  const approved = decision === "approve";
  const outcome = approved
    ? [
        { type: "MESSAGE", content: "Good news — your refund has been approved.", attachments: [] },
        { type: "NOTE", content: `Refund approved in Slack by${decidedBy}.` },
        { type: "CONVERSATION_COMPLETE" },
      ]
    : [
        { type: "MESSAGE", content: "A colleague will take over shortly.", attachments: [] },
        { type: "NOTE", content: `Refund declined in Slack by${decidedBy}.` },
        { type: "NEEDS_HELP", needsHelp: true },
      ];

  return [
    ...outcome,
    {
      type: "CONVERSATION_UPDATE",
      custom: { approvalPending: false, approvalDecided: true, approvalApproved: approved },
      // Empty list clears the override, restoring the button's account default.
      desktop: { customActions: [] },
    },
  ];
}

async function freezeCard(
  payload: BlockActionsPayload,
  decision: Decision,
  context: ApprovalContext,
  env: Env,
): Promise<void> {
  const verdict = decision === "approve"
    ? `:white_check_mark: *Approved* by <@${payload.user.id}>`
    : `:x: *Declined* by <@${payload.user.id}>`;

  await slack("chat.update", {
    channel: payload.channel.id,
    ts: payload.message.ts,
    text: payload.message.text,
    blocks: [
      { type: "section", text: { type: "mrkdwn", text: payload.message.text } },
      { type: "context", elements: [{
        type: "mrkdwn",
        text: context.requestedBy ? `${verdict} · requested by${context.requestedBy}` : verdict,
      }] },
    ],
  }, env.SLACK_BOT_TOKEN);
}

async function applyConversationActions(
  context: ApprovalContext,
  actions: ReadonlyArray<Record<string, unknown>>,
  env: Env,
): Promise<void> {
  const url =
    `https://api.${context.region}.salted.cx/api/v1/live/your-logic` +
    `/accounts/${context.accountId}/conversations/${context.conversationPid}`;

  const response = await fetch(url, {
    method: "POST",
    headers: {
      Authorization: `Bearer${env.YOURLOGIC_SHARED_SECRET}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ actions }),  // no requestId — out of band
  });
  if (!response.ok) {
    throw new Error(`Salted CX rejected actions:${response.status}${await response.text()}`);
  }
}
```

#### [](#python-fastapi)Python (FastAPI)

```python
import json
import os
from urllib.parse import parse_qs

import httpx
from fastapi import BackgroundTasks, Request, Response

SLACK_SIGNING_SECRET = os.environ["SLACK_SIGNING_SECRET"]


@app.post("/slack/interactive")
async def slack_interactive(request: Request, background: BackgroundTasks) -> Response:
    raw_body = await request.body()

    if not verify_slack_signature(
        signing_secret=SLACK_SIGNING_SECRET,
        timestamp=request.headers.get("x-slack-request-timestamp"),
        signature=request.headers.get("x-slack-signature"),
        body=raw_body,
    ):
        return Response(status_code=401, content="Invalid Slack signature")

    fields = parse_qs(raw_body.decode("utf-8"))
    payload_json = fields.get("payload", [None])[0]
    if not payload_json:
        return Response(status_code=200)

    payload = json.loads(payload_json)
    if payload.get("type") == "block_actions":
        # Ack now, work later — Slack's window is 3 seconds.
        background.add_task(handle_block_action, payload)

    return Response(status_code=200)


async def handle_block_action(payload: dict) -> None:
    actions = payload.get("actions") or []
    if not actions:
        return
    action = actions[0]
    if action.get("action_id") not in ("approve", "decline"):
        return

    context = decode_context(action.get("value", ""))
    if context is None:
        return

    approved = action["action_id"] == "approve"
    user = payload.get("user") or {}
    decided_by = user.get("username") or user.get("id") or "someone"
    verdict = (f":white_check_mark: *Approved* by <@{user.get('id')}>"
               if approved else f":x: *Declined* by <@{user.get('id')}>")
    requested_by = context.get("requestedBy")

    await slack("chat.update", {
        "channel": payload["channel"]["id"],
        "ts": payload["message"]["ts"],
        "text": payload["message"]["text"],
        "blocks": [
            {"type": "section",
             "text": {"type": "mrkdwn", "text": payload["message"]["text"]}},
            {"type": "context", "elements": [{
                "type": "mrkdwn",
                "text": f"{verdict} · requested by{requested_by}" if requested_by else verdict,
            }]},
        ],
    }, SLACK_BOT_TOKEN)

    if approved:
        outcome = [
            {"type": "MESSAGE", "content": "Good news — your refund has been approved.",
             "attachments": []},
            {"type": "NOTE", "content": f"Refund approved in Slack by{decided_by}."},
            {"type": "CONVERSATION_COMPLETE"},
        ]
    else:
        outcome = [
            {"type": "MESSAGE", "content": "A colleague will take over shortly.",
             "attachments": []},
            {"type": "NOTE", "content": f"Refund declined in Slack by{decided_by}."},
            {"type": "NEEDS_HELP", "needsHelp": True},
        ]

    # Clear the desktop button override so the agent can request again.
    outcome.append({
        "type": "CONVERSATION_UPDATE",
        "custom": {"approvalPending": False, "approvalDecided": True, "approvalApproved": approved},
        "desktop": {"customActions": []},
    })

    await apply_conversation_actions(context, outcome)


async def apply_conversation_actions(context: dict, actions: list[dict]) -> None:
    url = (
        f"https://api.{context['region']}.salted.cx/api/v1/live/your-logic"
        f"/accounts/{context['accountId']}/conversations/{context['conversationPid']}"
    )
    async with httpx.AsyncClient(timeout=10) as client:
        response = await client.post(
            url,
            json={"actions": actions},  # no requestId — out of band
            headers={"Authorization": f"Bearer{SHARED_SECRET}"},
        )
    response.raise_for_status()
```

### [](#2-6-double-click-and-race-protection)2.6 Double-click and race protection

There are two double-click risks in this flow, at opposite ends:

The agent’s desktop button. Solved by the `Disabled` override you send in the same turn (§5.3) — the button is greyed out before the agent can press it again, and the `approvalPending` flag in `custom` lets you reject a stray press that was already in flight.

The Slack card. Two people can press Approve and Decline within the same second, and Slack does not serialise this for you. The cheapest defence is the `chat.update` in step 1 — replacing the `actions` block removes the buttons, so a second click has nothing to hit. But it is not atomic: a click already in flight still arrives. For anything that moves money, add a real guard:

- Conditional update: call `chat.update` before applying the conversation actions and treat a Slack `message_not_found` / mismatch as “already decided”.

- Idempotency key: key on `payload.message.ts` (unique per card) in a small store — KV, Redis, a database row with a unique constraint. Store the decision on first write; on a duplicate, do nothing.

- Conversation-side flag: the `approvalDecided` flag written in the callback above — ignore clicks whose context snapshot already carries it.

### [](#2-7-what-if-nobody-presses-anything)2.7 What if nobody presses anything?

Slack messages never expire, so an unanswered card sits there forever while the customer waits — and the agent’s desktop button stays disabled, so they cannot even retry. Always pair the card with a timeout:

- Schedule a job (cron, delayed queue, durable timer) for e.g. 15 minutes after posting.

- On fire, check whether a decision was recorded. If not:
    1. `chat.update` the card to “expired — no longer actionable”,
    
    
    2. apply `NEEDS_HELP: true` so a human agent picks the conversation up,
    
    
    3. clear the `<span class="fw-bold">customActions</span>` override so the requesting agent’s button works again.

Do not rely on Salted CX to time this out for you — Your Logic’s own `expires` governs the in-band turn, not your out-of-band approval.

---

## [](#8-verifying-inbound-slack-requests)8. Verifying inbound Slack requests

Slack signs every request. The recipe:

```plain
basestring = "v0:" + X-Slack-Request-Timestamp + ":" + <raw request body>
expected   = "v0=" + hex( HMAC_SHA256( signing_secret, basestring ) )
compare expected against X-Slack-Signature  (constant time)
```

Two non-negotiable details:

1. The body must be the raw bytes, before any framework has parsed or re-serialised it. If your framework consumed the body into a dict, you cannot recompute the signature.

2. Reject timestamps older than 5 minutes. Without this the signature alone permits unlimited replay of a captured request.

### [](#javascript-node)JavaScript (Node)

```javascript
import crypto from "node:crypto";

function verifySlackSignature({ signingSecret, timestamp, signature, body, toleranceSeconds = 300 }) {
  if (!timestamp || !signature) return false;

  const ts = Number.parseInt(timestamp, 10);
  if (!Number.isFinite(ts)) return false;
  if (Math.abs(Math.floor(Date.now() / 1000) - ts) > toleranceSeconds) return false;

  const expected = "v0=" + crypto
    .createHmac("sha256", signingSecret)
    .update(`v0:${timestamp}:${body}`)
    .digest("hex");

  const a = Buffer.from(expected, "utf8");
  const b = Buffer.from(signature, "utf8");
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}
```

### [](#typescript-web-crypto-works-on-workers-deno-bun-and-modern-node)TypeScript (Web Crypto — works on Workers, Deno, Bun and modern Node)

```typescript
export async function verifySlackSignature(options: {
  readonly signingSecret: string;
  readonly timestamp: string | null;
  readonly signature: string | null;
  readonly body: string;
  readonly toleranceSeconds?: number;
}): Promise<boolean> {
  const { signingSecret, timestamp, signature, body } = options;
  if (!timestamp || !signature) return false;

  const tolerance = options.toleranceSeconds ?? 300;
  const ts = Number.parseInt(timestamp, 10);
  if (!Number.isFinite(ts) || Math.abs(Math.floor(Date.now() / 1000) - ts) > tolerance) return false;

  const key = await crypto.subtle.importKey(
    "raw",
    new TextEncoder().encode(signingSecret),
    { name: "HMAC", hash: "SHA-256" },
    false,
    ["sign"],
  );
  const mac = await crypto.subtle.sign("HMAC", key, new TextEncoder().encode(`v0:${timestamp}:${body}`));
  const expected = "v0=" + [...new Uint8Array(mac)].map((b) => b.toString(16).padStart(2, "0")).join("");

  return timingSafeEqual(expected, signature);
}

/** Length-independent, value-constant-time string comparison. */
function timingSafeEqual(a: string, b: string): boolean {
  if (a.length !== b.length) return false;
  let diff = 0;
  for (let i = 0; i < a.length; i++) diff |= a.charCodeAt(i) ^ b.charCodeAt(i);
  return diff === 0;
}
```

### [](#python)Python

```python
import hashlib
import hmac
import time


def verify_slack_signature(
    *, signing_secret: str, timestamp: str | None, signature: str | None,
    body: bytes, tolerance_seconds: int = 300,
) -> bool:
    if not timestamp or not signature:
        return False
    try:
        ts = int(timestamp)
    except ValueError:
        return False
    if abs(int(time.time()) - ts) > tolerance_seconds:
        return False

    basestring = f"v0:{timestamp}:".encode("utf-8") + body
    expected = "v0=" + hmac.new(
        signing_secret.encode("utf-8"), basestring, hashlib.sha256
    ).hexdigest()

    return hmac.compare_digest(expected, signature)
```

---

## [](#9-carrying-conversation-state-through-slack)9. Carrying conversation state through Slack

The round-trip is stateless by design: the Slack button click arrives at a process that may have no memory of posting the card — a new container, a recycled serverless isolate, a different region. There are two ways to bridge the gap.

### [](#option-a-self-contained-recommended)Option A — self-contained (recommended)

Encode everything needed into the button `value`: `accountId`, `region`, `domain`, `conversationPid`, `customerPid`, who requested it, and a snapshot of `conversation.custom`.

```json
{
  "accountId": "a1b2c3d4-0000-1111-2222-333344445555",
  "region": "eu",
  "domain": "demo-adventures.salted.cx",
  "conversationPid": "cnv_5d9c8b7a",
  "customerPid": "cus_7f3a2b19",
  "requestedBy": "Petr Dvorak",
  "custom": { "orderId": "10042", "refundAmount": 129 }
}
```

Base64url-encode the JSON (the codecs are in §2.3) — it stays URL/JSON-safe and Slack will not mangle it.

- Pro: no database, no TTL, no cleanup, survives every kind of restart.

- Con: the 2000-character ceiling, and `custom` is a snapshot — if the conversation moves on between posting the card and the click, blindly restoring it can overwrite newer values. Fine for short-lived approvals; carry only what the decision actually needs.

- Security: the value is base64, not encryption — it is readable by anyone who can inspect the message, and Slack echoes back whatever it was given. Never put secrets or money amounts you will act on unverified in it. Re-read authoritative values (price, balance, entitlement) from your own system after the click, and treat the context purely as an identifier of what to re-check.

### [](#option-b-server-side-store)Option B — server-side store

Put an opaque random key in `value`, store the full context in KV/Redis/SQL under that key with a TTL a little longer than your approval timeout.

Use this when the context genuinely exceeds 2000 characters, or when it contains data that must not leave your perimeter. Cost: infrastructure, expiry handling, and a new failure mode (“the key was evicted before the human clicked”).

### [](#persisting-flags-on-the-conversation-itself)Persisting flags on the conversation itself

`conversation.custom` is a free-form object you own. Write to it with a `CONVERSATION_UPDATE`action; read it back off the next event — including the next agent button press. Use it for state that must survive independently of Slack, and pair it with the toolbar override so the agent sees the same state you are enforcing:

```json
{
  "actions": [
    {
      "type": "CONVERSATION_UPDATE",
      "custom": {
        "slackApprovalMessageTs": "1753351234.123456",
        "approvalPending": true
      },
      "desktop": {
        "customActions": [{ "id": "slack.approval", "status": "Disabled", "title": "Approval pending…" }]
      }
    }
  ]
}
```

---

## [](#10-security-checklist)10. Security checklist

| ✔ | Item |
|---|---|
| ☐ | Bot token and signing secret live in a secret manager, not in source or a `.env` committed to git |
| ☐ | Inbound Your Logic requests: bearer token compared in constant time |
| ☐ | Inbound Slack requests: signature verified over the raw body, timestamp within 5 minutes |
| ☐ | Both endpoints are HTTPS with a valid certificate, and reject non-`POST` |
| ☐ | `ACTION` triggers checked for `participantType` and a known `action` id before acting |
| ☐ | Button `value` contains no secrets — it is base64, not encrypted, and echoes back from Slack |
| ☐ | Amounts / entitlements re-read from your own system after the click, never trusted from the button |
| ☐ | Approver identity checked if it matters: `payload.user.id` against an allowlist, not the channel |
| ☐ | User-controlled text escaped (`&`, `<`, `>`) before entering `mrkdwn` |
| ☐ | Slack token rotated on staff turnover; a leaked `xoxb-` token can post as your company |
| ☐ | Slack failures logged and swallowed — never propagated into the customer conversation |
| ☐ | Approvals de-duplicated by `message.ts` so a double-click cannot double-refund |
| ☐ | Desktop button disabled while a request is in flight, and re-enabled when it resolves |



Two notes on who is allowed to do what:

- Pressing the desktop button is governed by Salted CX’s own per-account action configuration and agent permissions — that is the customer’s admin decision, not something you enforce in code. But do record who pressed (`trigger.agent`) on the timeline and in the Slack card; an approval request with no attributable requester is not auditable.

- Pressing Approve in Slack is access control by convention, not by enforcement — anyone in the channel can press, and anyone added later inherits that power. If approval authority is a real business control, check `payload.user.id` against an explicit allowlist in your own code and reject the click otherwise (update the card with “not authorised” rather than silently ignoring it).

---

## [](#11-testing-and-troubleshooting)11. Testing and troubleshooting

### [](#11-1-local-development)11.1 Local development

Slack must reach your machine over HTTPS. Use a tunnel:

```bash
# Cloudflare Tunnel
cloudflared tunnel --url http://localhost:8787

# or ngrok
ngrok http 8787
```

Paste the resulting `https://…` URL into Interactivity &amp; Shortcuts → Request URL. The URL changes on every restart unless you use a named tunnel — configure one to avoid re-pasting.

### [](#11-2-simulating-an-agent-button-press)11.2 Simulating an agent button press

You do not need the agent desktop to test leg A — replay the `ACTION` event yourself:

```bash
curl -X POST https://your-service.example.com/yourlogic \
  -H "Authorization: Bearer$YOURLOGIC_SHARED_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "requestId": "test-1",
    "accountId": "a1b2c3d4-0000-1111-2222-333344445555",
    "time": "2026-07-24T10:15:30Z",
    "expires": "2026-07-24T10:16:00Z",
    "domain": "demo-adventures.salted.cx",
    "region": "eu",
    "trigger": { "type": "ACTION", "participantType": "AGENT",
                 "time": "2026-07-24T10:15:29Z",
                 "action": "slack.approval", "agent": "agt_test" },
    "customer": { "pid": "cus_test", "displayName": "Jana Novak", "contacts": [] },
    "conversation": { "pid": "cnv_test", "startConversationTime": "2026-07-24T10:14:02Z",
                      "needsHelp": false, "status": "IN_PROGRESS",
                      "defaultChannel": "web-chat", "direction": "INBOUND",
                      "custom": { "orderId": "10042", "refundAmount": 129 } },
    "engagements": [
      { "pid": "eng_test", "time": "2026-07-24T10:14:40Z", "type": "AGENT",
        "status": "IN_PROGRESS",
        "agent": { "pid": "agt_test", "type": "HUMAN", "name": "Petr Dvorak" } }
    ],
    "turns": []
  }'
```

Change `trigger.action` to `slack.announce` to exercise use case 1. Note that `conversation.custom`must carry the order/amount — that is exactly the precondition §2.2warns about, and testing without it verifies your “missing data” `NOTE` path.

### [](#11-3-previewing-a-card-before-you-ship-it)11.3 Previewing a card before you ship it

Paste your `blocks` array into [Block Kit Builder](https://app.slack.com/block-kit-builder) — it renders live and reports schema errors precisely. Far faster than iterating through `invalid_blocks`.

### [](#11-4-symptom-table)11.4 Symptom table

| Symptom | Cause | Fix |
|---|---|---|
| Agent presses the button, nothing happens anywhere | `ACTION` trigger not enabled for the endpoint, or the id does not match | Check Salted CX config; log every inbound `trigger.action` |
| Button press reaches you but is ignored | `trigger.action` differs from your constant (renamed in admin) | Read the id from config, not source; log the mismatch |
| Button not visible in the desktop | Custom action not configured, or a stale `Hidden` override | Clear the override with an empty `customActions` list |
| Button stuck greyed out | A `Disabled` override was never cleared | Send `desktop.customActions: []`; add a timeout path |
| Slack “Request URL didn’t respond in time” when saving | Endpoint not deployed, or slower than 3 s | Deploy first, ack before doing work |
| `{"ok": false, "error": "not_in_channel"}` | Bot not a member | `/invite @app`, or add `chat:write.public` |
| `{"ok": false, "error": "channel_not_found"}` | Wrong ID, or private channel | Use the channel ID; invite the bot |
| `{"ok": false, "error": "missing_scope"}` | Scope not granted | Add scope, reinstall the app |
| `{"ok": false, "error": "invalid_blocks"}` | Malformed Block Kit | Validate in Block Kit Builder |
| Signature verification always fails | Body was parsed/re-serialised before hashing | Hash the raw bytes |
| Signature fails only sometimes | Server clock drift | Sync NTP; the tolerance is 5 min |
| Slack button click shows a red error | Handler exceeded 3 s | Ack first, background the work |
| Card posted twice | Agent pressed twice before the button was disabled | Disable the button in the same turn as the post |
| Salted CX returns 401 on leg D | Wrong or missing bearer token | Same shared secret as leg A |
| Salted CX returns 404 on leg D | Wrong `accountId` / `conversationPid` / region in the URL | Read all three from the event |
| Actions accepted but nothing visible | `requestId` sent out of band, or turn already expired | Omit `requestId` for out-of-band calls |



---

## [](#12-reference-tables)12. Reference tables

### [](#12-1-trigger-types)12.1 Trigger types

Inbound `trigger.type` values. Treat the set as open — acknowledge unknown types with `200`.

| Type | Fires when |
|---|---|
| `ACTION` | A named action fired — including an agent pressing a custom desktop button. The entry point for both use cases here. |
| `MESSAGE` | A chat message was sent (`participantType` says by whom) |
| `EMAIL` | An email arrived on the conversation (carries `subject`) |
| `QUESTION` / `QUESTION_DYNAMIC` | A question was posed |
| `ANSWER` | A question was answered (`questionId` / `answerId`) |
| `TEMPLATE` | A WhatsApp template message was sent |
| `NOTE` | An internal note was added |
| `FILE` / `IMAGE` / `AUDIO` / `VIDEO` | Media was uploaded |
| `REVIEW` | A CSAT / review event |
| `CONVERSATION_OFFERED` | The conversation was offered to agents |
| `CONVERSATION_COMPLETE` | The conversation finished |
| `CONVERSATION_UPDATE` | Conversation attributes or `custom` changed |
| `CONVERSATION_INACTIVE` | No activity for the configured period |
| `ENGAGEMENT_COMPLETE` | One agent/bot engagement ended |



### [](#12-2-the-action-trigger)12.2 The `ACTION` trigger

| Field | Type | Meaning |
|---|---|---|
| `type` | `"ACTION"` | Discriminant |
| `participantType` | `AGENT` / `EXTERNAL_AGENT` / `BOT` / `CUSTOMER` / `UNKNOWN` | Who caused it — filter on the agent kinds |
| `time` | ISO-8601 | When it fired |
| `action` | string | The configured custom-action id — your switch key |
| `agent` | string \| null | Pid of the agent; resolve a name via `engagements[]` |



### [](#12-3-action-types)12.3 Action types

Outbound `actions[].type` values, with the fields these use cases need.

| Type | Key fields | Effect |
|---|---|---|
| `MESSAGE` | `content`, `attachments`, `channel?`, `contactPid?` | Sends a message to the customer |
| `NOTE` | `content`, `responseTo?` | Internal note on the timeline — invisible to the customer |
| `NEEDS_HELP` | `needsHelp`, `targetAgentPid?`, `timeout?`, `onTimeout?` | Escalates to a human agent |
| `CONVERSATION_UPDATE` | `custom`, `desktop`, `urgency?`, `info?`, `attributes?` | Writes conversation state and controls the toolbar buttons |
| `QUESTION` | `questionPid`, `allowCustomReply?` | Poses a pre-configured question |
| `QUESTION_DYNAMIC` | `question: { externalId, content, answers[] }` | Poses an ad-hoc question with answer options |
| `CUSTOMER_UPDATE` | `countryExternalId?`, `segmentExternalId?`, … | Updates customer classification |
| `EMAIL` | `contactPid`, `subject`, `body`, `attachments?` | Sends an email to an email contact |
| `SEND_FILE` | `path`, `name`, `mimeType` | Sends a file to the customer |
| `INVITE_EXTERNAL_AGENT` | `email`, `name`, `subject`, `expires` | Invites a partner into the conversation |
| `ENGAGEMENT_COMPLETE` | `engagementPid`, `outcome*?`, `reason*?` | Closes one engagement with an outcome |
| `CONVERSATION_COMPLETE` | — | Closes the conversation |
| `ENGAGE_YOUR_LOGIC` | `engageYourLogic` | Turns the bot on/off for this conversation |
| `NO_ACTION` | — | Explicit no-op — acknowledges the turn without doing anything |



### [](#12-4-desktop-button-control-conversation-update-desktop)12.4 Desktop button control (`CONVERSATION_UPDATE.desktop`)

| Field | Shape | Purpose |
|---|---|---|
| `customActions` | `[{ id, status, title? }]` | Per-account buttons — `status` is `Disabled` or `Hidden` |
| `attributes` | `[{ id, status }]` | Per-account display fields |
| `actions` | `{ leave?, resolve?, waitForCustomer?, askForHelp?, inviteExternal? }` | Standard buttons; each `{ status }` is `Hidden` / `Disabled` / `Enabled` |
| `defaultReply` | `{ title?, subject?, message }` | Pre-fills the agent’s composer |



Custom actions and attributes carry only `Disabled` / `Hidden`. To restore a button’s default, omit its entry (or send an empty `customActions` list) rather than sending an `Enabled` status.

### [](#12-5-endpoints)12.5 Endpoints

| Purpose | Method + URL |
|---|---|
| Apply actions to a conversation (in and out of band) | `POST https://api.{region}.salted.cx/api/v1/live/your-logic/accounts/{accountId}/conversations/{conversationPid}` |
| Post a Slack message or card | `POST https://slack.com/api/chat.postMessage` |
| Edit an existing Slack message | `POST https://slack.com/api/chat.update` |
| Post an ephemeral (single-viewer) Slack message | `POST https://slack.com/api/chat.postEphemeral` |



### [](#12-6-environment-variables)12.6 Environment variables

| Name | Value | Source |
|---|---|---|
| `YOURLOGIC_SHARED_SECRET` | Bearer token for legs A and D | You generate; give to Salted CX |
| `SLACK_BOT_TOKEN` | `xoxb-…` | Slack → OAuth &amp; Permissions |
| `SLACK_SIGNING_SECRET` | Hex string | Slack → Basic Information |
| `SLACK_CHANNEL_ID` | `C0123ABCDEF` — announcements | Slack → channel → About |
| `SLACK_APPROVAL_CHANNEL_ID` | `C0456DEFGHI` — approvals | Slack → channel → About |
| `SALTED_ACTION_ANNOUNCE` | `slack.announce` | Salted CX admin — custom action id |
| `SALTED_ACTION_APPROVAL` | `slack.approval` | Salted CX admin — custom action id |



---

## [](#further-reading)Further reading

- [Slack Block Kit reference](https://api.slack.com/reference/block-kit/blocks)

- [Slack Block Kit Builder](https://app.slack.com/block-kit-builder) — live preview

- [Slack ](https://api.slack.com/methods/chat.postMessage)`chat.postMessage` · `chat.update`

- [Slack interactivity handling](https://api.slack.com/interactivity/handling)

- [Verifying requests from Slack](https://api.slack.com/authentication/verifying-requests-from-slack)

- [Slack OAuth scopes](https://api.slack.com/scopes)

- [Slack rate limits](https://api.slack.com/apis/rate-limits)

---

## Demo Adventures

Source: https://help.salted.cx/en/articles/1770452728-demo-adventures


Article short description

Demo Adventures is a company that uses Salted CX to automate their contact center.

[Option One 1](/2fd5d3a2a8dc806b8288e7299a6a60ed)

[Option 2](/2fd5d3a2a8dc80be8e86fdc94c6e6274)

---

## Dynamic Agent Desktop

Source: https://help.salted.cx/en/articles/1781867273-dynamic-agent-desktop


Article short description

Your bot can also interact with the agent desktop to better focus agent attention, offer agents more relevant choices in a given situation, and enforce your processes. You can disable or hide controls in the agent user interface.

You can control these things:

- What [custom buttons](https://help.salted.cx/en/articles/1759298233-live-conversations-toolbar) the agents see and whether they are enabled or disabled

- What conversation attributes the agents see and whether they can edit them

- Hide or disable built-in buttons

- Suggested reply the agent can use (or ignore)

Update to the user interface can be part of the `CONVERSATION_UPDATE` event. You can combine the update to the agent desktop with other updates or other actions. See the code sample

```json
{
	"requestId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
	
	"actions": [
		{
			"type": "CONVERSATION_UPDATE",
			"desktop": {
				"defaultReply": {
					"title": "Optional description of the default reply",
					"subject": "Optional subject for emails",
					"message": "Body that shows in the agent reply field"
				},
				
				"toolbar": [
					{
						"type": "action",
						"id": "escalate.legal",
						"status": "Disabled"
					},
					{
						"type": "attribute",
						"id": "queue",
						"status": "Disabled"
					},
					{
						"type": "action",
						"id": "escalate.privacy",
						"status": "Hidden"
					}
				],
				
				"leave": "Disabled",
				"resolve": "Disabled",
				"waitForCustomer": "Disabled",
				"askForHelp": "Hidden",
				"inviteExternal": "Enabled"
			}
		}
	]
}
```

Example action that updates the ## [](#control-custom-buttons-and-attributes)Control Custom Buttons and Attributes

TODO

---

## External Agents

Source: https://help.salted.cx/en/articles/1759322910-external-agents


Article short description

External agents are people that you invite to handle conversations even when they do not have user account in Salted CX. External agents can be partners whose products or services you resell, or they can a large pool of people to handle specific requests in a virtual contact center.

You can invite customer agents to conversations to help to resolve with the customer.

---

## KV

Source: https://help.salted.cx/en/articles/kveta


Article short description

Ahoj

---

## Setup Email in Google Workspace

Source: https://help.salted.cx/en/articles/1761337783-setup-email-in-google-workspace


![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

You will need access to the management of DNS records for your company's domain to finish the email setup. If you cannot edit DNS records for your domain, ask your IT department to do the changes for you.





Salted CX can automatically handle your emails, respond to customers and help users within Salted CX to interact with the customer via email.

You need to allow Salted CX to handle your email in the following steps:

- Identify an email address you want Salted CX to handle such as [support@company.com](mailto:support@yourcompany.com), [help@company.com](mailto:help@yourcompany.com) or similar. Salted CX will process all incoming emails to that address and use the address for sending emails. You can connect Salted CX to multiple emails.

- Enable Salted CX to send emails from your email address on you behalf.

- Forward incoming email messages from your infrastructure to Salted CX.

You can easily revoke Salted CX using your email address if you change your mind.

## [](#how-salted-cx-uses-the-email)How Salted CX Uses the Email

Salted CX sends emails on your behalf from the address when:

- A human agent sends the customer an email message.

- AI sends an email message to a customer based on received customer message.

For each sent message, Salted CX sets the response value to the same email. This means that the customers can always respond to the email they receive from Salted CX.

This setup includes enabling DKIM, SPF, and DMARC to ensure the deliverability of your email, and it is handled as authentic and verified by email clients. Salted CX listens for bounced emails (emails that do not find a recipient) and marks the corresponding message turns in the customer journey as failed.

![](https://www.notion.so/icons/warning_yellow.svg?mode=light)

Salted CX watches the reputation of the email to prevent sending spam. If your emails have a high number of bounced and undelivered emails, we will reach out to you. If this problem persists and Salted CX determines misuse of its services, we will disable email functionality for your account.





## [](#email-behavior)Email Behavior

Salted CX never uses “no reply” email addresses. Each message sent from Salted CX allows the customer to reach back. We believe this is a proper behavior for any company that values its customers and enables them to tie any follow-up conversation to outbound messages.

## [](#brand-setup)Brand Setup

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

Each brand has its default email address that looks like ebd1fcda-376d-4f33-9cb7-654346983cb5@eu.salted.help. You can use this email for testing purposes. However, for production use, you definitely want to use your own email domain.





Make sure you choose an email address that can be used exclusively by Salted CX to avoid unexpected behavior.

## [](#dns-setup)DNS Setup

DNS setup enables us to send emails on your behalf. Please contact Salted CX to obtain the information needed to set up DNS.

For

## [](#forward-incoming-emails-to-salted-cx)Forward Incoming Emails to Salted CX

You need to forward emails from your email provider (such as Gmail or Outlook) to Salted CX so they appear in Live Conversations. The setup depends on the email provider.

![](https://www.notion.so/icons/warning_yellow.svg?mode=light)

Do not use mailing lists such as Google Groups. Mailing lists often obscure the original customer email and prevent connecting the email conversation to a [customer journey](https://help.salted.cx/en/collections/1755250527-customer-journey).





![](https://www.notion.so/icons/warning_yellow.svg?mode=light)

Make sure the Salted CX address in your forwarded emails uses your desired region. The address should end like this: eu.salted.help or us.salted.help with the region included in the domain name.





### [](#google-workspace)Google Workspace

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

You need Google Workspace admin permissions to enable email forwarding. It can take up to 24 hours for email forwarding to take effect. Usually, the changes are applied much faster.





You can use these [Google-provided instructions](https://support.google.com/a/answer/10486484?product_name=UnuFlow&hl=en&hl=en&visit_id=638690871651590812-3129432273&rd=1&src=supportwidget0) as a reference or follow them for guidance.

Follow these steps to enable forwarding:

1. Go to [Default Routing Settings](https://admin.google.com/ac/apps/gmail/defaultrouting) in Your Google Workspace Admin, log in when asked. Alternatively you can open the Default Routing Settings from Admin Console by clicking Apps ![:r1:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/cbece7ea-90d1-42be-b944-7d3a40472c0a/Circle_1.png) ⏵ Google Workspace ![:r2:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/828ec6f6-6da7-41e1-ab7d-81f376318b90/Circle_2.png) ⏵ Gmail ![:r3:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/6a0e6eb2-4742-4445-80a6-8be77bab104f/Circle_3.png) ⏵ Default Routing ![:r4:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/49964e58-e0e9-40b5-b973-00c416e5d0bc/Circle_4.png)![](https://media.notiondesk.so/upload/6971d12e5acaf489128896.png)

2. Click Configure

3. In the Add Setting dialog, fill your support email (such as support@company.com) into Email ![:r5:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/a8d7fc85-01c2-4beb-ae57-18073a27a40e/Circle_5.png) field in Specify envelope recipients to match section.![](https://media.notiondesk.so/upload/6971d135cea47270760289.png)

4. In Envelope recipient section section check Change envelope recipient ![:r6:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/22961b53-f52d-4017-87e3-e0ab43ddd029/Circle_6.png)

5. Choose Replace Recipient ![:r7:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/9e5e9e5f-9b80-4656-8d16-a78ef863eb57/Circle_7.png) option.

6. Paste your Salted CX email address from brand settings to Enter new email address ![:r8:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/bd34cd7e-cbac-4650-9d97-2a4412a47520/Circle_8.png) field.

7. Click Save ![:r9:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/72b59471-92ba-446c-94f7-8d19849cfc6a/Circle_9.png).

8. Click Edit on the rule you have just created.

9. Make sure that the option in Options section is set to Perform this action on non-recognized and recognized addresses.

You can try sending an email to your support address and check that it ends up in Salted CX. Please note that it may take up to 24 hours for the change to take effect.

---

## Setup Salesforce Integration

Source: https://help.salted.cx/en/articles/1769877319-setup-salesforce-integration


Salted CX retrieves data to be able to analyze them. You need to enable access of Salted CX to Salesforce. During this process, you will need to collect information that is necessary. When you encounter this information, store this information securely and share it with Salted CX.

Salted CX needs the following information to connect to Salesforce:

- [Consumer Key](https://help.salted.cx/en/articles/1769877319-setup-salesforce-integration#063b5e9874924c3487458122b25e198e)

- [Customer Secret](https://help.salted.cx/en/articles/1769877319-setup-salesforce-integration#667516581799447da56c18886d3b4614)

- [Salesforce API User Username](https://help.salted.cx/en/articles/1769877319-setup-salesforce-integration#669a7ed3251543dcb7ae6bad390cf079)

- [Salesforce API User Password](https://help.salted.cx/en/articles/1769877319-setup-salesforce-integration#ace4ec3658c64358be0722775fce3847)

- [Salesforce API User Secret Token](https://help.salted.cx/en/articles/1769877319-setup-salesforce-integration#33bccd0733c845d9aaa61b30a633b2b3)

To enable access to Salesforce and collect all necessary information you will go through the following steps:

- [Add Connected Application](https://help.salted.cx/en/articles/1769877319-setup-salesforce-integration#1139e90e665440ecb79dddb937b94a30). This adds Salted CX as an application to Salesforce. Only connected applications can retrieve data from Salesforce.

- [Create Salesforce Profile](https://help.salted.cx/en/articles/integration-salesforce#1139e90e665440ecb79dddb937b94a30). This profile in Salesforce will contain all permissions that Salted CX has when accessing Salesforce.

- [Create Salesforce API User](https://help.salted.cx/en/articles/integration-salesforce#1139e90e665440ecb79dddb937b94a30). Salted CX will use this credentials to log into your Salesforce instance. The user also serves as a single point that can be deleted to remove access to data from Salted CX.

- [Retrieve Secure Token](https://help.salted.cx/en/articles/integration-salesforce#24b785655b4a4578b827365b1c874274). This token is used by Salted CX for authorization against the API.

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

This guide is an example Salesforce setup. You might use different methods of giving access to your Salesforce. The critical part for Salted CX to work properly is to have read-only access to Bulk Export API 2.0 and permission to access setup and configuration API that is used to prevent hitting Salesforce rate limits for the API use.





# [](#add-connected-application)Add Connected Application

Connect Salted CX do the following steps in your Salesforce:

![](https://media.notiondesk.so/upload/689de849f177a003645404.png)

1. When logged in to your Salesforce, press gear button in the top right corner

2. In the menu press Setup

3. In the Setup application, press the Quick Find field in the top right corner and search for App Manager

4. Press App Manager in the navigation to open it![](https://media.notiondesk.so/upload/689de84d09e18463470345.png)

5. Press New Connected App button in the top right corner![](https://media.notiondesk.so/upload/689de84f2ac7d128078576.png)

6. Type Salted CX Integration into the Connected App Name

7. API Name will be automatically filled by Salesforce based on the name above, leave it as it is

8. Type support@salted.cx into Contact Email![](https://media.notiondesk.so/upload/689de8516706e363367253.png)

9. In the Enable OAuth Settings section check Enable OAuth Settings

10. Although Callback URL is mandatory it is not important for the integration. Just use [https://www.salesforce.com](https://www.salesforce.com/) or any other URL

11. In Selected OAuth Scopes section in Available OAuth Scopes choose Manage user data via APIs and press Add right arrow to add the scope into Selected OAuth Scopes![](https://media.notiondesk.so/upload/689de853a35d5888100299.png)

12. Press Save button, keep the other settings as they are![](https://media.notiondesk.so/upload/689de855c4d30788422371.png)

13. Press Continue button![](https://media.notiondesk.so/upload/689de857e3b30995605064.png)

14. In API (Enable OAuth Settings) section press Manage Consumer Details button in the first line

15. Open your email inbox and copy the received verification code from Salesforce![](https://media.notiondesk.so/upload/689de85bdb7d3892545121.png)

16. Paste the copied code to Verification Code field

17. Press Verify button![](https://media.notiondesk.so/upload/689de85e30644105798389.png)

18. Press Copy button in Consumer Key line and safely store it

19. Press Copy button in Consumer Secret line and safely store it

# [](#create-salesforce-profile)Create Salesforce Profile

The following steps create a Salesforce profile that limits access of Salted CX integration to Salesforce features and data. These instructions focus on giving minimal necessary access to Salted CX:

1. When logged in to your Salesforce, press gear button in the top right corner![](https://media.notiondesk.so/upload/689de860a9233096895856.png)

2. In the menu press Setup

3. In the Setup application, press the Quick Find field in the top right corner and search for Profiles

4. Press Profiles in the navigation to open it

5. Press New Profile

6. In Existing Profile choose Salesforce API Only System Integrations![](https://media.notiondesk.so/upload/689de8631533f760250011.png)

7. Type `Salted CX Profile` into Profile name field

8. Press Save

9. Press Edit![](https://media.notiondesk.so/upload/689de86553682157690272.png)

10. Uncheck everything you can in Custom App Settings![](https://media.notiondesk.so/upload/689de8680147b691985931.png)

11. Uncheck everything you can in Connected App Access

12. In Administrative Permissions uncheck everything you can EXCEPT:
    - API Enabled
    
    
    - Lightning Experience User (temporarily useful for this setup)
    
    
    - View Roles and Role Hierarchy
    
    
    - View Setup and Configuration
    
    ![](https://media.notiondesk.so/upload/689de86a5a907004613239.png)

13. Make sure Api Only User checkbox in unchecked (UI access is needed later in the setup, can be disabled later)

14. In General User Permissions uncheck everything you can![](https://media.notiondesk.so/upload/689de86d18f71841368894.png)

15. In Standard Object Permissions section make sure the following objects have Read and VIew All checkboxes checked:
    - Accounts
    
    
    - Agent Work
    
    
    - Assets
    
    
    - Call Disposition
    
    
    - Call Disposition Category
    
    
    - Campaigns
    
    
    - Cases
    
    
    - Case Comment
    
    
    - Case History
    
    
    - Contacts
    
    
    - Customers
    
    
    - Chat Sessions
    
    
    - Chat Transcripts
    
    
    - Chat Visitors
    
    
    - Email Messages
    
    
    - Group
    
    
    - Leads
    
    
    - Live Chat Transcript
    
    
    - Messaging Sessions
    
    
    - Messaging Users
    
    
    - Opportunities
    
    
    - Products
    
    
    - Profile
    
    
    - Record Type
    
    
    - Queues
    
    
    - Queued Parties
    
    
    - Queue Messaging Template
    
    
    - Refunds
    
    
    - Service Channel
    
    
    - Shifts
    
    
    - Surveys
    
    
    - Survey Invitations
    
    
    - Survey Question Choice
    
    
    - Survey Question Response
    
    
    - Survey Responses
    
    
    - Survey Subjects
    
    
    - Tasks
    
    
    - User Service Presence
    
    
    - Work Orders
    
    ![](https://media.notiondesk.so/upload/689de86f9b9d4172028969.png)
    
    ![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)
    
    You can enable access to more objects than listed above. The listed objects are those that Salted CX expect access to. Enabling access to more objects prevents you from having to update the profile in case there are new features in Salted CX that require additional objects. Salted CX does not hoard data. It downloads only data necessary to support its current set of features.

16. In Password Policies for User passwords expire in choose Never Expires![](https://media.notiondesk.so/upload/689de871b9ca1806766942.png)

17. Press Save

Now you have a profile that is a single place where you can manage what Salted CX can access.

# [](#create-salesforce-api-user)Create Salesforce API User

Create Salesforce user that Salted CX will use to access the API in these steps:

1. Search for Users in the left navigation in Setup![](https://media.notiondesk.so/upload/689de873f1c82178099836.png)

2. Press Users

3. Press New User

4. Fill in mandatory user information![](https://media.notiondesk.so/upload/689de8764eef1526412707.png)

5. Make sure you fill an email address you have access to. You will use it to get a new Security Token

6. Leave Role value set to &lt;None Specified&gt;

7. Choose Salesforce in the User License menu

8. Choose the created Salted CX Profile in the Profile menu

9. Press Save

10. Log in as the newly created user, and set or reset your password if necessary

11. Securely store the user’s username and password to share it with Salted CX

Now you have a user that will be used by Salted CX to download data from Salesforce.

# [](#get-new-security-token)Get New Security Token

The security token is used by Salted CX to authenticate in Salesforce. The security token is part of credentials for API access to your data in Salesforce.

Follow these steps to retrieve the Security Token for the API user:

1. Log into Salesforce under the user create in the step [Create Salesforce API User](https://help.salted.cx/en/articles/1769877319-setup-salesforce-integration)

2. Press the user avatar in the top right corner![](https://media.notiondesk.so/upload/689de878a52db608251287.png)

3. Press Settings in the menu

4. In the navigation on the left press Reset My Security Token

5. Press Reset Security Token button on the screen

6. Check you email inbox, you will receive the Security Token, copy it and safely store it

After you retrieve the Security Token you can disable access to the UI for the API user1. Go to Salted CX Profile created in the step [Add Connected Application](https://help.salted.cx/en/articles/1769877319-setup-salesforce-integration)

2. Press Edit

3. Check Api user only checkbox in Administrative Permissions

4. Uncheck Lightning Experience User in Administrative Permissions

5. Press Save





# [](#credentials)Credentials

Now you should have all information necessary for Salted CX to connect to your Salesforce. Please share all the credentials with Salted CX safely.

---

## Voice Scenarios

Source: https://help.salted.cx/en/articles/1778913582-voice-scenarios


## [](#vocabulary)Vocabulary

Join Conversation — The agent opens the conversation, but this does not imply being part of the conversation.

Answer — The agent is the first one joining the call, which has impact on transitioning the customer between states.

Join Call — The agent joins the call.

Leave Call — Stopping the participation in a call without impacting the other participants. Leave applies only to agents/bots, not the customer.

Hang Up — Ending the call for all participants. No one stays on the call.

Listen — A user joins the call, nobody else hears them, but they hear everybody.

Whisper — A user joins the call, customers cannot hear them, but other agents can.

Mute — The call is muted. The customers do not hear the agents. The customer listens to the music. Agents do not hear the customers.

## [](#open-questions)Open Questions

1. End of queue engagement — on join vs. on answer

2. Preparation time — we should measure it between join and answer

3. Engagement Type of joining the conversation — “Agent” by default and switch to “Supervise” on whisper listen

4. Use engagement type = `Supervise` also for other engagements in which the customer does not respond to anything

## [](#general-rules)General Rules

- Agents who listen or whisper are not considered handling the customer. This means their presence does not influence whether the customer transitions to needs help, etc.

- We never hang up from our own initiative. Always considered an error on our side. There are 3 options how the call is hangup:
    - Customer hangs up.
    
    
    - Agent hangs up.
    
    
    - Bot tells us to hang up.

- Customer never leaves the call, but always hangs up. Calls do not continue after the customer hangup or after the customer is in any way kicked out of the conversation.
    - Outbound

- When customer is the only on the phone. The conversation MUST be in Needs Help (no matter its state — customer can be talking, on hold)

- During hold customer does not hear any agent. Any agent including bot does not hear the customer. Customer hears music. Also no party should be recorded during hold.

- 

## [](#abandoned-inbound-call-no-voice-bot-in-place)Abandoned Inbound Call (no Voice Bot in Place)

The customer calls, no bot is set up, and the customer hangs up before the agent gets to join the conversation.

See [Untitled](/3595d3a2a8dc80d59e18e0a260bf8434)

1. Customer calls in

2. Live Conversations show customer in Needs Help

3. Customer hangs up

4. Live Conversation disappears from Live Conversations

5. NNNNN The conversation will appear in Reach back

| Type | Start | End | Outcome Type | Agent |
|---|---|---|---|---|
| Queue | 1 | 3 | Customer Left | — |



## [](#abandoned-inbound-call-after-agent-joined)Abandoned Inbound Call After Agent Joined

1. Customer calls in

2. Live Conversations show customer in Needs Help

3. Agent Joins the Conversation

4. Customer hangs up

5. Live Conversation disappears from Live Conversations

6. Agent Starts Outbound Call

7. NNNNN The conversation will appear in Reach back

## [](#agent-leaves-the-covnersation)Agent Leaves the Covnersation

## [](#abandoned-outbound-call)Abandoned Outbound Call

1. Agent starts a New Conversation

2. Agent starts a call

3. Agents hangs up

4. Agent leaves the conversation

| Type | Start | End | Outcome Type | Agent |
|---|---|---|---|---|
| Agent | 1 | 3 | Agent Hangup | — |



## [](#inbound-bot-only-call)Inbound Bot-Only Call

The customer calls in, and the call is handled simply by a bot; no escalation to a person happens.

1. Customer calls in

2. Live Conversations — Forward the customer to the voice bot

3. Live Conversations — The conversations shows in All in Progress

4. … Voice Bot — Talks to the customer

5. Customer (or Voice Bot) — Hangs up the call

| Type | Start | End | Outcome Type | Agent |
|---|---|---|---|---|
| Agent | 1 | 3 | Resolved | Voice Bot |



## [](#bot-with-escalation-to-an-agent)Bot With Escalation to an Agent

This is actually a cold transfer from a bot.

1. Customer — Calls in

2. Live Conversations — Forward the customer to the voice bot

3. Live Conversations — The conversations shows in All in Progress

4. Voice Bot — Asks for help

5. Live Conversations — The conversation shows in Needs Help

6. Agent #1 — Clicks Join

7. Agent #1 — Clicks Answer

8. … agent and customer talk

9. Customer — Hangs up

10. Agent is kicked out of the call (wrap up phase starts)

11. Agent clicks Resolve

| Type | Start | End | Outcome Type | Agent |
|---|---|---|---|---|
| Agent | 1 | 3 | Resolved | Voice Bot |
| Queue | 4 | 6 | Accepted | — |
| Agent | 6 | 11 | Resolved | Agent #1 |



## [](#escalation-while-listening)Escalation while Listening

An agent escalates to another agent while somebody is listening.

1. …

2. Agent #1 — Joins Conversation

3. Agent #1 — Answers Call

4. …

5. Agent #2 — Joins Conversation

6. Agent #2 — Listens to Conversation

7. 

| Type | Start | End | Outcome Type | Agent |
|---|---|---|---|---|
| Agent | 1 | 3 | Resolved | Voice Bot |
| Queue | 4 | 6 | Accepted | — |
| Agent | 6 | 11 | Resolved | Agent #1 |



## [](#inbound-call-cold-transfer)Inbound Call Cold Transfer

1. …

2. Agent #1 — Joins the conversation

3. Agent #1 — Answers the phone

4. …

5. Agent #1 — Asks for help

6. Live Conversations — The conversation shows in Needs Help

7. Agent #1 — Leaves the call

8. Agent #1 — Leaves the conversation

9. …

10. Agent #2 — Joins the conversation

11. Agent #2 — Answers the phone

12. …

13. 

| Type | Start | End | Outcome Type | Agent |
|---|---|---|---|---|
| Agent | 1 | 7 | Agent Left | Agent #1 |
| Queue | 6 | 11?? | Accepted | — |
| Agent | 10 | after 12 | Resolved | Agent #2 |



## [](#listening-whisper)Listening, Whisper

1. …

2. Agent #1 — Joins the conversation

3. Live Conversations — Remove conversation from Needs Help

4. Agent #1 — Answers the call

5. …

6. Agent #2 — Joins the Conversation

7. Agent #2 — Listens to the call

8. …

9. Agent #1 — Leaves the call

10. Live Conversations — Put the conversation to Needs Help

11. Agent #2 — Leaves the call

12. Agent #2 — Leaves the engagement

| Type | Start | End | Outcome Type | Agent |
|---|---|---|---|---|
| Agent | 2 | 7 | Agent Left | Agent #1 |
| Supervisor | 6 | 11 | Accepted | — |
| Queue | 9 | after 12 | Resolved | Agent #2 |



## [](#from-whisper-to-join-call)From Whisper to Join Call

The supervisor first just listens to a conversation but then decides to join a conversation.

1. …

2. Agent #1 — Joins the conversation

3. Agent #1 — Answers the phone

4. …

5. Agent #2 — Joins the conversation

6. Agent #2 — Whispers to conversations

7. …

8. Agent #1 — Leaves the call

9. Live Conversations — Wrap Up starts

10. Agent #1 — Completes the conversation

11. Live Conversations —

12. Live Conversations — Shows conversation in Needs Help

13. Agent #3 — Joins the Conversation

14. Agent #3 — Joins the Call

15. Agent #2 — Leaves the Conversation

16. Agent #3 — Leaves the Call

17. Agent #3 — Leaves the Conversation

| Type | Start | End | Outcome Type | Agent |
|---|---|---|---|---|
| Agent | 2 | 8 | Agent Left | Agent #1 |
| Supervisor | 5 | 15 | Accepted | Agent #2 |
| Queue | 9 | 13 | Accepted | — |
| Agent | 13 | 17 | Resolved | Agent #3 |



## [](#customer-hangup-before-bot-picks-up)Customer Hangup Before Bot Picks Up

TODO

## [](#successful-inbound-voice-with-bot)Successful Inbound Voice with Bot

TODO

1. Customer Calls In

2. Bit picks up

3. Customer hangs up

| Type | Start | End | Outcome Type | Agent |
|---|---|---|---|---|
| Agent | 2 | 3 | Handled | Agent #1 |



## [](#customer-hang-after-escalation)Customer Hang after Escalation

TODO

## [](#escalated-inbound-voice-with-bot)Escalated Inbound Voice with Bot

TODO

## [](#listen-to-a-bot-conversation)Listen to a Bot Conversation

TODO

## [](#elevenlabs-fail-leads-to-customer-waiting-in-the-queue)ElevenLabs Fail Leads to Customer Waiting in the Queue

TODO

## [](#null)

---

## Working with Live Conversations in Groupon

Source: https://help.salted.cx/en/articles/live-conversations-groupon-agents


Article short description

Live Conversations in Groupon are conversations from the Groupon FAQ page that got escalated from a chatbot. These escalated conversations will not be handled in Salesforce to improve the experience for both customers and agents and to better integrate with the bot.

## [](#collaboration-ai-chatbot-pilot)Collaboration — [AI Chatbot Pilot](https://mail.google.com/mail/u/0/#chat/space/AAQAnuarLAw)

Join the [AI Chatbot Pilot](https://mail.google.com/mail/u/0/#chat/space/AAQAnuarLAw) Google Space, which we will use to collaborate among all agents, team leaders, and Salted CX team members. We hope that having this space will help resolve any issues more quickly.

Please add your feedback and suggestions to this [Chatbot Observation](https://docs.google.com/spreadsheets/d/1NmDjq08M8NBK8WrWyqnYZWS9yeLhbtlpHtU_AUhtabw/edit?usp=sharing) tracker.

## [](#setup)Setup

### [](#zingtree-setup-to-use-snippets-from-zingtree)Zingtree Setup — to use snippets from Zingtree

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

You will use this case to retrieve the Zingtree snippet to send to customers. You can use it for every conversation in Zingtree. Bookmark it and reuse it. Do not close it.





To create the placeholder case:

1. Go to this link [https://zingtree.com/live/738905624?tree\_id=738905624000#1](https://zingtree.com/live/738905624?tree_id=738905624000#1)

2. Fill your groupon email address into Your Email Address field ![:r1:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/cbece7ea-90d1-42be-b944-7d3a40472c0a/Circle_1.png)

![](https://media.notiondesk.so/upload/68ece6c87e950022743010.png)

1. Click on CS Case Creation button ![:r2:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/828ec6f6-6da7-41e1-ab7d-81f376318b90/Circle_2.png)

2. Provide any text into Name your request ![:r3:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/6a0e6eb2-4742-4445-80a6-8be77bab104f/Circle_3.png) and Describe your request ![:r4:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/49964e58-e0e9-40b5-b973-00c416e5d0bc/Circle_4.png) fields

![](https://media.notiondesk.so/upload/68ece6cb56c02552592920.png)

1. Set Country ![:r5:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/a8d7fc85-01c2-4beb-ae57-18073a27a40e/Circle_5.png) to US

2. Click the Continue button ![:r6:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/22961b53-f52d-4017-87e3-e0ab43ddd029/Circle_6.png)

3. Click Copy Case Link ![:r7:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/9e5e9e5f-9b80-4656-8d16-a78ef863eb57/Circle_7.png) button

![](https://media.notiondesk.so/upload/68ece6ce034b3229907594.png)

1. Open the copied link in you browser

2. Click on the down arrow button ![:r8:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/bd34cd7e-cbac-4650-9d97-2a4412a47520/Circle_8.png) in the tab of the case

![](https://media.notiondesk.so/upload/68ece6d093f2b854665459.png)

1. Click Pin Tab menu item to keep the tab always visible

2. Go to case Details ![:r10:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/39cc41d0-405c-4a91-bb9a-f1c584d8fb1a/Circle_10.png) tab![](https://media.notiondesk.so/upload/68ed4128d691d632486903.png)

3. Click Status ![:r11:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/3ee86a8a-caf2-477b-accb-27c2e2a315ea/Circle_11.png) menu

4. Click Closed ![:r12:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/b6a745ee-4a40-42ab-b73a-e66d599f7442/Circle_12.png) menu item to make sure the case is not assigned to customer support

5. Click Save ![:r13:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/ecf5bec7-0640-4f5a-928c-0f89d29f37ba/Circle_13.png) button

Now you have your case ready for using Zingtree to get snippets.









## [](#team-leaders)Team Leaders

As the Chatbot process is being moved to Salted, TLs are requested to regularly monitor the queue in the Salted Live interface to ensure no contacts are missed.

With the team leader permissions, you now have the opportunity to see the content of the conversation without joining it. Just click on the conversation in the left pane, both in the Help Needed or All In Progress, to see what is happening in this conversation in real time. You can click the join button to join the conversation as needed.

### [](#watch-key-metrics)Watch Key Metrics

Key metrics to watch:

![](https://media.notiondesk.so/upload/68fb8aa384806531603355.png)

- Encourage agents to keep number of conversations in My Conversations at 2 to 4 if there are any conversations waiting in Needs Help

- Watch the longest waiting customer time and keep it below 30 seconds if there are more customers that the current agents can handle you need to increase the number of agents





### [](#watch-escalations)Watch Escalations

To watch escalations, click on the number in the Help Needed section and select Internal Agents. This shows you only conversions that already have at least one agent engaged in the conversation.

![](https://media.notiondesk.so/upload/68ed364375876502036341.png)









## [](#start-your-work)Start Your Work

### [](#set-salesforce-status-to-open-salted-cx-keep-your-adherence)Set Salesforce Status to Open (Salted CX) — keep your adherence

You manage your status in Salesforce.

- Set the status within [Salesforce](https://groupon-dev.lightning.force.com/lightning/page/home) to Open (Salted CX). The status is used to measure adherence and even when you do not handle conversations in Salesforce you have to switch update it there.

![](https://media.notiondesk.so/upload/68dfe6270f479473134701.png)

- Go to [groupon.eu.salted.cx/live](https://groupon.eu.salted.cx/live)

- Login if asked to using Groupon Okta

![](https://www.notion.so/icons/warning_yellow.svg?mode=light)

If you cannot see the Live tab in the top left corner, try logging out by clicking the user icon in the top right corner and then selecting 'Logout’. Then try to visit [groupon.eu.salted.cx/live](https://groupon.eu.salted.cx/live) again. If you still do not have access to the Live tab, reach out to our collaboration [Google Space](https://mail.google.com/mail/u/0/#chat/space/AAQAdkY2z9o) to enable the feature for you.













### [](#what-customer-requests-do-you-handle)What Customer Requests Do You Handle

You are focused on two sets of customer requests:

- Chat Escalations from bot in Salted CX — You will handle chat escalations from Groupon AI chatbot. In case the bot does not know how to resolve the issue. You will handle those from Salted CX Live Conversations.

- Emails in Salesforce — You handle emails in Salesforce as usual. Work on emails when you have no conversations waiting.





## [](#finishing-your-work)Finishing Your Work

### [](#leave-live-conversations-ensure-somebody-takes-over-your-work)Leave Live Conversations — ensure somebody takes over your work

When wrapping up your work, it's possible that you still have conversations in progress. Make sure you will not leave the customers hanging.

![](https://media.notiondesk.so/upload/68d696bd09161928981887.png)

- Go though My conversations ![:r1:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/cbece7ea-90d1-42be-b944-7d3a40472c0a/Circle_1.png) until you have 0 items conversations there

- If the conversations need somebody to finish them press Request help ![:r2:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/828ec6f6-6da7-41e1-ab7d-81f376318b90/Circle_2.png)

- Click Leave ![:r3:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/6a0e6eb2-4742-4445-80a6-8be77bab104f/Circle_3.png) (you can click Resolve if the customer request got resolved)

- Choose the reason ![:r4:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/49964e58-e0e9-40b5-b973-00c416e5d0bc/Circle_4.png) why you are leaving the conversation









### [](#change-your-salesforce-status)Change Your Salesforce Status

You manage your status in Salesforce.

- Set the status within [Salesforce](https://groupon-dev.lightning.force.com/lightning/page/home) to Offline or other status depending on what you do next.

![](https://media.notiondesk.so/upload/68ed0fb83ac41326515107.png)





## [](#picking-conversations)Picking Conversations

### [](#pick-the-longest-waiting-customers-first)Pick the Longest Waiting Customers First

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

The goal is to keep the maximum wait time under 30 seconds.





You should strongly prefer joining conversations where the customer has been waiting the longest. To do so, click the Join longest waiting ![:r1:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/cbece7ea-90d1-42be-b944-7d3a40472c0a/Circle_1.png) menu item with the counter.

![](https://media.notiondesk.so/upload/68fb8aae25669769370784.png)





### [](#picking-conversation-without-another-agent)Picking Conversation without Another Agent

You see conversations in which you participate in the My Conversations section ![:r1:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/cbece7ea-90d1-42be-b944-7d3a40472c0a/Circle_1.png) in the left-hand navigation.

![](https://media.notiondesk.so/upload/68d6acfdf0fb7710699283.png)

When joining conversations:

- Make sure number of conversations in My Conversations is at most 3. Do not join more conversations if you have already 3 in My Conversations. You see the number of conversations you are participating in next to the title ![:r2:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/828ec6f6-6da7-41e1-ab7d-81f376318b90/Circle_2.png).

- If you participate in two or less conversations check whether there are any conversations in Needs help section. To join a conversation click the Join button ![:r3:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/6a0e6eb2-4742-4445-80a6-8be77bab104f/Circle_3.png). You cannot view a conversation before joining. Handling time is measured from the moment you join the conversation.









### [](#watch-for-new-conversations)Watch for New Conversations

Live Conversations notify you of new messages. So, if you have a different browser app open, you know you might need to return to the customer.

![](https://media.notiondesk.so/upload/68e6b5bed5e19724458119.png)Tabs in background show they need the agent’s attention

In the browser tab, you can see the following symbols:

- Full circle ● — There is a new message in the conversation that is open in the tab.

- Empty circle ○ — There is a new message in a conversation in your My Conversations list that is not focused in the tab.

- Raised hand ✋ — There is no new message. However there is a conversation that needs help that you can join and help the bot or a fellow agent.

Directly in Live Conversations, you can see the number of new messages in My Conversations right in the navigation.

![](https://media.notiondesk.so/upload/68e6b5c1b1a41907216640.png)Navigation with 2 new messages

Also a sounds is played when a new message arrives to bring this to your attention.









### [](#other-participants-in-a-conversation)Other Participants in a Conversation

Live Conversation enables multiple participants to join the same conversation. If someone other than you is engaged in the conversation, you will see blue or yellow +1, +2, etc. text in the navigation.

Blue is the number of the agents other than you.

Yellow is the number of external agents (merchants). Merchants will get access to Live Conversations in the future.

![](https://media.notiondesk.so/upload/68ed19c1b4728652845686.png)

You can see who exactly is in the conversation in the tooltip, or you can click on any conversation to open a join screen and see the names of the engaged agents.

If Help Needed contains a conversation that shows involvement of another agent:

- If you are a senior agent join the conversation to help a fellow agent. This helps to unblock them to handle other customer requests.

- If you are a junior agent avoid joining those as they may be more complex cases.









## [](#handle-conversations)Handle Conversations

### [](#get-snippet-from-zingtree-know-how-to-respond-to-the-customer)Get Snippet from Zingtree — know how to respond to the customer

To get a response to the customer from the Zingtree follow these steps:

1. Click the Order ID ![:r1:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/cbece7ea-90d1-42be-b944-7d3a40472c0a/Circle_1.png) button to copy order ID from the conversation

![](https://media.notiondesk.so/upload/68ecea5244846930475799.png)

1. Switch to Salesforce

2. Click pencil icon next to Order ID ![:r2:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/828ec6f6-6da7-41e1-ab7d-81f376318b90/Circle_2.png) in Salesforce

![](https://media.notiondesk.so/upload/68ecea551f78f219546036.png)

1. Paste the Order ID to the text field ![:r3:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/6a0e6eb2-4742-4445-80a6-8be77bab104f/Circle_3.png) from your clipboard

![](https://media.notiondesk.so/upload/68ecea578d177470393741.png)

1. Add Web Email.

2. Click Save ![:r4:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/49964e58-e0e9-40b5-b973-00c416e5d0bc/Circle_4.png) button

3. Click Sync Order &amp; Customer Info ![:r5:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/a8d7fc85-01c2-4beb-ae57-18073a27a40e/Circle_5.png) button![](https://media.notiondesk.so/upload/68ecea5a05365544049004.png)

4. Click on Done ![:r6:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/22961b53-f52d-4017-87e3-e0ab43ddd029/Circle_6.png) button

5. Now navigate Zingtree to find the answer to the customer request

![](https://media.notiondesk.so/upload/68ecea5c77cee090405559.png)

1. Use the instructions at the end of the Zingtree path to respond to the customer









### [](#refund-in-cyclops)Refund in Cyclops

To refund something in Salesforce:

- Click on Cyclops ![:r1:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/cbece7ea-90d1-42be-b944-7d3a40472c0a/Circle_1.png) button or UK/DE ![:r2:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/828ec6f6-6da7-41e1-ab7d-81f376318b90/Circle_2.png) button if the button shows something else than US

![](https://media.notiondesk.so/upload/68fb8abc43ae0332793239.png)

- Perform any refunds in Cyclops

- Use your Salesforce placeholder case into Case Number ![:r2:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/828ec6f6-6da7-41e1-ab7d-81f376318b90/Circle_2.png)

![](https://media.notiondesk.so/upload/68ed161e6d96e314495582.png)

- Paste a link to the Live Conversation to Notes ![:r3:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/6a0e6eb2-4742-4445-80a6-8be77bab104f/Circle_3.png)





### [](#issue-goodwill-credits)Issue Goodwill Credits

To issue goodwill credits:

1. Click Cyclops ![:r1:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/cbece7ea-90d1-42be-b944-7d3a40472c0a/Circle_1.png) buttons to open the deal in Cyclops

![](https://media.notiondesk.so/upload/68ee408172bc3620825755.png)

1. Copy the Salesforce Case Record ID ![:r2:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/828ec6f6-6da7-41e1-ab7d-81f376318b90/Circle_2.png) from browser address bar

![](https://media.notiondesk.so/upload/68ee4084535f7287389780.png)

1. Paste the copied Salesforce record ID to SF Case Record ID ![:r3:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/6a0e6eb2-4742-4445-80a6-8be77bab104f/Circle_3.png)

![](https://media.notiondesk.so/upload/68ee4086ee789676744377.png)

1. Copy the Salesforce case number ![:r4:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/49964e58-e0e9-40b5-b973-00c416e5d0bc/Circle_4.png) to clipboard

2. Paste the copied Salesforce case number SF Case Number ![:r5:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/a8d7fc85-01c2-4beb-ae57-18073a27a40e/Circle_5.png)





### [](#when-customer-reaches-out-about-a-salesforce-case)When Customer Reaches Out About a Salesforce Case

Open Salesforce and locate the case to understand the context of the customer’s request.

1. Go to Salesforce cases <https://groupon-dev.lightning.force.com/lightning/o/Case/list>

2. Search for the case number ![:r1:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/cbece7ea-90d1-42be-b944-7d3a40472c0a/Circle_1.png)

![](https://media.notiondesk.so/upload/68ed19c8eb8fc048395983.png)

1. Click on the case ![:r2:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/828ec6f6-6da7-41e1-ab7d-81f376318b90/Circle_2.png)





### [](#view-previous-conversations-with-the-customer)View Previous Conversations with the Customer

You can also click Journey ![:r20:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/436983da-8ca9-411a-bd4d-fea6e44b7749/Circle_20.png) button next to the customer name to view previous conversations with the customer. From the customer journey, you can then open a Salesforce case related to the conversation by using the cloud button at the beginning of the conversation.

![](https://media.notiondesk.so/upload/68fb8ac1b2f06671312981.png)

![](https://www.notion.so/icons/warning_yellow.svg?mode=light)

If the customer has no history of conversations, there may be no customer journey available. Live Conversations are loaded approximately every 15 minutes, so you might not see the entire conversation in the journey yet.













## [](#reply-to-customer)Reply to Customer

Use the tips in this section to answer more quickly and consistently for the customers.

### [](#wait-for-customer-join-more-conversations)Wait for Customer — join more conversations

Press the button Wait for customer ![:r1:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/cbece7ea-90d1-42be-b944-7d3a40472c0a/Circle_1.png) to move to the next conversation while you wait for a final confirmation from the customer that the issue is truly resolved. Do not select Resolve or Leave in this case. If the customer really stops responding, you can mark it as Resolved later. You can pick up to 4 conversations at once, especially when waiting for a customer.

We record the usage of this feature and so when used correctly it does not negatively impact your performance.





### [](#improve-reply-respond-faster)Improve Reply — respond faster

Type two dots `..` at the end of the reply to let AI improve the answer for you. The improved reply will be polite and include context from the previous conversation. You will have still get a chance to review the improved reply before sending.

![](https://media.notiondesk.so/upload/68ee408ca63be445570100.gif)

Be really short to save time. The improve reply feature is not just a grammar check and polish but is also expands the sentence to be polite and explanatory.

- `no..` — tell customer negative response politely or politely refuse their request.

- `yes..` — confirm the customer question, agree with them

- `sorry..` — excuse to customer taking the context into consideration

- `already redeemed..` — to tell the customer that their request is redepend









### [](#working-on-it-button-one-click-working-on-it)Working on it Button — one click “working on it”

Use the “working on it” button ![:r1:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/cbece7ea-90d1-42be-b944-7d3a40472c0a/Circle_1.png). Salted CX will automatically send the customer one of 7 predefined messages that states you are working on their issue. As it selects these messages randomly, you can use it multiple times during one chat while it still sounds authentic.

![](https://media.notiondesk.so/upload/68ed19d0955b1474500163.png)









### [](#prepared-replies-use-stashed-and-ready-to-use-replies)Prepared Replies — use stashed and ready to use replies

Search by shortcuts and the replies’ content to find a prepared reply. You still have a chance to review the reply before sending.

![](https://media.notiondesk.so/upload/68d642d84df5a641549030.png)









### [](#shortcuts-list-list-of-basic-shortcuts)Shortcuts List — list of basic shortcuts

This is the list of basic shortcuts you can use. Just type the shortcut with two dots `..` at the end. For example, `ty..` will write “Thank you for understanding”.

| Shortcut | Text |
|---|---|
| `hi..` | Hi xxxx, thank you for contacting Groupon Customer Support. My name is xxxxxxx. |
| `fa..` | Please let me know if you have any questions or if I can be of further assistance. |
| `ty..` | Thank you for understanding. |
| `elb..` | Could you please tell me a little more about your issue? That will help me determine how I can best help. |
| `mf..` | I can imagine how frustrating that must be. |
| `ae..` | Is there anything else I can help you with today? |
| `ca..` | Is there a specific reason you would like to cancel the order? |
| `yw..` | You're welcome. |
| `pw..` | Please allow me a moment to look into this for you. |
| `tp..` | Thanks for your patience. |
| `ss..` | Can you send a screenshot of what you're seeing? |
| `bye..` | Thank you again for contacting Groupon Customer Support. |
| `rv..` | Please give me a moment while I review your conversation with the previous agent. |
| `mre..` | I'm very sorry you had this experience. This is definitely not something we ever want our customers to encounter. |
| `mo..` | Please give me a moment while I pull up your account info. |







## [](#finish-work-on-a-conversation)Finish Work on a Conversation

There are two ways for you to finish your work in a conversation.

![](https://www.notion.so/icons/warning_yellow.svg?mode=light)

Do not use the Resolve or Leave buttons while waiting for the customer. Use the Wait for Customer button instead.





### [](#customer-request-is-resolved-customers-have-everything-they-need)Customer Request is Resolved — customers have everything they need

![](https://www.notion.so/icons/warning_yellow.svg?mode=light)

Do not use this when you are waiting for a response from a customer or when somebody else needs to finish the communication.









### [](#you-can-t-help-somebody-else-can-somebody-else-needs-to-follow-up-with-the-customer)You Can’t Help, Somebody Else Can — somebody else needs to follow-up with the customer

When you do not know what to do, you need to end a shift, etc.

1. If there is no other agent involved press Request help button to ensure somebody picks

2. Click Leave button

3. Pick the reason why you are leaving the conversation

When leaving a conversation, use the following reasons:

- CX requires supervisor assistance – SME/TL is handling the customer

- Abusive customer — our policy allows to ignore a customer due to their behavior.

- Going for a break — you have to take a break.

- Going home — your shift ends but the conversation is still not resolved.

- Other reason — none of the above. Use sparingly.

Do not pick any other reasons. The reasons are used in analytics to monitor performance. If you miss a reason that you need to use for your work, ask your Team Leader to add it.





### [](#customer-is-not-responsive)Customer is Not Responsive

Feel free to take additional conversations while you are waiting for a customer.

When customer is not responsive for extended pedriod of time leave the conversation:

- Click on Leave

- Click on Customer not responsive





## [](#escalations)Escalations

### [](#request-help-from-sme-or-tl)Request Help from SME or TL

Press the Request help ![:r1:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/cbece7ea-90d1-42be-b944-7d3a40472c0a/Circle_1.png) button

![](https://media.notiondesk.so/upload/68ed19d588b1b700624313.png)





### [](#escalations-to-merchant-operations)Escalations to Merchant Operations

1. Press →MO ![:r3:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/6a0e6eb2-4742-4445-80a6-8be77bab104f/Circle_3.png) button

![](https://media.notiondesk.so/upload/68fb8ad07e4a2245572855.png)

1. A short message will appear in the chat confirming the button was pressed.

2. Let the customer know the case has been escalated to Merchant Operations.

After the conversation is escalated to Merchant Operations, the entire chat transcript is available in the created case. From that moment on, the resolution is handled entirely in Salesforce.

All follow-up conversations with the merchant from that point forward happen in Salesforce. When it is necessary to inform the customer about the outcome of the conversation with the merchant, Salesforce is also used.

If the case wasn’t created automatically, you need to create it manually in Salesforce: Copy the JOURNEY URL, not the live chat URL, into the comment of the new case. For that, click the "Journey" button in your Salted Live agent desktop (right next to the customer name at the top), then copy and paste the URL of that journey screen. The correct URL doesn’t include the /live/ path.





### [](#escalations-to-merchant)Escalations to Merchant

1. Press →Merchant ![:r4:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/49964e58-e0e9-40b5-b973-00c416e5d0bc/Circle_4.png) button

![](https://media.notiondesk.so/upload/68fb8ad48a61d799547113.png)

1. A short message will appear in the chat confirming the button was pressed.

2. Let the customer know the case has been escalated to the Merchant.

After the conversation is escalated to the Merchant, the entire chat transcript is available in the created case. From that moment on, the resolution is handled entirely in Salesforce.

All follow-up conversations with the merchant from that point forward happen in Salesforce. When it is necessary to inform the customer about the outcome of the conversation with the merchant, Salesforce is also used.

If the case wasn’t created automatically, you need to create it manually in Salesforce: Copy the JOURNEY URL, not the live chat URL, into the comment of the new case. For that, click the "Journey" button in your Salted Live agent desktop (right next to the customer name at the top), then copy and paste the URL of that journey screen. The correct URL doesn’t include the /live/ path.





### [](#escalations-to-goods)Escalations to Goods

1. Press →Goods ![:r5:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/a8d7fc85-01c2-4beb-ae57-18073a27a40e/Circle_5.png) button

![](https://media.notiondesk.so/upload/68fb8ad78e625170878612.png)

1. A short message will appear in the chat confirming the button was pressed.

2. Let the customer know the case has been escalated to Goods.

After the conversation is escalated to Goods, the entire chat transcript is available in the created case. From that moment on, the resolution is handled entirely in Salesforce.

All follow-up conversations with the merchant from that point forward happen in Salesforce. When it is necessary to inform the customer about the outcome of the conversation with the merchant, Salesforce is also used.

If the case wasn’t created automatically, you need to create it manually in Salesforce: Copy the JOURNEY URL, not the live chat URL, into the comment of the new case. For that, click the "Journey" button in your Salted Live agent desktop (right next to the customer name at the top), then copy and paste the URL of that journey screen. The correct URL doesn’t include the /live/ path.





## [](#where-did-my-feature-go)Where Did My Feature Go?

### [](#grouptimize)Grouptimize

Simply write what you would write in Grouptimize directly into the reply field, and then type two dots `..`, Live Conversations will improve your reply right in the reply text box. You still have an opportunity to review the proposal before sending it to the customer.

![](https://media.notiondesk.so/upload/68ee40b398983340825167.gif)





### [](#case-number-tracking-in-google-sheets)Case number tracking in Google Sheets

You do not need to track conversations that you join in Live Conversations. We track those automatically and use them in analytics. We keep the number of conversations you have participated in, the duration of each engagement, the quality of the conversation content, and other relevant metrics.





### [](#timer-since-the-last-customer-message)Timer since the last customer message

There is no timer in Live Conversations. However, we track very detailed performance metrics on time to answer and show conversations that require attention in the reporting.

---

## Logical Model Tips

Source: https://help.salted.cx/en/articles/model-tips


When creating custom metrics it is useful to understand our [Logical Model](https://help.salted.cx/en/collections/1755206106-logical-model). Logical Model is designed to be easy to understand without reading too much of a documentation.

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

We recommend to reuse the built-in metrics in the beginning and add additional conditions and aggregations on top of them. Another option is to create copies of the built-in metrics. This practice can help you to remove some uncertainty and learn some practices we use in our metrics to get the expected results. See [Built-in Metrics Overview](https://help.salted.cx/en/articles/metrics-overview) and [Metrics Reference](https://help.salted.cx/en/articles/1755225286-metrics-reference) for more information.





## [](#engagements)Engagements

Engagements data set is the core of our Logical Model. When building metrics you should consider what engagements you want to include in your metrics. The following simple example counts all items in the Engagements data set:

```sql
SELECT COUNT(<span class="fw-bold nd-color--orange">Engagement</span>)
```

The above metric is technically correct. However it is extremely unlikely it would be useful for any business need. Engagements data set contains a lot of items you might want to exclude from counting depending on your use case.

### [](#engagement-type)Engagement Type

IN most cases you will be filtering for a specific type of an Engagements. Otherwise you will often count apples and oranges. Different types of Engagements have a very different meaning described in detail in this [dedicated article](https://help.salted.cx/en/articles/model-engagement#24a5dd77902c48139ddfdf2f17bde46e).

```plain
SELECT COUNT(<span class="fw-bold nd-color--orange">Engagements</span>) 
	WHERE <span class="fw-bold nd-color--orange">Type</span> = <span class="nd-color--red">"Agent"</span>
```

The above metric counts only Engagements where an Agent was engaged in a Conversation with a customer.

Engagements that have `<span class="fw-bold nd-color--orange">Type</span>` equal to `<span class="nd-color--red">"Technical"</span>` are in the data set to ensure that the Logical Model behaves as expected for some use cases and you should always exclude them when creating metrics.

### [](#engagement-status)Engagement Status

In many cases you will be reporting on completed Engagements.

```plain
SELECT COUNT(<span class="fw-bold nd-color--orange">Engagements</span>) 
	WHERE <span class="fw-bold nd-color--orange">Type</span> = <span class="nd-color--red">"Agent"</span> AND <span class="fw-bold nd-color--orange">Status</span> = <span class="nd-color--red">"Completed"</span>
```

The above metric counts only Engagements where an Agent was engaged in a Conversation with a Customer and the Engagement is over which means the agent is not longer engaged with the customer and the wrap up is over if there was any.

Engagements that are reported as in progress were in progress when the data was loaded. At the time when you report of them they may already be completed.

## [](#conversations)Conversations

Conversations add extra complexity to analytics. Conversation is a set of Engagements. Engagements that belong to the same Conversation have the same Conversation attribute value. There is not a separate Data Set that would represent the conversations themselves. Because metrics are working on the granular Engagement level you have to consider how filters, segmentations and aggregations actually work.

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

In most cases reporting on Engagement level is what you need. When reporting on conversations make sure it is right for what you are trying to do.





| Conversation | Engagement | Direction | Queue |
|---|---|---|---|
| Co1 | En1 | Inbound | Queue A |
| Co1 | En2 | Inbound | Queue A |
| Co1 | En3 | Inbound | Queue B |



When you do simple report on the Engagements data set above with metrics counting Conversations and metric counting Engagements you will get different results.

| Queue | `SELECT COUNT(``Engagement``)` | `SELECT COUNT(``Conversation``)` |
|---|---|---|
| Queue A | 2 | 1 |
| Queue B | 1 | 1 |
| Sum | 3 | 2 |
| Rollup | 3 | 1 |



The second column counting Engagements is easy to understand. We have in total 3 engagements (3 rows in the table) with IDs En1, En2 and En3. Two of the Engagements are in Queue A and one Engagement is in Queue B. Both Sum and Rollup rows show that there are in total 3 Engagements as expected.

The third columns counting Conversations is slightly more complex. There is only 1 Conversation with ID Co1 in the data set. The Conversation goes through multiple queues. It appears twice (in Engagements En1 and En2) in the Queue A and once in the Queue B (Engagement En3).

## [](#start-time-and-end-time)Start Time and End Time

Salted CX enables you to report either based on time when an Engagement started or when the Engagement ended.

Start Time is available for every Engagement. Thus Start Time enables you to report on Engagements that are were in progress during the last data load. Start Time is great to understand when customers started to reach you which is great to

End Time is available only after an Engagement is completed. It does not have to be available for engagements.

## [](#internal-conversations)Internal Conversations

Internal conversations require extra attention to interpret them properly. Our [Logical Model ](https://help.salted.cx/en/collections/1755206106-logical-model)enables only one agent to be associated with an engagement. This is to ensure the data are easy to use for reporting. In internal conversations agents talk to other agents.

In internal conversations the agent starting the conversation is represented by Customer data set item with `Type` = `Agent` . The receiving agents who handle the conversation are stored in regular Agent data set items.

## [](#agents)Agents

Salted CX represents even bots and other services as agents. If you want to focus specifically on people use `Agent ⏵ Type` attribute in filters.

## [](#technical-items-in-data-sets)Technical Items in Data Sets

Each data set and each entity contain one item that as its primary identifier equal to `00000000-0000-0000-0000-000000000000`. These items are there for technical purposes that maintains referential integrity. All other values facts, attributes and labels for these items are empty.

## [](#no-many-to-many-relationships)No Many-to-Many Relationships

Logical Model intentionally does not support many-to-many relationships. This is motivated by performance considerations and also the simplicity of reporting and writing metrics. Many-to-many relationships make especially attribution of any metrics very difficult.

*Tags: Logical Model*


---

## Turn

Source: https://help.salted.cx/en/articles/model-turn


![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

Turn data set is not available for building visualizations and dashboards. The properties in this article cannot be used in reporting. Turns are visible in the [Customer Journey](https://help.salted.cx/en/collections/1755250527-customer-journey).





Turns are the most granular units of the customer journey. They represent individual messages, continuous talk, menu steps, actions, and transactions individual participants do during the engagement. There are different types of turns representing different activities.





## [](#data-set-properties)Data Set Properties

| Property | Type | Description |
|---|---|---|
| Turn | [PID](https://help.salted.cx/en/collections/1755206106-logical-model?v=24f5d3a2a8dc81f49249000c3e502787#2565d3a2a8dc8010b907f9c8aeac496e) | Unique identifier of the turn. |
| Engagement | Reference to [Engagement](https://help.salted.cx/en/articles/model-engagement) | The engagement in which the turn happened. |
| Turn Time | [Date and Time](https://help.salted.cx/en/articles/model-dates) | The time when the turn started. |
| Origin | [Enumeration](https://help.salted.cx/en/collections/1755206106-logical-model?v=24f5d3a2a8dc81f49249000c3e502787#2565d3a2a8dc80bfb945e38d99038ba8)Custom, Suggested |  |
| [Type](https://help.salted.cx/en/articles/model-turn#c9fddceb842d42c8b332c3a31e209ba2) |  | High-level categorization of turn that tells what action was done. |
| Duration | [Fact](https://help.salted.cx/en/collections/1755206106-logical-model?v=24f5d3a2a8dc81f49249000c3e502787#2565d3a2a8dc80189ad1cb926fd85828) | The duration of the turn in seconds if it can be attributed. This applies only to voice channels. |
| Length | Fact | The length of the turn. In characters. This applies only to text channels. |
| Confidence | Fact | The confidence with which this turn was used by an agent. This is specifically used by bots to indicate how sure they are about the answers they provide to customers. |



## [](#type)Type

Type of the turn represents one exchange that happened during an engagement. Some turn type represent events, some turns have a duration and represent longer periods of time.

| Type | Typical Engagement Type | Description |
|---|---|---|
| Application Action | Application | The participant performed an action in an application or a web service. |
| File | Agent, Menu | A file that was shared during the conversation. |
| Image | Agent, Menu | An image that was shared during the conversation. |
| Menu Back | Menu | The participant made a step back in the menu returning one step back. |
| Menu Restart | Menu | Represents a restart when going through a menu. The customer is at the beginning of the menu as if they just opened it. |
| Menu Step | Menu | Represents a single step in the service that enables users to navigate menus such as IVR, web wizards, etc. |
| Message | Agent | Message that cannot be attributed to any participant and it is unclear whether it was sent or received. |
| Recording | Agent | The turn represents a audio/visual recording related to the engagement. |
| Talk | Agent | The turn represents a piece of talk in a voice/audio conversation. |
| Transaction | Any | Represents a transaction that transitions a product/service/order from one state to another. For example, buying a product, refunding a product, etc. |
| Transcript | Any | The turn represents an entire transcript of the engagement or part of the engagement. This happens in cases when the platform does not support turn-level granularity for messages or speech. |
| Unknown | Any | The turn type is unknown and Salted CX keeps it only for purposes that it is not missing in the customer journey. |

*Tags: Logical Model*


---

## Transaction

Source: https://help.salted.cx/en/articles/model-transaction


A transaction represents a single business operation during an engagement. There can be multiple transactions in a single engagement.

## [](#data-set-properties)Data Set Properties

| Property | Type | Description |
|---|---|---|
| Transaction | [PID](https://help.salted.cx/en/collections/1755206106-logical-model?v=24f5d3a2a8dc81f49249000c3e502787#2565d3a2a8dc8010b907f9c8aeac496e) | Unique identifier of the transaction. |
| [Engagement](https://help.salted.cx/en/articles/model-engagement) | Reference to Engagement | Engagement in which the transaction happened. |
| Currency | [Attribute](https://help.salted.cx/en/collections/1755206106-logical-model?v=24f5d3a2a8dc81f49249000c3e502787#2565d3a2a8dc80b4a012f2965acc2b09) | Currency in 3-letter ISO 4217 [https://en.wikipedia.org/wiki/ISO\_4217](https://en.wikipedia.org/wiki/ISO_4217) |
| [Original State](https://help.salted.cx/en/articles/model-transaction#b64ca86554ae49c29501e6a5f8d1e580) | [Entity](https://help.salted.cx/en/collections/1755206106-logical-model?v=24f5d3a2a8dc81f49249000c3e502787#2565d3a2a8dc8040887dfa7ea6952826) | The state of the transaction before this engagement started. |
| [Process](https://help.salted.cx/en/articles/model-transaction#b64ca86554ae49c29501e6a5f8d1e580) | Entity | Business process name for this transaction. This can group transactions into logical units to watch. You can have for example “Online Order” process for sold products on your web, “Outbound Sale” for sold products during outbound call campaigns, etc. |
| Product | Entity | The product that is part of the transaction. |
| [Target State](https://help.salted.cx/en/articles/model-transaction#b64ca86554ae49c29501e6a5f8d1e580) | Entity | The state of the transaction at the end of the engagement. |
| Vendor | Entity | The vendor of the product that takes part in this transaction. |
| Cost | [Fact](https://help.salted.cx/en/collections/1755206106-logical-model?v=24f5d3a2a8dc81f49249000c3e502787#2565d3a2a8dc8010b907f9c8aeac496e) | All the costs associated with this transitions. |
| Exchange Rate | Fact | The rate how to recalculate the foreign currency to the account one. |
| Price | Fact | Base price for this transaction before any discounts for the entire volume. |
| Revenue | Fact | Total actual revenue generated from this transaction. This includes any discounts and applies to the entire volume of the transaction. |
| Volume | Fact | Number of items or volume of products or services associated with this transaction. |

*Tags: Logical Model*


---

## Service

Source: https://help.salted.cx/en/articles/model-service


Service dataset enables to related a conversation to a specific service or a product. This enables to provide segmentation and filtering to a specific service or product that the agents sell, service or support.

# [](#data-set-properties)Data Set Properties

| Property | Type | Description |
|---|---|---|
| Service | [PID](https://help.salted.cx/en/collections/1755206106-logical-model?v=24f5d3a2a8dc81f49249000c3e502787#2565d3a2a8dc8010b907f9c8aeac496e) | The service or a product that the conversation is related to. |
| Service ID | Label for Service | External ID for the service. |
| Service Name | Label for Service | Human readable name or the service. |
| Partner | [Entity](https://help.salted.cx/en/collections/1755206106-logical-model?v=24f5d3a2a8dc81f49249000c3e502787#2565d3a2a8dc8040887dfa7ea6952826) | Partner that is associated with the service or product. Partner enables you to group multiple services and products. |
| Partner Manager | Entity | The person who is currently responsible for managing the relationship with the partner for the given service or product. |
| Region | Entity | Geographical location of the service based on any segmentation used by the company. Ir might be a city for local operations or large region such as Europe, APAC for international operations. |
| Service Attribute 1 | Entity | Custom attribute associated with the service. |
| Service Attribute 2 | Entity | Custom attribute associated with the service. |
| Service Attribute 3 | Entity | Custom attribute associated with the service. |
| Service Status | Enumeration | The current service status enables to identify whether i |
| Vertical | Entity | The vertical in which the service or product is present. |

*Tags: Logical Model*


---

## Reviewer

Source: https://help.salted.cx/en/articles/model-reviewer


Reviewer data set contains people and services that provided the feedback related to conversations, engagements or even individual turns.





| Property | Type | Description |
|---|---|---|
| Reviewer | [PID](https://help.salted.cx/en/collections/1755206106-logical-model?v=24f5d3a2a8dc81f49249000c3e502787#2565d3a2a8dc8010b907f9c8aeac496e) | Unique identifier of the reviewer. |
| ID | [Label](https://help.salted.cx/en/collections/1755206106-logical-model?v=24f5d3a2a8dc81f49249000c3e502787#2565d3a2a8dc801684edeb3e8e714fb3) for Reviewer | Platform identifier for the reviewer. |
| Name | Label for Reviewer | User friendly display name for the reviewer. |
| Link | Label for Reviewer | Link for profile of the reviewer. |
| [Type](https://help.salted.cx/en/articles/model-reviewer#bf3267e89e204fe5a97832c2abda54d6) | [Enumeration](https://help.salted.cx/en/collections/1755206106-logical-model?v=24f5d3a2a8dc81f49249000c3e502787#2565d3a2a8dc801684edeb3e8e714fb3)Auto, User | Type of the reviewer. Enables to differentiate between people and automatic services. |



## [](#type)Type

Type of the reviewer. Distinguishes between bots and users that provide reviews. You can use it to focus specifically on input from users or bots.

| Type | Description |
|---|---|
| Auto | Automated bot that tries to handle the customer without an involvement of a human. |
| User | Human agent. An actual person working for the company. |



![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

Customer Reviews do not have an associated Reviewer. So unlike in [Review](https://help.salted.cx/en/articles/model-review) data set there are no Reviewers with Type `Customer`.

*Tags: Logical Model*


---

## Custom Digital Channel

Source: https://help.salted.cx/en/articles/custom-digital-channel


ℹ️

This guide describes how to integrate your own platform (e.g. a web chat widget) with Salted CX over the Custom Digital Channel. You push customer triggers (events that already happened on your side) to us, and we deliver agent/bot actions (replies to render) to your webhook.





## [](#why-this-channel-exists-and-the-role-of-yourlogic)Why this channel exists, and the role of YourLogic

Salted CX ships with native digital channels (web chat, WhatsApp, SMS, email). The Custom Digital Channel exists for platforms that have their own customer-facing UI — typically a chat widget — but want the conversation itself to run on Salted CX: the YourLogic AI, translation, routing, agent escalation, and analytics.

The most important thing to understand: Salted CX orchestrates the conversation, and YourLogic controls what happens in it. YourLogic is a service on your side, registered per account in Salted CX. For every customer turn, Salted CX sends a request to the YourLogic endpoint registered for your account, carrying the trigger plus the full conversation context (customer, engagements, all turns). YourLogic then responds through the Salted CX YourLogic response API with a list of actions — send a `MESSAGE` or `QUESTION`, update the conversation, or raise `NEEDS_HELP` to escalate to a human agent — and Salted CX executes them. Salted CX is not a passive history sink that you mirror messages into. The integration is the conversation:

- Your widget never talks to YourLogic directly — it talks only to Salted CX: triggers in, webhook actions out.

- Every customer message you push as a trigger is forwarded by Salted CX to YourLogic with the full conversation context — that is how the AI receives its input.

- Every AI reply (and later every agent reply) reaches your widget through the outbound webhook — your widget only renders it.

- Escalation is decided by YourLogic: it responds with a `NEEDS_HELP` action (or times out, or disengages) and Salted CX routes the conversation to a human agent. There is no inbound "escalation event" in the widget API, and none is needed.

- Because of that, customer messages must flow to Salted CX from the start of the conversation, not only once it is escalated.

End-to-end — the green-highlighted steps are the new Custom Digital Channel (widget ↔ Salted CX); everything else is the existing Salted CX conversation flow:

![](https://media.notiondesk.so/upload/6a60b7d309809100453096.svg)Custom Digital Channel end-to-end flow

Diagram source (Mermaid)```mermaid
sequenceDiagram
	actor W as Customer (Via Your Widget)
	participant S as Salted CX
	participant YL as YourLogic
	actor A as Agent
	rect rgb(200, 230, 201)
		W->>S: Customer Message
	end
	S->>YL: Customer Message
	YL->>S: AI Message
	rect rgb(200, 230, 201)
		S->>W: AI Message
	end
	Note over W,A: YourLogic Here Decides to Escalate
	YL->>S: Escalation (NEEDS_HELP)
	A->>S: Agent Message
	S->>YL: Agent Message
	rect rgb(200, 230, 201)
		S->>W: Agent Message
	end
	rect rgb(200, 230, 201)
		W->>S: Customer Message
	end
	S->>YL: Customer Message
	S->>A: Customer Message
```





Note that YourLogic keeps receiving all customer and agent turns even after escalation — it stays engaged in the conversation until it disengages.

Your widget does the same two things in both phases — push customer messages to Salted CX and render the replies we send back. Whether a reply comes from the AI or a human agent is transparent to your integration.

## [](#overview)Overview

The Custom Digital Channel lets your platform deliver customer turns to Salted CX. Direction is defined from your point of view:

- Trigger (inbound, you → us) — a message the customer already sent in your widget. You push it to us.

- Action (outbound, us → you) — an agent, bot, or system reply for your platform to render. We POST it to your webhook — see the "Receive actions" section below.

Each trigger runs through the same conversation lifecycle as a native digital turn (translation, routing to an agent or bot).

⚠️

v1 scope: one custom channel per account; trigger types `MESSAGE` (with attachments; `participantType` `CUSTOMER` or `BOT`), `QUESTION_DYNAMIC` and `QUESTION` (`BOT` only), and `ANSWER` (`CUSTOMER` only); outbound actions `MESSAGE` (with attachments) and `QUESTION`. Standalone media turns (file/image-only, without text) are not delivered outbound — attachments reach your widget only as part of a `MESSAGE`. Typing indicators, delivery receipts, and lifecycle events are not yet available.





## [](#authentication)Authentication

All requests use your per-account bearer token (the same token used for the YourLogic integration):

```plain
Authorization: Bearer <your-account-token>
Content-Type: application/json
```

Requests are rejected when the token is unknown, or when it does not belong to the account specified in the path.

## [](#flow)Flow

![](https://media.notiondesk.so/upload/6a60b7d45b46a711407238.svg)Endpoint-level flow

Diagram source (Mermaid)```mermaid
sequenceDiagram
	autonumber
	participant You as Your Widget
	participant Salted as Salted CX
	You->>Salted: POST /conversations (create)
	Salted-->>You: conversationPid
	You->>Salted: POST /conversations/{conversationPid}/triggers
	Salted-->>You: per-trigger result
	Salted->>You: POST action to your webhook (agent/bot reply)
	You-->>Salted: 2xx
```





Create the conversation once (you receive a `conversationPid`), then push one or more triggers to that conversation. Agent and bot replies flow back to your webhook as actions.

A conversation stays usable for its whole lifetime: if it has been completed on our side and the customer writes again, pushing the trigger to the same `conversationPid` reopens the conversation and re-engages YourLogic — you do not need to create a new one.

## [](#create-the-conversation)Create the conversation

Create the conversation first; the response returns a `conversationPid` that you use when pushing triggers. The contact is created or matched automatically from the `customer` block — you do not make a separate contact call.

```plain
POST /api/v1/live/custom-channel/accounts/{accountId}/conversations
```

The conversation is created as an inbound chat conversation. Request body:

```json
{
  "brandPid": "<brand-uuid>",
  "customer": {
    "displayName": "Jane Doe",
    "contact": { "contact": "customer-12345", "contactType": "Anonymous" }
  },
  "languageCustomer": "en",
  "url": "https://widget.example.com/chat",
  "custom": null
}
```

Request fields:

| Field | Type | Required | Description |
|---|---|---|---|
| `brandPid` | uuid | yes | Your brand id |
| `customer` | object | yes | Customer details (see below) |
| `languageCustomer` | string | no | Customer language, e.g. `en` |
| `url` | string | no | Last page the customer visited |
| `custom` | object | no | Custom properties (any JSON), or `null` |



`customer` fields:

| Field | Type | Required | Description |
|---|---|---|---|
| `displayName` | string | yes | Customer display name |
| `contact.contact` | string | yes | A stable identifier for the customer (email, phone, or your own id) |
| `contact.contactType` | string | yes | Classifies the identifier in `contact.contact` — see below |



`contactType` is an open string, and together with `contact.contact` it determines how the conversation is matched to a customer profile. Two values have special meaning:

- `Email` — the value is validated and normalized as an e-mail address and matched globally: the conversation links to the same customer profile as any other communication with that address. Use it when you have the customer's verified e-mail (e.g. a logged-in user).

- `Phone` — the value is validated and formatted as a phone number, also matched globally.

Any other value (by convention `Anonymous`) is treated as an opaque identifier without validation and matched only within its own type. Use `Anonymous` with a stable visitor or session id of your own for widget users who are not identified.

Pick the type by the identifier you actually have, not by the channel: a verified e-mail is worth sending as `Email`; an unauthenticated visitor should be `Anonymous`, not a made-up e-mail.

Response:

```json
{ "conversationPid": "11111111-2222-3333-4444-555555555555" }
```

## [](#push-triggers)Push triggers

```plain
POST /api/v1/live/custom-channel/accounts/{accountId}/conversations/{conversationPid}/triggers
```

The `{conversationPid}` path parameter is the value returned when you created the conversation.

The body is an ordered array of triggers. Four trigger types are supported: `MESSAGE` (`participantType` `CUSTOMER` or `BOT`), `QUESTION_DYNAMIC` and `QUESTION` (`BOT` only), and `ANSWER` (`CUSTOMER` only).

### [](#common-fields)Common fields

| Field | Type | Required | Description |
|---|---|---|---|
| `type` | string | yes | `MESSAGE`, `QUESTION_DYNAMIC`, `QUESTION`, or `ANSWER` |
| `participantType` | string | yes | `CUSTOMER`; `MESSAGE` also accepts `BOT`, and the question triggers are `BOT` only (see below) |
| `externalId` | string | yes | Your unique id for this trigger; used as the idempotency key. Must be unique across all conversations on the account and stable across retries of the same trigger |



### [](#message-a-customer-text-message)`MESSAGE` — a customer text message

| Field | Type | Required | Description |
|---|---|---|---|
| `content` | string | yes | The message text |
| `contentCustomer` | string | no | `BOT` only — the text in the customer's language as you displayed it; `content` is then the account-language version (see below) |
| `attachments` | array | no | List of attachments (see below) |



Attachments are uploaded first and referenced by `path` — the same flow the YourLogic `SEND_FILE` action uses. Request an upload URL (same bearer token):

```plain
POST /api/v1/live/media/accounts/{accountId}/upload-url
```

Response:

```json
{ "url": "", "path": "..." }
```

Then:

1. Upload the file: `curl --request PUT '<url>' --data-binary '@/path/to/file'` — the URL is valid for 1 hour.

2. Reference the returned `path` in the trigger attachment.

Attachment object:

| Field | Type | Required | Description |
|---|---|---|---|
| `name` | string | yes | File name |
| `path` | string | yes | The `path` returned by the upload-url endpoint. Account-scoped: a path that does not belong to your account, or has no uploaded file, fails the trigger with a per-trigger `FAILED` result. |
| `mimeType` | string | yes | e.g. `image/jpeg` |



### [](#message-with-participanttype-bot-recording-your-own-bot-turn)`MESSAGE` with `participantType: BOT` — recording your own bot turn

When your platform handles a flow directly with the widget (a feature Salted CX does not support natively), push the bot message you already displayed so agents and supervisors see the whole conversation:

- The turn is recorded as a bot turn and shown in the agent workspace like any other bot message.

- It is not delivered back to your webhook (you already displayed it) and not forwarded to YourLogic (no loop when your platform is also the YourLogic).

- Idempotency by `externalId` works exactly like customer triggers.

A `BOT` `MESSAGE` may additionally carry `contentCustomer` — the text in the customer's language exactly as your platform displayed it, with `content` being the account-language (English) version. When both are present we store them as-is and skip machine translation for that turn; without `contentCustomer` the turn is translated as today. (`contentCustomer` is not accepted on `CUSTOMER` messages — that direction is translated by us.) A `BOT` `ANSWER` fails with a per-trigger `FAILED` result.

### [](#question-dynamic-and-question-recording-a-question-your-bot-asked-bot-only)`QUESTION_DYNAMIC` and `QUESTION` — recording a question your bot asked (`BOT` only)

When your platform asks the customer a question directly, push it so it is recorded as a structured question turn. The convention is the same as for bot messages: every text field has an optional `*Customer` counterpart carrying what you actually displayed to the customer, and the base field is the account-language (English) version. We store both variants as-is — no translation on our side. Each `*Customer` field is optional and falls back to the English value.

| Field | Type | Required | Description |
|---|---|---|---|
| `name` | string | yes | Question text in the account language (English) |
| `nameCustomer` | string | no | Question text as the customer saw it; falls back to `name` |
| `answers` | array | no | Answer options; leave empty for a free-text question |
| `answers[].id` | string | yes | Your own id for `QUESTION_DYNAMIC`, the configured answer pid for `QUESTION`. Non-blank and unique within the question |
| `answers[].name` | string | yes | Answer label in the account language (English) |
| `answers[].nameCustomer` | string | no | Answer label as the customer saw it; falls back to `answers[].name` |
| `allowCustomReply` | boolean | no | Whether the customer could also type their own reply (default `true`) |
| `questionPid` | uuid | `QUESTION` only | The configured question pid, provided to you during onboarding |



`QUESTION_DYNAMIC` — an ad-hoc question; the answer ids are your choice (non-blank, unique). An empty `answers` list with `allowCustomReply: true` models a free-text question:

```json
{
  "type": "QUESTION_DYNAMIC",
  "participantType": "BOT",
  "externalId": "q-1",
  "name": "Was this helpful?",
  "nameCustomer": "Oliko tästä apua?",
  "answers": [
    { "id": "yes", "name": "Yes", "nameCustomer": "Kyllä" },
    { "id": "no", "name": "No", "nameCustomer": "Ei" }
  ],
  "allowCustomReply": true
}
```

`QUESTION` — a built-in (configured) question. Same shape, but the ids are the configured question and answer pids (provided to you during onboarding), and `questionPid` references the configured question — that identity is what ties the customer's answer to review creation:

```json
{
  "type": "QUESTION",
  "participantType": "BOT",
  "externalId": "q-2",
  "questionPid": "<configured question pid>",
  "name": "How satisfied are you?",
  "nameCustomer": "Kuinka tyytyväinen olet?",
  "answers": [
    { "id": "<configured answer pid>", "name": "Satisfied", "nameCustomer": "Tyytyväinen" },
    { "id": "<configured answer pid>", "name": "Unsatisfied", "nameCustomer": "Tyytymätön" }
  ]
}
```

You send the full wording you displayed to the customer — we record what the customer actually saw, not the configured texts. Both question triggers return the created `turnId` in the per-trigger result; store it and use it as `responseToId` when the customer answers.

Which path should a question take?

- Through YourLogic (the standard path) — YourLogic responds with a `QUESTION` action, we deliver it to your webhook with structured `answers`, and the customer replies with an `ANSWER` trigger. Use this whenever the bot acts as YourLogic.

- Deferred with a question trigger — when your platform asks the question itself, push it as `QUESTION_DYNAMIC` or `QUESTION` as shown above. The turn is recorded as a real question, so the customer's choice comes back as a proper `ANSWER` against the returned `turnId` rather than as a plain message.

### [](#answer-a-customer-answering-a-question)`ANSWER` — a customer answering a question

| Field | Type | Required | Description |
|---|---|---|---|
| `answerId` | string | see below | The id of the answer the customer chose |
| `content` | string | see below | Free-text reply (for questions with `allowCustomReply`); translated like a normal customer message |
| `responseToId` | uuid | yes | The id of the question turn being answered — the webhook envelope's `turnId`, or the `turnId` returned in the trigger result when you pushed the question yourself |



At least one of `answerId` / `content` must be present.

`responseToId` must reference a question turn in the conversation you are pushing to. Answering a turn that belongs to another conversation, or a turn that is not a `QUESTION` / `QUESTION_DYNAMIC` (a plain `MESSAGE`, for example), fails with a per-trigger `FAILED` result, as does an `answerId` that is not one of that question's answer ids.

## [](#examples)Examples

Text message:

```json
{
  "triggers": [
    {
      "type": "MESSAGE",
      "participantType": "CUSTOMER",
      "externalId": "a1b2c3-0001",
      "content": "Hello, I need help with my order"
    }
  ]
}
```

Message with an attachment:

```json
{
  "triggers": [
    {
      "type": "MESSAGE",
      "participantType": "CUSTOMER",
      "externalId": "a1b2c3-0002",
      "content": "Here is the photo",
      "attachments": [
        { "name": "receipt.jpg", "path": "<path from the upload-url endpoint>", "mimeType": "image/jpeg" }
      ]
    }
  ]
}
```

Bot message your widget already displayed:

```json
{
  "triggers": [
    {
      "type": "MESSAGE",
      "participantType": "BOT",
      "externalId": "a1b2c3-0004",
      "content": "Here is the tracking link for your order.",
      "contentCustomer": "Tässä on tilauksesi seurantalinkki."
    }
  ]
}
```

Question your bot already asked:

```json
{
  "triggers": [
    {
      "type": "QUESTION_DYNAMIC",
      "participantType": "BOT",
      "externalId": "a1b2c3-0005",
      "name": "Was this helpful?",
      "nameCustomer": "Oliko tästä apua?",
      "answers": [
        { "id": "yes", "name": "Yes", "nameCustomer": "Kyllä" },
        { "id": "no", "name": "No", "nameCustomer": "Ei" }
      ],
      "allowCustomReply": true
    }
  ]
}
```

Answer to a question — the customer picked an option:

```json
{
  "triggers": [
    {
      "type": "ANSWER",
      "participantType": "CUSTOMER",
      "externalId": "a1b2c3-0003",
      "answerId": "yes",
      "responseToId": "11111111-2222-3333-4444-555555555555"
    }
  ]
}
```

Answer to a question — the customer typed their own reply instead:

```json
{
  "triggers": [
    {
      "type": "ANSWER",
      "participantType": "CUSTOMER",
      "externalId": "a1b2c3-0006",
      "content": "It only half worked",
      "responseToId": "11111111-2222-3333-4444-555555555555"
    }
  ]
}
```

## [](#response)Response

The response reports a status per trigger, in the same order:

```json
{
  "conversationPid": "11111111-2222-3333-4444-555555555555",
  "results": [
    { "index": 0, "type": "MESSAGE", "status": "CREATED", "message": "Created", "turnId": "66666666-7777-8888-9999-000000000000" }
  ]
}
```

Per-trigger `status`:

| Status | Meaning |
|---|---|
| `CREATED` | The trigger was applied and a turn was created |
| `DUPLICATE` | A trigger with this `externalId` was already applied; nothing changed (idempotent) |
| `FAILED` | The trigger could not be applied (see Batch semantics below) |
| `SKIPPED` | Not attempted because an earlier trigger in the batch failed |



`turnId` is the id of the created turn (`CREATED`) or of the previously created turn (`DUPLICATE`), and `null` for `FAILED` / `SKIPPED`. Store it for question triggers: it is the value a later `ANSWER` sends as `responseToId`.

HTTP status codes:

| Code | When |
|---|---|
| `200 OK` | All triggers applied (`CREATED` or `DUPLICATE`) |
| `207 Multi-Status` | At least one trigger `FAILED`; inspect the per-trigger results |
| `400 Bad Request` | A trigger is malformed (missing required field, unknown `type`/`participantType`). No trigger in the batch is applied. |
| `404 Not Found` | The conversation does not exist |



## [](#idempotency)Idempotency

Each trigger carries an `externalId` that you choose. Re-sending a trigger with the same `externalId` does not create a second turn — it returns `DUPLICATE` with the original `turnId`. Use stable ids so safe retries never duplicate messages. `externalId` must be unique across all conversations on the account (your own message UUIDs are ideal); reusing a value from another conversation fails the trigger.

## [](#batch-semantics)Batch semantics

- Triggers are applied strictly in order.

- On the first failure, processing stops; remaining triggers are returned as `SKIPPED` and the HTTP status is `207`.

- Send a single trigger per request if you prefer to handle each independently.

## [](#receive-actions-outbound-us-you)Receive actions (outbound, us → you)

When an agent, bot, or the system produces a customer-facing turn in a Custom Digital Channel conversation, we deliver it to your webhook so your widget can show it to the customer.

### [](#webhook-registration)Webhook registration

Your webhook URL is registered per account as part of the channel configuration by Salted CX — provide the HTTPS endpoint during onboarding. One custom channel (one endpoint) per account in v1.

### [](#webhook-authentication)Webhook authentication

We send the same per-account bearer token you use to call our API:

```plain
Authorization: Bearer <your-account-token>
Content-Type: application/json
```

Validate the token on every request before trusting the payload.

### [](#envelope)Envelope

Every delivery is a `POST` with a JSON envelope carrying one action:

```json
{
  "conversationPid": "11111111-2222-3333-4444-555555555555",
  "turnId": "66666666-7777-8888-9999-000000000000",
  "occurredAt": "2026-07-03T10:15:30Z",
  "participant": { "type": "AGENT", "displayName": "Agent Smith" },
  "action": { "type": "MESSAGE", "content": "Hello, how can I help?", "attachments": [] }
}
```

| Field | Type | Description |
|---|---|---|
| `conversationPid` | uuid | The conversation the action belongs to (the `conversationPid` you received on create) |
| `turnId` | uuid | Stable id of the delivered turn — use it to deduplicate and to answer questions |
| `occurredAt` | string | ISO-8601 timestamp of the turn |
| `participant.type` | string | `AGENT`, `BOT`, or `SYSTEM` |
| `participant.displayName` | string | Display name to render, when available |
| `action` | object | Polymorphic by `action.type`: `MESSAGE` or `QUESTION` (see below) |



### [](#message-action)`MESSAGE` action

| Field | Type | Description |
|---|---|---|
| `content` | string | Message text (may be `null` for attachment-only messages) |
| `attachments[].name` | string | File name |
| `attachments[].mimeType` | string | e.g. `image/jpeg` |
| `attachments[].url` | string | Short-lived pre-signed URL — download the file promptly; do not store the URL |



### [](#question-action)`QUESTION` action

A button/list question for the customer to answer:

```json
{
  "conversationPid": "11111111-2222-3333-4444-555555555555",
  "turnId": "66666666-7777-8888-9999-000000000000",
  "occurredAt": "2026-07-03T10:15:30Z",
  "participant": { "type": "BOT", "displayName": "Bot" },
  "action": {
    "type": "QUESTION",
    "questionId": "csat",
    "text": "Did this solve your problem?",
    "answers": [
      { "id": "yes", "label": "Yes" },
      { "id": "no", "label": "No" }
    ]
  }
}
```

When the customer picks an answer, push an `ANSWER` trigger back with `responseToId` set to the envelope's `turnId` and `answerId` set to the chosen answer's `id` — this closes the loop (see the "Push triggers" section above):

![](https://media.notiondesk.so/upload/6a60b7dfdb2e8656690129.svg)QUESTION to ANSWER loop

Diagram source (Mermaid)```mermaid
sequenceDiagram
	participant You as Your Widget
	participant Salted as Salted CX
	Salted->>You: QUESTION action (turnId, answers [yes, no])
	Note over You: Customer picks "yes"
	You->>Salted: ANSWER trigger (responseToId = turnId, answerId = "yes")
```





### [](#delivery-semantics)Delivery semantics

- Respond with any 2xx status to acknowledge. The response body is ignored.

- Acknowledge fast — respond within 1 second and do any processing asynchronously. A delivery attempt that takes longer times out on our side and counts as a failed attempt.

- Any non-2xx response or timeout is retried; after retries are exhausted the message is marked undelivered on our side.

- Delivery is at-least-once — deduplicate by `turnId`, which never changes across retries.

- Order is not guaranteed under retries; use `occurredAt` for display ordering.

- Expect a natural delay between pushing a trigger and receiving the reply: each turn is processed by YourLogic before anything is delivered to your webhook — this applies to agent replies too.

*Tags: Integration, Universal Chat, Your Logic*


---

## Review

Source: https://help.salted.cx/en/articles/model-review


Reviews contain individual feedback related to engagements or turns. Reviews have large scale use in Salted CX. Reviews are created among others in the following cases:

- During [manual quality assurance](https://help.salted.cx/en/collections/1755201479-quality-assurance).

- Salted CX auto reviewers that review 100% of conversations.

- Customer satisfaction surveys.

Each individual item in Review data set contains an answer to a single question. So if you review an engagement with a form and you reply to multiple questions within that form, you will have multiple review items related to the same engagement.





## [](#data-set-properties)Data Set Properties

| Property | Type | Description |
|---|---|---|
| Review | [PID](https://help.salted.cx/en/collections/1755206106-logical-model?v=24f5d3a2a8dc81f49249000c3e502787#2565d3a2a8dc8010b907f9c8aeac496e) | Unique identifier of this individual review. |
| Engagement | Reference to [Engagement](https://help.salted.cx/en/articles/model-engagement) | Engagement this review is related to. |
| Turn | Reference to [Turn](https://help.salted.cx/en/articles/model-turn) | Turn this review is related to. |
| Reviewer | Reference to [Reviewer](https://help.salted.cx/en/articles/model-reviewer) | Reviewer who provided this review. The reviewer can either be a person or a service. |
| Question | Reference to [Question](https://help.salted.cx/en/articles/model-question) | Question which was reviewed. |
| Review Time | [Date and Time](https://help.salted.cx/en/articles/model-dates) | The time when the review was last updated. |
| Review Session | [Entity](https://help.salted.cx/en/collections/1755206106-logical-model?v=24f5d3a2a8dc81f49249000c3e502787#2565d3a2a8dc8040887dfa7ea6952826) | Groups reviews into session so if there are more questions answered during a session they can be reported as one unit. |
| Answer | Entity | What answer the reviewer selected. The answer is identified by the text that was provided to them. |
| Comment | Attribute | The comment associated with the single review. |
| [Sampling](https://help.salted.cx/en/articles/model-review#64a19905043d425198c4a50e11af4ccf) | [Enumeration](https://help.salted.cx/en/collections/1755206106-logical-model?v=24f5d3a2a8dc81f49249000c3e502787#2565d3a2a8dc80bfb945e38d99038ba8)Focused, Random, Selected, All | Sampling method used for selecting which engagement or turn to review. This enables to distinguish mostly from random and focused sampling method. |
| [Status](https://help.salted.cx/en/articles/model-review#0d8740f506be48428a1ea6f8d9e672c8) | Enumeration Completed, Deleted, Ignore, Pending, Rejected, Timeout | The current state of the review. |
| [Type](https://help.salted.cx/en/articles/model-review#64a19905043d425198c4a50e11af4ccf) | Enumeration Agent, Auto, Customer, Reviewer | Type of the review. |
| Used Form | Entity | The form that the reviewer used when creating this review. Be careful that one question can be used in multiple forms. This attribute stores only the form which the user had open at the time when creating the review, not other forms where the question is present. |
| Verification Comment | Attribute | The comment that a person who provided feedback to this review. |
| Verified | Enumeration Acknowledged, Correct, Disputed, Incorrect, Unclear |  |
| Verified By | Entity | The person who performed the review. |
| Answer Score | [Fact](https://help.salted.cx/en/collections/1755206106-logical-model?v=24f5d3a2a8dc81f49249000c3e502787#2565d3a2a8dc80189ad1cb926fd85828) | The score associated with the review in the original scoring system. The value is between minimum and maximum score (both inclusive). |
| Confidence | Fact | The confidence with which the review answer was given. This is useful especially for auto review services. |
| Minimum Score | Fact | The minimum possible score for the question. |
| Maximum Score | Fact | The maximum possible score for the question. |
| Score | Fact | The score associated with the review normalized to percentages. |







## [](#sampling)Sampling

Sampling represents how it is decided that a conversation, engagement or turn was chosen for a review.

| Sampling | Description |
|---|---|
| Focused | All engagements matching a certain condition were used for reviews. This is useful for reviews intended to get deeper understanding of a potential issue or opportunity. They are typically not a fair representation of an agent performance. |
| Random | Random sample of engagements was selected for the review. Reviews with random sampling are the best possible representation of an agent performance. |
| Selected | The reviewer selected the conversation ad-hoc. This may happen for example when a user is in customer journey and encounters something where feedback is necessary or helpful. |
| All | The review is offered to everybody. |



## [](#status)Status

The current status of the review. In the most common cases you want to filter this attribute to `Completed` value. However the other states can be used for more targeted use cases. See the table below for more details.

| Status | Description |
|---|---|
| Completed | The review is completed and it can be included in the reports. |
| Deleted | The review was deleted and should not be in the results. |
| Ignore | The review is not relevant. |
| Pending | The review is scheduled but the reviewer has not answered yet. This may happen in case you have planned reviews that reviewers should do and you want to report on those that are yet to be done. |
| Rejected | The reviewer rejected to review the engagement. This may happen in case that the reviewer concludes that the engagement is not a good representative sample to review. |
| Timeout | The review was requested but the reviewer has not provided it. This may happen when reviewers did not have time to review or for customer reviews the customers simply choose not to answer. |







## [](#type)Type

Type attribute is used to filter the source of the review.

| Type | Description |
|---|---|
| Agent | Review provided by the agent on their engagements. This type of review enables you to gather the agent's perspective. |
| Auto | The review was provided by an automated service. |
| Customer | The review was provided by the customer. This is typical for customer journeys. |
| Reviewer | The review was provided by a person responsible for quality assurance in the company. This person is different from the agent who handled that engagement. |

*Tags: Logical Model*


---

## Alerts

Source: https://help.salted.cx/en/articles/dashboards-alerts


Alerts enable you to keep an eye on important metrics without watching dashboards all the time.

You can use alerts for example to:

- Watch when customer satisfaction score drops below your required dashboards

- Watch when the customers experience longer wait times than the previous day

- Watch when auto review finds an undesired behavior in conversations

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

Only users of Salted CX can receive alert notifications. Users cannot create alerts that notify people to arbitrary email addresses.





## [](#create-alert)Create Alert

You can create an alert from any dashboard containing visualizations.

![](https://media.notiondesk.so/upload/698b1167911f6345544155.png)

To create a new alert:

1. Move pointer over a visualization top right corner and click on the three dots button when it appears

2. In When menu choose a metric contained in the visualization you would like to watch

3. In For menu choose on which attribute used in the visualization you would like to watch the metric. For example you can choose a specific channel, queue or team you watch. You can also watch the metric overall without choosing a specific target.

4. Choose comparison function. You can use a comparison to a constant or to a previous time period.

5. Choose the value to compare the metric with

6. List people who will receive the alert emails

7. To choose whether to trigger the alert repeatedly click the gear button

![](https://media.notiondesk.so/upload/698b116aa0bcc463563974.png)

1. Click Create to create the alert

The alert uses the current filters applied to the dashboard. If you want to filter the the data for the alert differently, adjust the filters before you create the alert.

## [](#modify-alerts)Modify Alerts

When you open alerts on a visualization that already has some set up you will their list.

![](https://media.notiondesk.so/upload/698b116daa743039887393.png)

Click the three dots next to an alert to edit it, pause it of delete it.

## [](#disable-alerts)Disable Alerts

You can prevent users from creating alerts for individual visualizations in the visualization editor.

## [](#limits)Limits

The number and executions of alerts is limited to ensure fair use.

| Limit Description | Limit |
|---|---|
| Maximum number of alerts and scheduled exports | 200 |
| Maximum number of recipients in recipients field | 60 |
| Maximum number of scheduled exports in a 24-hour period | 100 |
| Maximum number of alert executions in a 24-hour period | 600 |
| Minimum time between scheduled exports | 60 minutes |
| Minimum time between alert executions | 60 minutes |
| Maximum size of attachments in email | 40 MB |
| Maximum number of attachments per scheduled export | 10 |

*Tags: Dashboards*


---

## Question

Source: https://help.salted.cx/en/articles/model-question


The questions data set contains questions answered during reviews.

| Property | Type | Description |
|---|---|---|
| Question | [PID](https://help.salted.cx/en/collections/1755206106-logical-model?v=24f5d3a2a8dc81f49249000c3e502787#2565d3a2a8dc8010b907f9c8aeac496e) | Unique identifier of the Question. |
| ID | [Label](https://help.salted.cx/en/collections/1755206106-logical-model?v=24f5d3a2a8dc81f49249000c3e502787#2565d3a2a8dc801684edeb3e8e714fb3) for Question | ID of the question in the original platform. |
| Name | Label for Question | Name of the question in the original platform. |
| Link | Label for Question | Link to the question in the original platform. |
| Category | [Entity](https://help.salted.cx/en/collections/1755206106-logical-model?v=24f5d3a2a8dc81f49249000c3e502787#2565d3a2a8dc8040887dfa7ea6952826) | The category of the question. |



![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

Only Questions that have already some answers are visible in reporting. When you create a form but nobody used it for a review the questions are not yet visible in reporting.

*Tags: Logical Model*


---

## External Agent

Source: https://help.salted.cx/en/articles/model-external-agent


Article short description

External agent represents a person or an organization outside of your company that can engage with the customers in the conversations.





## [](#data-set-properties)Data Set Properties

| Property | Type ● Mandatory ○ Highly Recommended | Description |
|---|---|---|
| External Agent | [PID](https://help.salted.cx/en/collections/1755206106-logical-model?v=24f5d3a2a8dc81f49249000c3e502787#2565d3a2a8dc8010b907f9c8aeac496e) | Primary identifier of the external agent. |
| External Agent Category | [Entity](https://help.salted.cx/en/collections/1755206106-logical-model?v=24f5d3a2a8dc81f49249000c3e502787#2565d3a2a8dc8040887dfa7ea6952826) | Custom high-level category of the external agents. You can use this for example to distinguish couriers, sellers, consulting partners, non-customer care company employees etc. |
| External Agent ID | [Label](https://help.salted.cx/en/collections/1755206106-logical-model?v=24f5d3a2a8dc81f49249000c3e502787#2565d3a2a8dc801684edeb3e8e714fb3) for External Agent | Identifier of the external agent. This can be for example the agent email (support email of the partner). |
| External Agent Name | Label for External Agent | Human-readable name of the external agent. |
| External Agent Status | Entity | The status of the agent that enables to filter those that are active (more relevant for reporting). |

*Tags: Logical Model*


---

## Engagement

Source: https://help.salted.cx/en/articles/model-engagement


Engagement data is a core data set containing all customer engagements organized into conversations and linked to important attributes that enable to filter and segment them.





| Property | Type ● Mandatory ○ Highly Recommended | Description |
|---|---|---|
| Engagement | [PID](https://help.salted.cx/en/collections/1755206106-logical-model?v=24f5d3a2a8dc81f49249000c3e502787#2565d3a2a8dc8010b907f9c8aeac496e) ● | Unique identifier of this engagement. |
| Agent | Reference to [Agent](https://help.salted.cx/en/articles/model-agent) ○ | The agent who engaged with the customer. |
| Contact | Reference to [Customer](https://help.salted.cx/en/articles/model-customer) ● | The contact the customer used during this engagement. Contact is a specific phone number, email, username, or other identifier. The original contact information is replaced by an anonymized identifier and is not visible in analytics. |
| Start Time | [Date and Time](https://help.salted.cx/en/articles/model-dates) ● | The time when the engagement started including a preparation phase if there is any. Start time is available for all engagements. |
| End Time | Date and Time ○ | The time when the engagement ended including a wrap-up phase if there is any. End time is not available for engagements that are [in progress](https://help.salted.cx/en/articles/model-engagement#74260c199da64c1b940c568d34966d1c). |
| Campaign | [Entity](https://help.salted.cx/en/collections/1755206106-logical-model?v=24f5d3a2a8dc81f49249000c3e502787#2565d3a2a8dc8040887dfa7ea6952826) | Campaign this engagement is part of. This can be for example outbound call campaign, emailing campaign or marketing campaign with a dedicated company contact that enables to categorize engagements. |
| [Case](https://help.salted.cx/en/articles/model-engagement#6f8539af2fa141ee8ca4de22726a628b) | Entity | The case is associated with the current engagement. Cases are units that can span many engagements, conversations, and even customers. Thus cases are no directly part of a customer journey as they may touch multiple customers. However, cases might be useful to calculate aggregated metrics to associate effort, costs, etc. with them. |
| Channel | Entity ○ | Channel is a granular channel identifier. |
| [Channel Type](https://help.salted.cx/en/articles/model-engagement#24a5dd77902c48139ddfdf2f17bde46e) |  | High level category of a channel which enables you to distinguish between engagements that may have very different expected metrics and attributes. |
| Channel Vendor | Entity ○ | The vendor used for handling this engagement. This enables you to understand what applications and service customers use or prefer. |
| Company Contact | Entity | The company contact that the customer reached or your agents used to reach the customer. |
| Conversation | [Attribute](https://help.salted.cx/en/collections/1755206106-logical-model?v=24f5d3a2a8dc81f49249000c3e502787#2565d3a2a8dc80b4a012f2965acc2b09) ○ | Conversation group together multiple Engagements into one [conversation](https://help.salted.cx/en/articles/model-customer-journey-structure#532baca81c6f443fa52373c897de1b36). |
| Direction | Enumeration ○ Inbound, Outbound, Internal, Unknown | The direction of the conversation. Direction should be the same for all engagements in the conversation based on the direction of the first engagement. |
| Engaged Team | Entity ○ | The team in which the agent when engaged in this engagement. |
| Flow | Entity | The flow trough which the engagement was processed. This can be name of the automated process created within a platform workflow editor or it can be a specific implementation or feature of the source platform how to process conversations. |
| Language | Entity | The predominant language is associated with the engagement. In a multi-lingual contact center. This enables you to segment engagements by the language you are serving. |
| Location | Entity | Location in which the engagement happened. |
| Menu Path | Entity | The menu path the customer went through during the last menu engagement. |
| Outcome | Entity ○ | Outcome of the engagement. How outcome is determined depends on the [engagement type](https://help.salted.cx/en/articles/model-engagement#0f719d44063d4d0e920851aa37e4097f). |
| Outcome Category | Entity ○ | Higher level of outcome that enables to categorize them for example by kind of conversations they are related, by failure/success or categorize by other criteria. |
| Platform | Entity | The platform name in which this engagement happened. |
| Priority | Entity | The priority of the engagement represented by a category. |
| Queue | Entity ○ | The queue with which the engagement is associated with. The meaning differs by the type of the engagement. |
| Reason | Entity ○ | The reason why the customers contact the company. This may be based on customer input, agent input or automatically detected based on the environment. |
| [Service Level](https://help.salted.cx/en/articles/model-engagement#8cebd21422a64d4c8a545e1980152827) | Enumeration Within SLA, Out of SLA, Ignore | Information whether this engagement was handled according to set service level standards. |
| Source | Entity | The account identifier in the platform in which this engagement happened. You can have multiple accounts in a single platform connected to one Salted CX account. This attribute enables you to show the engagements by this account. |
| [Status](https://help.salted.cx/en/articles/model-engagement#8cebd21422a64d4c8a545e1980152827) | Enumeration ○ Completed, Corrupted, Deleted, In Progress, On Hold | Engagement state represents the current state of the engagement. The state can change over time as engagements may be long-running. In this case, they may appear as in progress and later be completed. |
| Terminated By | Enumeration Agent, Customer, System, Technical, Unknown | Tells who has terminated the engagement. Typically a person who left the conversation. For example, during a phone call, this is when the participant hangs up. |
| [Type](https://help.salted.cx/en/articles/model-engagement#0f719d44063d4d0e920851aa37e4097f) |  | High-level type of the engagement. This categorizes engagements into very different kinds of categories that typically do not show in the single reporting. |
| Cost | [Fact](https://help.salted.cx/en/collections/1755206106-logical-model?v=24f5d3a2a8dc81f49249000c3e502787#2565d3a2a8dc80189ad1cb926fd85828) | The cost of engaging in this conversation. This includes all costs that are possible to attribute in a given environment including agent salaries, technology stack costs, used services, etc. |
| Engagement Time | Fact ● | The time from the moment when agent and a customer start talking together until they disconnect. |
| Focus Time | Fact | The time the agent spent focused on the engagement. In a multitasking environment when agents can be engaged in multiple conversations at the same time the focus time tries to isolate the time when the agent’s attention is focused solely on this engagement. |
| Hold Time | Fact | The time the customer spent waiting without the ability to talk to an agent during the engagement. Note that engagement time includes the hold time. |
| Invitation Time | Fact | The time the agent was invited to join the conversation. |
| Preparation Time | Fact | The time the agent spent before an engagement with a customer to prepare for it. This can be for example a research on customer history before reaching to them to ensure they better understand the customer. |
| Time | Fact | Technical timestamp representing Start time. As fact this can be used for sorting and arithmetics. |
| Wait Time | Fact ○ | The time the customer or an agent spent in waiting to be connected to an agent. The meaning of wait time differs by [engagement type](https://help.salted.cx/en/articles/model-engagement#0f719d44063d4d0e920851aa37e4097f). |
| Wrap Up Time | Fact ○ | The time the agent spent wrapping up the conversation after the customer is disconnected. |



## [](#cases)Cases

Cases enable you to connect engagements by case if the conversations are grouped by cases and tickets or other high-level requests.

## [](#channel-type)Channel Type

Channel type is a high-level way of categorizing channels.

| Channel Type | Description |
|---|---|
| Email | The engagement is an email conversation that has its specifics. It can have longer messages. |
| Chat | The engagement represents a chat where users communicate using messages instantly. |
| SMS | The engagement represents SMS or a similar short message system engagement. |
| Task | The engagement represents a generic task. |
| Video | The engagement represents a video call. |
| Voice | The engagement represents a voice call. |



## [](#conversation)Conversation

Conversation is an attribute that groups multiple Engagements into a single [Conversation](https://help.salted.cx/en/articles/model-customer-journey-structure#532baca81c6f443fa52373c897de1b36). There is an explicit data set containing individual conversations. Thee conversation is just a container for Engagements linked with the same permanent identifier.

## [](#direction)Direction

Direction is the same for every engagement in a conversation and it is based on the first engagement. So even when agents consult during an inbound conversation with other agents the engagement representing the consulting part is still Inbound (not Internal). Keeping the direction the same for all engagements is intended to simplify reporting.

| Direction | Description |
|---|---|
| Inbound | The conversation was initiated by the customer. |
| Internal | The conversation was initiated by an agent in the contact center and led to another agent in the contact center. |
| Outbound | The conversation was initiated by an agent (or dialer) in the contact center and led to a customer outside of the contact center. |



## [](#outcome)Outcome

Available outcomes depend on your business needs. This is typically called wrap code or disposition code based on the platform.

## [](#service-level)Service Level

Service Level indicates whether the engagement was handled within a required SLA policy.

| Service Level | Description |
|---|---|
| Within SLA | The engagement was handled according to service level requirements. |
| Out of SLA | The engagement was not handled within the service level requirements. |
| Ignore | The engagement should be excluded from any calculation of SLA-based metrics. |







## [](#status)Status

Engagement status represents the current state of the engagement. The status can change over time as engagements may be long-running. In this case, they may appear as in progress and lated be completed.

| Status | Description |
|---|---|
| Completed | The Engagement is over. The agent handling that Engagement has no further work associated with the given engagement. After this, the engagement metrics and attributes should not change unless updated by loading custom data. |
| Corrupted | Salted CX has not received all the data necessary to calculate some key metrics or attributes. These engagements may be the result of incomplete data received from a source platform. Corrupted engagements may appear when there is a problem with the underlying platform and it fails to deliver all the events it should, when there is a network issue between the source platform and Salted CX, or when there is an issue in Salted CX directly. Corrupted engagements are available for transparency and for being excluded from reporting when necessary. |
| Deleted | The Engagement was flagged as deleted. This means it should be excluded from most of the reporting unless the reporting is not specifically targeted deleted engagements. |
| In Progress | The Engagement has started but has not yet been completed. |
| On Hold | The Engagement is in progress technically but has a hold state to indicate no agent is busy working on the engagement. |



## [](#engagement-type)Engagement Type

Engagement type splits engagements into very different categories of engagements that have very different meanings. In the vast majority of metrics and reports you will want to filter by this attribute to get expected results.

| Type | Description |
|---|---|
| [Agent](https://help.salted.cx/en/articles/model-engagement#39981d0d52d1417a8ad7e91a583fb359) | Single agent’s engagement in a conversation. The agent can be either a human or a service such as bot, voicemail, etc. |
| Agent Activity | This engagement is a technical engagement that represents an agents in a given status. |
| Flow | This engagement is an engagement when customer was in a flow. |
| [Invitation](https://help.salted.cx/en/articles/model-engagement#d9c1d9d430374101b2b5b65a017a660d) | Invitation that asks an agent to join the conversation. |
| [Menu](https://help.salted.cx/en/articles/model-engagement#3b0e3a2e6bea48d381ea2453b5868a98) | Engagement in which the agent went through a process of picking options in a menu. This can be IVR for phone calls. |
| [Queue](https://help.salted.cx/en/articles/model-engagement#399481fd40864f3c8c4bc48e6cebfe71) | Customer or an agent waiting in a queue. |
| Technical | Item in Engagement Data Set that is stored there only for technical reasons. Typically to make reporting easier to use. |



### [](#agent-engagements)Agent Engagements

Agent engagements are engagements in which the customer and agent talk together.

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

Agent does not always have to be a person. There might be bots and other services that handle the customer. If you are interested in human only engagements you should make sure you use [Agent Type](https://help.salted.cx/en/articles/model-agent#e1bdc12e3c3340fdb90f6a2ee8673858) to filter the data.





### [](#invitation-engagements)Invitation Engagements

Invitation Engagements represent an invitation of an agent to a conversation.

| Property | Type | Description |
|---|---|---|
| Engagement | PID | Unique identifier of this engagement. |
| Agent | Reference to [Agent](https://help.salted.cx/en/articles/model-agent) | The agent who was invited to join the conversation. |
| Start Time | Date and time | The time when the invitation was created. |
| End Time | Date and time | The time when the invitation was accepted by an agent, was rejected and timed out. |
| Campaign | Attribute | Campaign this engagement is part of. This can be for example outbound call campaign, emailing campaign or marketing campaign with a dedicated company contact that enables to categorize engagements. |
| [Case](https://help.salted.cx/en/articles/model-engagement#6f8539af2fa141ee8ca4de22726a628b) | Attribute | Case associated with the current engagement. Cases are units that can span many engagements, conversations and even customers. Thus cases are no directly part of a customer journey as they may touch multiple customers. However cases might be useful to calculate aggregated metrics to associate effort, costs, etc. with them. |
| Channel | Entity | Channel is a granular channel identifier. |
| [Channel Type](https://help.salted.cx/en/articles/model-engagement#24a5dd77902c48139ddfdf2f17bde46e) | Attribute | High level category of a channel which enables you to distinguish between engagements that may have very different expected metrics and attributes. |
| Channel Vendor | Attribute | The vendor used for handling this engagement. This enables you to understand what applications and service customers use or prefer. |
| Company Contact | Entity | The company contact that the customer reached or your agents used to reach the customer. |
| Conversation | Attribute | Conversation group together multiple Engagements into one [conversation](https://help.salted.cx/en/articles/model-customer-journey-structure#532baca81c6f443fa52373c897de1b36). |
| Direction | Attribute | The direction of the conversation. Direction should be the same for all engagements in the conversation based on the direction of the first engagement. |
| Engaged Team | Entity | The team in which the agent when engaged in this engagement. |
| Language | Attribute | The predominant language associated with the engagement. In a multi-lingual contact center this enables you to segment engagements by the language you are serving. |
| Menu Path | Entity | The menu path the customer went through during the last menu engagement. |
| [Outcome](https://help.salted.cx/en/articles/model-engagement#74260c199da64c1b940c568d34966d1c) | Entity | `Accepted` for invitations that the agent accepted `Rejected` for invitations that the agent explicitly rejected `Time Out` for invitations that the agent did not respond to a given time-out `Revoked` for invitations that were revoked before the time out and before the agent had any chance to respond |
| Outcome Category | Entity | `Invitation` |
| Platform | Attribute | The platform name in which this engagement happened. |
| Priority | Attribute | The priority of the engagement. |
| Queue | Entity | The queue with which the engagement is associated with. The meaning differs by the type of the engagement. |
| [Service Level](https://help.salted.cx/en/articles/model-engagement#8cebd21422a64d4c8a545e1980152827) | Attribute | — |
| Source | Attribute | The account identifier in the platform in which this engagement happened. You can have multiple accounts in a single platform connected to one Salted CX account. This attribute enables you to show the engagements by this account. |
| [Status](https://help.salted.cx/en/articles/model-engagement#8cebd21422a64d4c8a545e1980152827) | Attribute | `Completed` for invitations that are accepted, rejected or timed out `In Progress` for invitations that are created but were not yet accepted/rejected/timed out |
| [Type](https://help.salted.cx/en/articles/model-engagement#0f719d44063d4d0e920851aa37e4097f) | Attribute | `Invitation` |
| Cost | Fact | — |
| Engagement Time | Fact | — |
| Focus Time | Fact | — |
| Hold Time | Fact | — |
| Invitation Time | Fact | The time the agent was invited to join the conversation. |
| Preparation Time | Fact | — |
| Time | Fact | Technical timestamp representing Start time. As fact this can be used for sorting and arithmetics. |
| Wait Time | Fact | — |
| Wrap Up Time | Fact | — |



### [](#queue-engagements)Queue Engagements

Queue engagement represents a customer ([which can be of type agent](https://help.salted.cx/en/articles/model-customer#526dfcf74caa4348a25cf069877fd4f4)) in a queue. Waiting in queue happens when you have limited number of people (eventually other resources) that can handle the customer request and you have nobody (or no resources) available for a given customer. Queues enable to overcome unavailability time period.

There might be multiple queue engagement when the customer moves from one queue to another.

| Property | Type | Description |
|---|---|---|
| Engagement | PID | Unique identifier of this engagement. |
| Agent | Reference to [Agent](https://help.salted.cx/en/articles/model-agent) | — |
| Contact | Reference to [Customer](https://help.salted.cx/en/articles/model-customer) | The contact the customer used during this engagement. Contact is a specific phone number, email, username or other identifier. The original contact information is replaced by an anonymized identifier and is not visible in analytics. |
| Start Time | Date and time | The time when the customer started to wait in the queue. |
| End Time | Date and time | The time when the customer left the queue for any reason. |
| Campaign | Attribute | Campaign this engagement is part of. This can be for example outbound call campaign, emailing campaign or marketing campaign with a dedicated company contact that enables to categorize engagements. |
| [Case](https://help.salted.cx/en/articles/model-engagement#6f8539af2fa141ee8ca4de22726a628b) | Attribute | Case associated with the current engagement. Cases are units that can span many engagements, conversations and even customers. Thus cases are no directly part of a customer journey as they may touch multiple customers. However cases might be useful to calculate aggregated metrics to associate effort, costs, etc. with them. |
| Channel | Entity | Channel is a granular channel identifier. |
| [Channel Type](https://help.salted.cx/en/articles/model-engagement#24a5dd77902c48139ddfdf2f17bde46e) | Attribute | High level category of a channel which enables you to distinguish between engagements that may have very different expected metrics and attributes. |
| Channel Vendor | Attribute | The vendor used for handling this engagement. This enables you to understand what applications and services customers use or prefer. |
| Company Contact | Entity | The company contact that the customer reached or your agents used to reach the customer. |
| Conversation | Attribute | Conversation group together multiple Engagements into one [conversation](https://help.salted.cx/en/articles/model-customer-journey-structure#532baca81c6f443fa52373c897de1b36). |
| Direction | Attribute | The direction of the conversation. Direction should be the same for all engagements in the conversation based on the direction of the first engagement. |
| Engaged Team | Entity | — |
| Language | Attribute | The predominant language is associated with the engagement. In a multi-lingual contact center, this enables you to segment engagements by the language you are serving. |
| Menu Path | Entity | The menu path the customer went through during the last menu engagement. |
| [Outcome](https://help.salted.cx/en/articles/model-engagement#74260c199da64c1b940c568d34966d1c) | Entity | `Accepted` when the |
| Outcome Category | Entity | `Queue` |
| Platform | Attribute | The platform name in which this engagement happened. |
| Priority | Attribute | The priority of the engagement. |
| Queue | Entity | The queue in which the customer is waiting. |
| [Service Level](https://help.salted.cx/en/articles/model-engagement#8cebd21422a64d4c8a545e1980152827) | Attribute | `Within SLA` if the customer waited within the range defined in the SLA. `Out of SLA` if the customer waited longer than defined in the SLA. |
| Source | Attribute | The account identifier in the platform in which this engagement happened. You can have multiple accounts in a single platform connected to one Salted CX account. This attribute enables you to show the engagements by this account. |
| [Status](https://help.salted.cx/en/articles/model-engagement#8cebd21422a64d4c8a545e1980152827) | Attribute | `Completed` if the customer already left the queue |
| [Type](https://help.salted.cx/en/articles/model-engagement#0f719d44063d4d0e920851aa37e4097f) | Attribute | High level type of the engagement. This categorizes engagements into very different kind of categories. |
| Cost | Fact | The cost for engaging in this conversation. This includes all costs that are possible to attribute in a given environment including agent salaries, technology stack costs, used services, etc. |
| Engagement Time | Fact | The time from the moment when agent and a customer start talking together until they disconnect. |
| Focus Time | Fact | The time the agent spent focused on the engagement. In multitasking environment when agent can be engaged in multiple conversations in the same time the focus time tries to isolate the time when the agent’s attention is focused solely on this engagement. |
| Hold Time | Fact | The time the customer spent waiting without the ability to talk to agent during the engagement. Note that engagement time includes the hold time. |
| Invitation Time | Fact | The time the agent was invited to join the conversation. |
| Preparation Time | Fact | The time the agent spent before an engagement with a customer to prepare for it. This can be for example a research on customer history before reaching to them to ensure they better understand the customer. |
| Time | Fact | Technical timestamp representing Start time. As fact this can be used for sorting and arithmetics. |
| Wait Time | Fact | The time the customer or an agent spent in waiting to be connected to an agent. The meaning of wait time differs by [engagement type](https://help.salted.cx/en/articles/model-engagement#0f719d44063d4d0e920851aa37e4097f). |
| Wrap Up Time | Fact | The time the agent spent wrapping up the conversation after the customer is disconnected. |



## [](#terminated-by)Terminated By

Indicates how the engagement was terminated and by whom.

| Terminated By | Description |
|---|---|
| Agent | The agent left the engagement while the customer was still in the engagement. |
| Customer | The customer left before the agent. |
| System | The engagement was terminated by the system as expected. This is for example the case when a customer arrives at the end of an IVR. |
| Other | The connection reason is none of the others. |
| Technical | The connection was terminated due to technical reasons. |

*Tags: Logical Model*


---

## Rich Text in Dashboards

Source: https://help.salted.cx/en/articles/dashboards-rich-text


To add rich text to a dashboard simply drag and drop the item Rich Text item from the left to any place in the dashboard.

![](https://media.notiondesk.so/upload/689dd8595b607790053560.png)

## [](#headings)Headings

To create a heading, add one to three number signs `#` at the start of the line. The number of the sign indicate the heading level.

```markdown
# Heading Level 1

## Heading Level 2

### Heading Level 3

The normal paragraph just states that you should not go deeper than heading level 3 as the text gets more difficult to read for the users..
```

![](https://www.gooddata.com/docs/dashboards/rich-text-headings.png)

## [](#new-lines)New Lines

To create a new line, end a line with two or more spaces, and press return. To create a new paragraph leave an empty line.

```markdown
Sentence followed by a new line.
Sentence followed by two spaces and a new line.
Sentence followed by a new line and an empty line.

The next paragraph.
```

![](https://www.gooddata.com/docs/dashboards/rich-text-line-breaks.png)

## [](#emphasis)Emphasis

To make text italic, surround the text with one asterisk `*`:

```markdown
*These words* are italicized.
```

To make the text bold, surround the text with two asterisks `**` :

```markdown
**These words** are bold.
```

To make the text bold and italic, surround the text with three asterisks `***`:

```markdown
***These words*** are bold and italicized.
```

![](https://www.gooddata.com/docs/dashboards/rich-text-emphasis.png)

## [](#lists)Lists

Create numbered list by using the number follower by a period. The list must start with the number one:

```markdown
1. First Item
2. Second Item
3. Third Item
```

Create bulleted list by starting a line with an asterisks `*`:

```markdown
* Item
* Item
* Item
```

To nest something into the list, indent it using four spaces or a tab.

```markdown
1. First Item
1. Second Item

    I need to add another paragraph below the second list item.

1. Third Item
```

![](https://www.gooddata.com/docs/dashboards/rich-text-lists.png)

## [](#links)Links

Links enable users to open any web address from within the dashboard.

You can use links for:

- Open detailed explanation for business goals that the dashboard is targeted towards

- Open detailed documentation related to the dashboard

- Navigate to related dashboards or visualizations

- Navigate to other items in Salted CX such are forms, questions, etc.

Create a link by surrounding the link text by square brackets `[Link Text]` followed (without a space) by the target web address surrounded by parentheses `(https://target.web.address/including/path)`. You can add tooltip that shows when hovering over the link by adding the tooltip text in quotes `"This is the tooltip text"` following the web address.

```markdown
Check or business goals related to [Customer Satisfaction](https://company.com/goals/satisfaction).

See a more detailed breakdown of metrics in the [Agent Dashboard](https://company.salted.cx/dashboards/3e218922-98a2-4523-a718-2784cf5d032a "Dashboard focusing on the agent performance from all perspectives").
```

![](https://media.notiondesk.so/upload/689dd85b83d85972546278.png)

## [](#images)Images

Images can help with explanation of how to interpret data in a dashboard. Often an image is worth thousand words and can help your users to better understand what to search for in individual charts and tables.

Insert image by using exclamation mark `!`, followed by description of the image in square brackets `[Image Description]`, followed by a path to the image in parentheses `(https://full-url-to-the-image.png)` . You can add tooltip that shows when hovering over the image by adding the tooltip text in quotes `"This is the tooltip text"` following the web address.

```markdown
![Illustration of false positives and false negatives in auto reviews](https://help.salted.cx/assets/images/auto-reviews-accuracy.8cc89328-828a-443d-b254-6efade5de0c4-cffec17770b1c3372f6a14a6f3ab5645.png)
```

![](https://help.salted.cx/assets/images/auto-reviews-accuracy.8cc89328-828a-443d-b254-6efade5de0c4-cffec17770b1c3372f6a14a6f3ab5645.png)

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

You cannot change the size of the image. If the image is too large it is resized to fit the dashboard layout.





### [](#blockquotes)Blockquotes

Create blockquotes by starting a line with `>`.

```markdown
I am going to create a blockquote:

> First line of a blockquote.
> This is still on the first line. But if we follow this line by two spaces...
> Now we're on the second line.
>
> The line above this one displays empty.
> Certain other **formatting** is also *supported* inside a blockquote.
>> This is a nested blockquote.

And we are back inside a normal paragraph.
```

![](https://www.gooddata.com/docs/dashboards/rich-text-blockquotes.png)

### [](#horizontal-divider)Horizontal Divider

Add horizontal dividers with a line that has three or more hyphens `---` without any other text on the line.

```markdown

The first line.

---

The second line.
```

![](https://www.gooddata.com/docs/dashboards/rich-text-dividers.png)

### [](#special-characters)Special Characters

To show a character that is normally used for formatting precede it by a backslash `\`:

```markdown
\* This is no longer an unordered list.

And \*\*this\*\* is not bold.
```

## [](#unsupported-markdown-features)Unsupported Markdown Features

The following features of markdown are not supported:

- Tables

- Embedding HTML

*Tags: Dashboards*


---

## Customer

Source: https://help.salted.cx/en/articles/model-customer


Customers data set contains contacts grouped into customers by a customer attribute.

| Property | Type | Description |
|---|---|---|
| Contact | [PID](https://help.salted.cx/en/collections/1755206106-logical-model?v=24f5d3a2a8dc81f49249000c3e502787#2565d3a2a8dc8010b907f9c8aeac496e) | Unique identifier of the contact used by the customer in given engagements. Contact is a specific phone number, email, username or other identifier. The original contact information is replaced by an anonymized identifier and is not visible in analytics. |
| Customer | [Entity](https://help.salted.cx/en/collections/1755206106-logical-model?v=24f5d3a2a8dc81f49249000c3e502787#2565d3a2a8dc8040887dfa7ea6952826) | Grouping contacts together into one person or other entity you want to represent as a single customer. |
| Category | Entity | Broad grouping of customers into categories. For example split between B2B and B2C customers. |
| Region | Entity | Geographic region that the customer is in. This is typically a high level unit covering multiple states such as North America, EMEA, APAC, etc. |
| Country | Entity | The country name associated with the customer. |
| Organization | Entity | Groups customers into their organizations. For example if you provide B2B services to large companies and you want to associate the individual customers with those companies. |
| Segment | Entity | Groups customers by (market) segment enabling you to better understand differences in customer behavior in different demographics, areas of interest, etc. |
| State | Entity | The state eventually other territory that is part of the country. |
| [Type](https://help.salted.cx/en/articles/model-customer#526dfcf74caa4348a25cf069877fd4f4) | [Enumeration](https://help.salted.cx/en/collections/1755206106-logical-model?v=24f5d3a2a8dc81f49249000c3e502787#2565d3a2a8dc80bfb945e38d99038ba8) | High-level type of customer to distinguish between physical people, organizations and agents in internal calls. |



## [](#type)Type

Type is used to distinguish customers that are actual customers.

| Type | Description |
|---|---|
| Agent | The customer is actually an agent. This is common for internal conversations. For internal conversations, the initiating agent is stored in the customer data set. This is done to keep the [Logical Model](https://help.salted.cx/en/collections/1755206106-logical-model) in an analytical-friendly shape. |
| Organization | The customer does not represent a single physical person but an external organization. This means multiple physical people may have conversations on behalf of the organization without the ability to distinguish between them based on contact information in the metadata. |
| Customer | The customer is a physical person. In most environments, this is the most common type of customer that represents a person outside of your company. |
| Technical | The customer item for technical reasons such as referential integrity. |

*Tags: Logical Model*


---

## Drill Down

Source: https://help.salted.cx/en/articles/dashboards-drill-down


Dashboards are a great starting point for understanding high-level performance and identifying outliers. To take action, however, you often need to understand what exactly happened in the conversations.

Drill down enables you to add interaction to dashboards. When users click an attribute or a metric you can make Salted CX go to another dashboard, open an visualization, open [Customer Journey](https://help.salted.cx/en/collections/1755250527-customer-journey) or open a web page.

To set up drill down:

- Go to Dashboards

- Click the dashboard to which you would like to add drill down to

- Click Edit

- Click the visualization where you would like to add drill-down

- Click the three dots in the top right corner![](https://media.notiondesk.so/upload/689dd85c2fced140798504.png)

- Click Interactions in the menu

- Click Add interaction in the menu![](https://media.notiondesk.so/upload/689dd85f1a71e929063686.png)

- Choose what metric or attribute users have to click to initiate drill down![](https://media.notiondesk.so/upload/689dd8618d63f620447009.png)

- Click Choose action… in the I want to section

- In the menu choose one of the options depending what is the destination
    - [Drill into dashboard](https://help.salted.cx/en/articles/dashboards-drill-down#5f331d2b828240479a213dfade7fa318) takes users to another dashboard with the filtering criteria set to the attribute or set of attributes that are applied on the item you users click on. So if a user clicks on an agent and the target dashboard has the agent filter the dashboard is filtered only to the data related to that agent.
    
    
    - [Drill into visualization](https://help.salted.cx/en/articles/dashboards-drill-down#939a0f6ad667458c86c0fb84bdd7a09b) opens a visualization in an overlay dialog filtered to the attribute or set of attributes that are applied on the item you users click on.
    
    
    - [Drill down based on attribute hierarchy](https://help.salted.cx/en/articles/dashboards-drill-down#65fd41c3b39d4010bfc1c01160190590) enables you to follow natural hierarchies in the data such as an organization structure.
    
    
    - [Drill into URL](https://help.salted.cx/en/articles/dashboards-drill-down#3c5ff2f31ab04ba2bf7676260a9b835c) opens either [Customer Journey](https://help.salted.cx/en/articles/dashboards-drill-down#270cd518b0a1481c954dd84eb3c276ca) or an [arbitrary web page](https://help.salted.cx/en/articles/dashboards-drill-down#d31308a54896450eae1535054ca998bf).

## [](#drill-down-to-dashboard)Drill Down to Dashboard

Drilling to another dashboard enables you to go to any other dashboard. This is very useful to drill down for example to agent scorecards, single queue statistics and other dashboards focused on looking at a single attribute from multiple different directions. Another use is to focus on a specific metric.

After clicking on Drill into dashboard:

- Click Choose dashboard…

- You can use Search all dashboards… to narrow down

- Click the dashboard you want to drill down to![](https://media.notiondesk.so/upload/689dd8649431c455839063.png)

The advantage of the drill-down to dashboards is that the target dashboards can contain drill-downs to further dashboards and customer journeys. They are great for following data further and narrowing the search with every click.

## [](#drill-down-to-visualization)Drill Down to Visualization

Drilling to a visualization is useful to get a quick look at more granular data such as a look into a list of individual conversations, engagements, and reviews.

After clicking on Drill into visualization:

- Click Choose visualization…

- You can use Search all visualizations… to narrow down the visualizations

- Click the visualizations you want to drill down to![](https://media.notiondesk.so/upload/689dd8670d7a3738848644.png)

## [](#drill-down-in-an-attribute-hierarchy)Drill Down in an Attribute Hierarchy

This drill-down enables you to drill into the same visualization segmented by a more granular attribute. This is useful for getting more details in the organization hierarchy.

Built-in supported Hierarchies:

- All dates and times have the hierarchy Year ⏵ Quarter ⏵ Month ⏵ Day ⏵ Hour ⏵ Minute

- Organization: Location ⏵ Organization ⏵ Engaged Department ⏵ Engaged Team ⏵ Agent

- Channel: Channel Type ⏵ Channel ⏵ Channel Vendor

- Queue: Direction ⏵ Queue ⏵ Engaged Team ⏵ Agent

- Outcome: Engagement Status ⏵ Reason ⏵ Outcome Category ⏵ Outcome

- Agent Activity: Availability ⏵ Agent Activity

- Source: Platform ⏵ Source

### [](#custom-hierarchy)Custom Hierarchy

You can create a custom drill-down hierarchy to fit your business needs and organization structure. These hierarchies work together with the built-in hierarchies. When editing a dashboard users will be able to pick what hierarchy to use for each used visualization.

To create a new drill-down hierarchy:

- 

## [](#drill-down-to-customer-journey)Drill Down to Customer Journey

Drill down to [Customer Journey](https://help.salted.cx/en/collections/1755250527-customer-journey) sends users to the customer journey where they can check what happened in conversations between agents and customers.

To create a drill down to customer journey you need to choose Drill into URL and provide the URL in the expected format. After clicking Drill into URL:

- Click Choose URL![](https://media.notiondesk.so/upload/689dd86974796079273572.png)

- Click Add custom URL in the menu

- Type `https://salted.cx/customers/`, `https://salted.cx/conversations/`, `https://salted.cx/engagements/`, or `https://salted.cx/reviews/` into the URL text field, depending on where you want to go in the customer journey and what granularity of data you have in the visualization

- From the Parameters choose the corresponding attribute and click on it so it appears in the URL text field after the beginning of the address from the previous step (the attribute appears in orange)![](https://media.notiondesk.so/upload/689dd86bb3f8f646270809.png)

The table below shows different URLs that you can use to drill down to different places within a customer journey:

| Target | Address | Description |
|---|---|---|
| Customer | `https://salted.cx/customers/{attribute_title(Customer.Customer)}` | Opens [Customer Journey](https://help.salted.cx/en/collections/1755250527-customer-journey) scrolled to the most recent conversation. |
| Conversation | `https://salted.cx/conversations/{attribute_title(Engagement.Conversation)}` | Opens [Customer Journey](https://help.salted.cx/en/collections/1755250527-customer-journey) scrolled to the conversation. |
| Engagement | `https://salted.cx/engagements/{attribute_title(Engagement.Engagement)}` | Opens [Customer Journey](https://help.salted.cx/en/collections/1755250527-customer-journey) scrolled to the engagement. |
| Review | `https://salted.cx/reviews/{attribute_title(Review.Review)}` | Opens [Customer Journey](https://help.salted.cx/en/collections/1755250527-customer-journey) scrolled to the specific engagement or turn that has the associated review. |



## [](#drill-down-to-a-web-page)Drill Down to a Web Page

Drill down to a web page enables users to go to any web page (for example your CRM, workforce management, etc.)

To create a drill down to customer journey you need to choose Drill into URL and provide the URL in the expected format. After clicking Drill into URL:

- Click Choose URL![](https://media.notiondesk.so/upload/689dd86ed10ea723598716.png)

- Click Add custom URL in the menu

- Into the URL field type any web address you want to send users to. You can use any attribute from the Parameters menu in the URL to open a specific page such as a profile of an agent, customer, or any other object in the destination application.![](https://media.notiondesk.so/upload/689dd87238ad5895608321.png)

You can use all attributes and their labels used in the visualization from where the users drill down. You can also use the following dynamic variables:

- Visualization ID is the ID of the insight that contains the drill down. This is a UUID identifier.

- Dashboard ID is the ID of the dashboard from which the user drills down. This is a UUID identifier.

- Workspace ID is your domain without region. So if you have Salted CX on `company.eu.salted.cx` then the workspace ID will be `company`.

Additionally, you can pass the currently applied filters to the URL. This enables the destination web page to apply the same filtering criteria as in the Salted CX dashboard. To add currently applied filters to the custom URL just click add next to them in the Edit custom URL dialog. You can use dashboard-level filters or visualization-level filters (as individual visualizations in a dashboard can ignore some dashboard-level filters).

![](https://media.notiondesk.so/upload/689dd87447bd3431139808.png)

The filter added to the URL has the following format that the destination page has to parse from the URL (encoded):

- `IN["Attribute Value 1", "Attribute Value 2"]` if the filters list explicit values to include

- `NOT_IN["Attribute Value 1", "Attribute Value 2"]` if the filters list explicit values NOT to include

- `NOT_IN[]` if there are no filters applied

*Tags: Dashboards*


---

## Agent

Source: https://help.salted.cx/en/articles/model-agent


Agents data set represents people, bots and other systems that engage in Conversations with customers. Each [Engagement](https://help.salted.cx/en/articles/model-engagement) is attributed to at most one agent.





| Property | Type ● Mandatory ○ Highly Recommended | Description |
|---|---|---|
| Agent | [PID](https://help.salted.cx/en/collections/1755206106-logical-model?v=24f5d3a2a8dc81f49249000c3e502787#2565d3a2a8dc8010b907f9c8aeac496e) | Unique identifier of the agent. |
| ID | [Label](https://help.salted.cx/en/collections/1755206106-logical-model?v=24f5d3a2a8dc81f49249000c3e502787#2565d3a2a8dc801684edeb3e8e714fb3) for Agent ● | Platform identifier for the agent. |
| Name | Label for Agent ○ | User friendly display name for the agent. |
| [Department](https://help.salted.cx/en/articles/model-agent#4931af3cdbe448ffb5b24dd8f6fd50bb) | [Entity](https://help.salted.cx/en/collections/1755206106-logical-model?v=24f5d3a2a8dc81f49249000c3e502787#2565d3a2a8dc8040887dfa7ea6952826) | Department in which the agent currently is. |
| [Organization](https://help.salted.cx/en/articles/model-agent#4931af3cdbe448ffb5b24dd8f6fd50bb) | Entity | Organization unit in which the agent currently is. |
| [Team](https://help.salted.cx/en/articles/model-agent#4931af3cdbe448ffb5b24dd8f6fd50bb) | Entity ○ | Team in which the agent currently is. |
| [Type](https://help.salted.cx/en/articles/model-agent#e1bdc12e3c3340fdb90f6a2ee8673858) | [Enumeration](https://help.salted.cx/en/collections/1755206106-logical-model?v=24f5d3a2a8dc81f49249000c3e502787#2565d3a2a8dc80bfb945e38d99038ba8)Menu, Bot, External, User, Voicemail | Broad categorization of agents to distinguish human agents and other services that engage in conversations with the customers on behalf of the company. |
| [Version](https://help.salted.cx/en/articles/model-agent#b4c364609bbf427e9276e6da08378538) | [Attribute](https://help.salted.cx/en/collections/1755206106-logical-model?v=24f5d3a2a8dc81f49249000c3e502787#2565d3a2a8dc80b4a012f2965acc2b09) | If the agent is a bot or other service this attribute enables you to distinguish between its different versions. This might be useful for ensuring that the new versions provide better performance - for example using A/B testing. |
| [Status](https://help.salted.cx/en/articles/model-agent#859f927a79474361aee361e265e3e7a5) | Enumeration Active, Inactive | The current state of the agent. State enables to filter out agents that are no longer in the company. |
| [Cost per Hour](https://help.salted.cx/en/articles/model-agent#45c39d72a7e04de1a82413b8d3e05f14) | [Fact](https://help.salted.cx/en/collections/1755206106-logical-model?v=24f5d3a2a8dc81f49249000c3e502787#2565d3a2a8dc80189ad1cb926fd85828) | The current cost of work of the agent work per one hour. |
| [Cost per Engagement](https://help.salted.cx/en/articles/model-agent#45c39d72a7e04de1a82413b8d3e05f14) | Fact | The current cost of work of the agent’s work per one engagement. |



## [](#type)Type

Agent type is a broad categorization of agents. It is used to distinguish human agents from other services that may engage with the customer during conversations.

| Type | Description |
|---|---|
| Menu | Agent representing a menu (self-service, IVR, etc.) that the customer uses to achieve some goal. |
| Bot | Automated bot that tries to handle the customer without an involvement of a human. |
| External | The agent is an external entity. This agent can represent a single person or an entire company as the exact mechanism for handling the customer is outside of the control your company. |
| User | Human agent. An actual person working for the company. |
| Voicemail | Voicemail that enables customers to leave a message. Unlike robot voice mail has no ambition to resolve the customer issue. Its goal is just to capture customers’ requests for reaching back. |



## [](#version)Version

Versions can be used for distinguishing between different versions or configurations of the same bot or service. This can be very useful for ensuring different versions or configurations perform as expected.

Salted CX does not enforce a specific format for versioning the agents.

## [](#status)Status

Status is typically used to filter out agents that are no longer active in the company. This is particularly useful for filtering, as it allows you to see only those agents that are relevant in most cases.

| State | Description |
|---|---|
| Active | The agent is currently part of the company. This does not mean that the agent is currently in work. For bots this means they are used in the production. |
| Inactive | The agent does no longer work in the company. For bots this means they are no longer deployed in the production. You can deactivate the old versions of a bot one newer are released if you would like to use [versions](https://help.salted.cx/en/articles/model-agent#b4c364609bbf427e9276e6da08378538). |



![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

All agent related data stay in Salted CX even after an agent is deleted or deactivated in the source platform. Salted CX maintains the information to keep historical performance record for those agents.





## [](#hierarchy)Hierarchy

Salted CX offers attributes to represent an agent hierarchy. These attributes are (in order from the highest level to the lowest):

- Organization

- Department

- Team

For analytical purposes, the agent can be only in one team, one department, and one organization. This restriction is in place because many-to-many relationships in analytics introduce additional complexity for writing and understanding metrics, and incur significant performance penalties.

*Tags: Logical Model*


---

## Create Account

Source: https://help.salted.cx/en/articles/account


![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

You can currently use self-service to create accounts with data stored and processed only in the European Union. To create an account with data stored and processed in other regions please contact us at <help@salted.cx>





One account enables you to to access all features Salted CX offers on top of conversations from any number of data sources. Each account has a dedicated domain within a preferred region. For example mycompany.eu.salted.cx is an account of a company in the European Union. All domains in one region are on the same salted.cx sub-domain.

Each created account requires setup of Single Sign On and connecting data sources. You currently cannot do those yourselves. We will reach to you to setup those.

## [](#create-a-salted-cx-account)Create a Salted CX Account

Customers and partners on behalf of their customers can create an account with domain of their choice. We reserve the domain they choose across all Salted CX current and future regions. Each account can have only one user that does not use Single Sign On. This user is used to manage the account. We require multi-factor authentication for this user.

Follow these steps:

1. Ask your Salted contact for the URL where to get started.

![](https://media.notiondesk.so/upload/698b115847c93728250689.png)

1. Type the customer facing business name into Company field

2. Type the email you use for work into Work Email, this should not be email from personal email providers such as Gmail, iCloud, etc. You have to provide a valid email you have access to, so you can activate your account.![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)
    
    We recommend using a group email with multiple associated members, such as account-salted@mycompany.com. This prevents loss of account management access if one person becomes unavailable. A group email simplifies adding and removing people authorized to manage the Salted CX account. Note that each user in the group will need to set up their own multi-factor authentication, as outlined in the later steps.

3. Choose the Timezone that will be the default one for your account. Timezone influences the times we show in Salted CX. By default users inherit the company timezone but they can choose their own. Pick the timezone most people using Salted CX would use. You can also change timezone in settings later.

4. Type the Domain on which the application will run. We recommend to base this on your web site domain. For example if you have a website at mycompany.com you can use mycompany.eu.salted.cx.

5. Check the box I have read and agree with the [Terms of Use](https://www.salted.cx/terms-of-service) and [Privacy Policy](https://www.salted.cx/privacy-policy) if you agree with the policies

6. Press Register

![](https://media.notiondesk.so/upload/698b115bdfb75904492415.png)

1. Check your email inbox as the application asks you. We send the email from hello@salted.cx email.

![](https://media.notiondesk.so/upload/698b115f0459d115764687.png)

1. Click on the link Activate My Salted CX Account you receive via email

![](https://media.notiondesk.so/upload/698b1161d4b64529053707.png)

1. Choose a strong password to protect your access to your account and type the password into both New password and Confirm password fields

2. Press the Set New Password button

![](https://media.notiondesk.so/upload/698b1164aee4b903693135.png)

1. Use an MFA application to scan the QR code. You can use an application such as Google Authenticator ([Apple App Store](https://apps.apple.com/cz/app/google-authenticator/id388497605), [Google Play](https://help.salted.cx/en/articles/account)), Microsoft Authenticator ([Apple App Store](https://apps.apple.com/cz/app/microsoft-authenticator/id983156458), [Google Play](https://play.google.com/store/apps/details?id=com.azure.authenticator)), LastPass Password Manager ([Apple App Store](https://apps.apple.com/cz/app/lastpass-password-manager/id324613447), [Google Play](https://play.google.com/store/apps/details?id=com.lastpass.lpandroid&hl=en)) or similar.

2. Enter the code that the authenticator shows you into Code field

3. Press Set up MFA button

Congratulations! Now you have a Salted CX account. The first step to understand conversations between your customers and your agents.

## [](#single-sign-on)Single Sign On

Salted CX requires you to have a single sign-on for all users except the one you have just created. You can use a SAML provider of your choice to enable other people to access Salted CX.

Unless you [give users explicit permissions](https://help.salted.cx/en/articles/permissions), they will not be able to do anything in Salted CX. You do not need to be concerned that setting up single sign-on would grant people in your organization unwanted or unexpected access.

Follow guides for the specific platforms:

- [Google](https://help.salted.cx/en/articles/identity-provider-google)

- [Okta](https://help.salted.cx/en/articles/identity-provider-okta)

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

If you use a different identity provider please reach to us at <help@salted.cx> and we will help you with the setup.





## [](#technical-setup)Technical Setup

### [](#cloudflare)Cloudflare

If you are using Cloudflare and your users are experiencing network issues (for example, slow or no response when users click a conversation in Live Conversations), add a Do Not Inspect HTTP policy for `*.salted.cx` in Cloudflare Zero Trust Do Not Inspect HTTP policy for `*.salted.cx` in Cloudflare Zero Trust.

- Open the Zero Trust dashboard at <https://one.dash.cloudflare.com/>

- Go to Traffic policies → Firewall policies → HTTP tab and click Add a policy

- Name the policy (e.g. Do Not Inspect salted.cx)

- Set Domain → in → salted.cx and Action → Do Not Inspect

- Click Create policy and move it near the top of the list

## [](#data-sources)Data Sources

To get conversations into Salted CX, you need to connect your contact center platforms to your account as a new data source. Connecting data sources currently requires contacting the Salted CX team. We will reach out to you after your account is created to add all data sources to your account. You can also reach out to us at <help@salted.cx>.

See [supported data sources](https://help.salted.cx/en/collections/1755256026-integrations) to learn what contact center platforms you can connect to Salted CX.

## [](#data-from-multiple-regions)Data from Multiple Regions

One Salted CX is always in one region, so there is absolutely minimal risk for the data to leave the region from the moment they enter Salted CX infrastructure. In case a customer has data in platforms in several regions, they have the following options:

- One Salted CX account in one picked region to hold all the data. This enables the users to view data from all the data sources in one place. This requires the customer to ensure they have privacy policy and data protection policies that enable to move the conversation-related data to the chosen region.

- Multiple Salted CX accounts in regions that match the location of the data source. This ensures that the data do not leave the given region. This prevents the users from viewing all data in a single dashboard, table or chart.

Customers can also consider combining the two above to have one account for several regions and then dedicated accounts for regions from which they cannot move data to the common account.

---

## Custom Dashboards

Source: https://help.salted.cx/en/articles/dashboards-custom


You can build your custom dashboards in Salted CX. Your dashboards can use built-in visualizations and [custom visualizations](https://help.salted.cx/en/articles/visualizations-custom) in one canvas.

## [](#create-a-custom-dashboard)Create a Custom Dashboard

You can create a new dashboard either from scratch or from an existing built-in or custom dashboard.

### [](#create-a-new-dashboard)Create a New Dashboard

To create a new dashboard from scratch:

1. Go to Dashboards

2. Click New Dashboard

### [](#copy-an-existing-dashboard)Copy an Existing Dashboard

You can copy an existing built-in or custom dashboard:

1. Go to Dashboards

2. Click the dashboard that is the closest to the

3. Click the menu in the top right corner

4. Click Save as New

## [](#add-visualizations)Add Visualizations

Dashboards are collections of visualizations organized on a canvas. Ideally, one dashboard focuses on a small set of use cases and uses multiple visualizations to provide a look from multiple perspectives.

To add an visualization to a dashboard:

- Drag an visualization from the left panel anywhere to the dashboard canvas. Depending on where you move, Salted CX will highlight the area where the visualization will be dropped. You can place the visualization anywhere in the dashboard. When you place it below the last row you create a new section.

### [](#layout)Layout

The dashboards respond to the device screen size to rearrange the visualizations in a way that is best suitable for a user’s device. On a desktop computer, the visualizations are shown as you see them in the editor. On a phone, they will be shown in a narrow column one after another.

After adding visualizations you can change the dashboard layout by:

- Drag visualizations from one place to another to change the order of the visualizations in the dashboard.

- Move over the right side of an visualization to adjust its width. Note that the dashboard is split into 12 narrow columns which are the increments you can use when setting the dashboard width.

- Move over the bottom side of an visualization to adjust the height of all visualizations in the same row.

### [](#sections)Sections

Sections help you organize a dashboard. Sections are placed vertically one under another. Each section has an option title and description. Use this opportunity to describe to users the purpose of the dashboard or the section and how to use it.

To place an visualization into a new section drag a newly added visualization or visualization already in the dashboard below the last row of visualizations in the dashboard.

### [](#remove-insight)Remove Insight

To remove an visualization from a dashboard:

- Click the dashboard you want to remove

- Click on three dots in the top right corner

- Click Remove from dashboard in the menu

## [](#filters)Filters

You can add attribute filters to your dashboards. Attribute filters apply to all visualizations in the dashboard by default.

To add a filter to a dashboard:

- Drag an Attribute Filter item from the left pane to the filter bar on top of the dashboard

- Select the Attribute you want to use for filtering

- Select the default values in the filter. These are the values the users will see when opening the dashboard. They can change the filter afterward.

- Click Apply

- Now you will see the dashboard filtered to your selection.

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

You can change the default filtering criteria later by clicking on a filter and choosing different values.





### [](#exclude-filters)Exclude Filters

By default, each visualization in a dashboard is filtered by all filters in the dashboard. In some cases, you might want not to filter some visualizations by some attributes.

These are examples when you can disable filtering by a specific attribute:

- Show a long-term trend next to a recent performance. Chart showing the long-term trend would have filter by date disabled.

- Agent performance comparison with the team. Charts showing the team performance would have filtering by agent disabled.

- Team performance compared to the department or the entire contact center. Charts showing the performance of the higher level organization units would have filtering by team disabled.

To exclude individual visualizations from filtering:

- Click on the visualization you do not want to filter by one of the filters.

- Click the three dots button in the top right corner of the visualization

- Click Configuration in the menu

- In Filter by section uncheck all filters that you do not want to apply to the visualization

- Click outside of the menu

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

Under the Date option in the Filter by section, you have a menu where you can choose by what date and time to filter the contents. Choosing different dates and times shows different results in the reports. [Learn more about date and time](https://help.salted.cx/en/articles/model-dates).





## [](#drill-downs)Drill Downs

Drill downs enable you to explore data deeper whenever you find something interesting in a table or a chart. Drill downs enable to open visualizations, other dashboards, [Customer Journey](https://help.salted.cx/en/collections/1755250527-customer-journey) or external websites when you click on a metric or an attribute.

See [Drill Down from Dashboards](https://help.salted.cx/en/articles/dashboards-drill-down) for more details.

## [](#delete-dashboard)Delete Dashboard

To delete a dashboard in the Dashboards tab:

- Open the dashboard you want to delete

- Click the menu button in the top right corner

- Click Delete in the menu

- Click Delete in the confirmation dialog

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

Visualizations and metrics used in the deleted dashboard are not deleted. You can use them to build another dashboard.

*Tags: Dashboards*


---

## Activity

Source: https://help.salted.cx/en/articles/model-activity


Activity is a detailed agent status change (AUX codes) during the day including attribution to time. Each item in the Activity data set represents a sum of time spent in a single agent status (AUX code) in a 15-minute interval.

Each item in the Activity data set references a placeholder item in Engagement data set that links it the other data sets such as Agent and enables to report agent activity along side other metrics.

| Property | Type | Description |
|---|---|---|
| Activity | [PID](https://help.salted.cx/en/collections/1755206106-logical-model?v=24f5d3a2a8dc81f49249000c3e502787#2565d3a2a8dc8010b907f9c8aeac496e) | Unique identifier of this item in the data set. |
| Engagement | Reference to [Engagement](https://help.salted.cx/en/articles/model-engagement) | Unique identifier of an item in [Engagement](https://help.salted.cx/en/articles/model-engagement) |
| Interval Time | [Date and Time](https://help.salted.cx/en/articles/model-dates) | Time interval into which this activity is attributed. All activity in a given interval is attributed to the start of the interval regardless on when it actually started. |
| Agent Activity | [Entity](https://help.salted.cx/en/collections/1755206106-logical-model?v=24f5d3a2a8dc81f49249000c3e502787#2565d3a2a8dc8040887dfa7ea6952826) | The status that the agent was in or was supposed to be in. |
| [Availability](https://help.salted.cx/en/articles/model-activity#fa97924575694c4dbcd0b93070f7bba6) | [Enumeration](https://help.salted.cx/en/collections/1755206106-logical-model?v=24f5d3a2a8dc81f49249000c3e502787#2565d3a2a8dc80bfb945e38d99038ba8)Available, Unavailable | Split of agent status into high level availability items. |
| [Type](https://help.salted.cx/en/articles/model-activity#9455a227fb4142aea6d308b1f6043cff) | Enumeration Agent Activity | Type of the activity that this item represents. |
| Activity Time | [Fact](https://help.salted.cx/en/collections/1755206106-logical-model?v=24f5d3a2a8dc81f49249000c3e502787#2565d3a2a8dc80189ad1cb926fd85828) | Time spent in the activity by the agent. |
| Available Capacity | Fact | The total available capacity the agent had available. This includes capacity that is consumed. Free capacity can be calculated as Available Capacity - Consumed Capacity. |
| Consumed Capacity | Fact | The capacity that the agent actually consumed. |
| Scheduled Time | Fact | The time the agent was supposed to be in the given activity. |



## [](#availability)Availability

Categorizes agent status into high-level availability categories that indicate whether the agent was free to handle the customer conversations.

| Type | Description |
|---|---|
| Available | Agents are allowed to receive invitations to engage in conversations. This is typically considered a productive time. |
| Unavailable | Agents are logged into their agent desktop but are not expected to engage in conversations with customers. Unavailable activities are often considered not productive and can include activities such as break, meetings, administrative tasks, etc. |



![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

Offline agent activity is not reported in Salted CX. You can consider the offline time all the time that is not included in all Available and Unavailable agent activity.





## [](#type)Type

| Type | Description |
|---|---|
| Agent Activity | Actual agent activity as it happened in the platform. |

*Tags: Logical Model*


---

## Releases

Source: https://help.salted.cx/en/articles/releases


### [](#attach-comments-to-review-answers)Attach Comments to Review Answers

10 Sep 2026

Reviewers can now add a comment to a single-choice or tag answer in the Customer Journey, respecting the comment mode set on each question, so feedback can capture the reasoning behind a rating and not just the score. The coaching dialog and Pulse Check use the same form, so they get it too.

### [](#comment-mode-for-questions)Comment Mode for Questions

9 Sep 2026

Question settings gain a Comments option (Not Allowed, Optional, or Required) for single-choice and tag questions, giving admins control over whether reviewers can add context to an answer so feedback captures the "why," not just the rating.

### [](#local-answer-copies-for-questions)Local Answer Copies for Questions

7 Sep 2026

You can now create a local copy of an answer directly from a question and swap it in place of the shared one, and Salted shows you where an answer is used and warns before you change a shared answer — so editing one question can't quietly break others that rely on the same answer.

## [](#copy-a-link-and-content-of-any-turn)Copy a Link and Content of Any Turn

2 Sep 2026

Every turn in a Live conversation now has a hover "More" menu whose first action copies a shareable deep link that scrolls to and highlights that exact turn when opened, making it effortless to point a colleague at a specific moment when escalating or collaborating.

Second action copies content of the turn, so agents can grab a message's exact text in one click to reuse in notes or other systems — and masked PII is copied as readable labels rather than raw tokens, so nothing sensitive leaks in the process.

![](https://pub-6e850a88e7c944bfb05bc715893a058d.r2.dev/Release%20Notes/2Sep2026Release.png)

## [](#question-category-and-updated-filter-design-in-ask)Question Category and Updated Filter Design in Ask

1 Sep 2026

Ask can now filter reviews and engagements by question category, making it much faster to focus on the feedback that matters when you're analyzing quality across many different questions.

Ask filters also got a small redesign to keep consistent with the rest of the app.

![](https://pub-6e850a88e7c944bfb05bc715893a058d.r2.dev/Release%20Notes/1Sep2026Release.png)

## [](#configurable-toolbar-colors)Configurable Toolbar Colors

28 Aug 2026

Custom actions and conversation attributes in the Live toolbar can now be given colors that show on their buttons and pills, so agents can recognize the right control at a glance and move faster through busy conversations.

![](https://pub-6e850a88e7c944bfb05bc715893a058d.r2.dev/Release%20Notes/28Aug2026bRelease.png)

## [](#availability-filter-for-toolbar-canned-replies-questions)Availability Filter for Toolbar, Canned Replies &amp; Questions

28 Aug 2026

Toolbar actions, canned replies, and questions can now be restricted by channel, language, brand, and queue, so agents only ever see the ones relevant to the current conversation — cutting the clutter and helping them pick the right reply or action with fewer mistakes.

![](https://pub-6e850a88e7c944bfb05bc715893a058d.r2.dev/Release%20Notes/28Aug2026aRelease.png)

## [](#play-voice-call-recordings-in-the-conversation)Play Voice Call Recordings in the Conversation

26 Aug 2026

Completed voice calls in the Live conversation view now show a play button that expands an inline audio player and streams the recording, so agents and supervisors can review exactly what was said without leaving the conversation or digging through the journey view.

![](https://pub-6e850a88e7c944bfb05bc715893a058d.r2.dev/Release%20Notes/26Aug2026Release.png)

## [](#available-questions-in-live-conversations)Available Questions in Live Conversations

25 Aug 2026

Single-choice questions can now opt into Live, and the composer shows only the questions that fit the active conversation, so agents always reach for the right feedback questions for each channel and context without scrolling past the ones that are not relevant to them.

## [](#join-live-conversations-from-the-customer-journey)Join Live Conversations from the Customer Journey

20 Aug 2026

The Customer Journey now shows a customer's active Live conversations with a join control — including multi-conversation selection, channel and start-time details, together with help-needed indicators — so you can jump straight into a live conversation from the journey view.

## [](#live-tools-in-the-customer-journey)Live Tools in the Customer Journey

19 Aug 2026

The Customer Journey gains Live Tools tabs for customer engagements and turns, reusing the same panels and actions available in conversation views.

## [](#agent-activity-settings)Agent Activity Settings

19 Aug 2026

Account administrators can manage the set of activities agents choose from, and the default activity applied after login, from a new Agent Activity section in Live Conversations settings.

![](https://pub-6e850a88e7c944bfb05bc715893a058d.r2.dev/Release%20Notes/AgentActivity.png)

## [](#configure-chat-languages-per-brand)Configure Chat Languages per Brand

18 Aug 2026

Languages can now be configured per brand in Brand settings to set which languages are used

## [](#custom-conversation-info-panels)Custom Conversation Info Panels

14 Aug 2026

Admins can now configure custom Info Panels at the account and brand level in settings, which then appear to agents in the Conversation Info sidebar — building on the dynamic, variable-driven panels added earlier.

## [](#switch-customer-language)Switch Customer Language

14 Aug 2026

Agents can change a conversation's customer language from a selector in Live conversations, replacing the old toolbar language attribute.

![](https://pub-6e850a88e7c944bfb05bc715893a058d.r2.dev/Release%20Notes/LiveLanguage.png)

## [](#pause-and-resume-call-recording)Pause and Resume Call Recording

12 Aug 2026

Agents can now pause a voice call's recording while sensitive information like a credit card number is spoken, then resume it afterward — so that data is never stored.

## [](#schedule-a-conversation-back-to-needs-help)Schedule a Conversation Back to Needs Help

10 Aug 2026

Agents can park a Live conversation and from the reply action bar (button with clock) schedule its return to the Needs Help queue at a chosen time – up to 10 days out, optionally aimed at a specific agent and with an internal note attached.

![](https://pub-6e850a88e7c944bfb05bc715893a058d.r2.dev/Release%20Notes/ScheduleHelp.png)

## [](#supervisors-can-ask-for-help-without-joining)Supervisors Can Ask for Help Without Joining

3 Aug 2026

Supervisors viewing a conversation can now flag it as Help Needed without joining it. The Request Help button sits next to Join.

## [](#show-brand-name-or-logo)Show Brand Name or Logo

31 Jul 2026

Brands can now upload a logo (PNG/JPG) and choose how the chat header appears — logo, name, or both. Brand indicators show in Live conversations and carry through to Universal Chat.

![](https://pub-6e850a88e7c944bfb05bc715893a058d.r2.dev/Release%20Notes/Logo.png)

## [](#filter-conversations-by-language)Filter Conversations by Language

31 Jul 2026

Customer language is now a Live conversation filter and works with both personal and assigned filters.

## [](#engagements-per-day-in-team-view)Engagements per Day in Team View

31 Jul 2026

The Team View metrics table gains an "Engagements per Day" column, showing today's count alongside the daily average over the selected range.

## [](#cc-and-bcc-on-email-replies)CC and BCC on Email Replies

29 Jul 2026

Agents can now copy additional recipients on Live email replies. Toggle the CC/BCC button to reveal multi-value recipient fields.

![](https://pub-6e850a88e7c944bfb05bc715893a058d.r2.dev/Release%20Notes/CcBcc.png)

## [](#add-and-link-contacts-to-a-customer)Add and Link Contacts to a Customer

29 Jul 2026

Agents can add or link email and phone contacts to a customer directly from the Live conversation channel picker, with lookup, validation, and permission gating.

![](https://pub-6e850a88e7c944bfb05bc715893a058d.r2.dev/Release%20Notes/AddingContact.png)

## [](#email-signatures)Email Signatures

23 Jul 2026

Brands can now configure an email signature that appears, editable, in Live email replies. Signatures are combined with your message on send, kept per-conversation as you draft, and included in email question replies.

## [](#favorite-canned-replies)Favorite Canned Replies

22 Jul 2026

Mark canned replies as favorites so they surface first in the prepared-replies menu, alongside your recently used ones.

## [](#copy-smart-ids-from-a-conversation)Copy Smart IDs from a Conversation

22 Jul 2026

Smart IDs mentioned anywhere in conversation text — messages, questions, notes, and email subjects — are now detected and turn into one-click copy buttons.

## [](#edit-agent-attributes-in-the-agent-panel)Edit Agent Attributes in the Agent Panel

22 Jul 2026

Users with the right permission can now edit an agent's team, department, location, organization, manager, and role directly from the agent panel — picking existing values, creating new ones, or clearing them.

## [](#team-based-live-overview-enforced-filters)Team-Based Live Overview &amp; Enforced Filters

22 Jul 2026

Every active team appears in Live Overview with its full list of agents, even those with no current activity. Supervisors can also enforce which conversations agents see in the Needs Help queue — set per agent or per team.

## [](#redesigned-settings-pages)Redesigned Settings Pages

17 Jul 2026

Settings are reorganized into clear section cards with explicit, granular saving — save per section rather than the whole page — and every settings page now warns you before leaving with unsaved changes. Brand settings gain a dedicated Email tab.

## [](#message-variable-placeholders)Message Variable Placeholders

17 Jul 2026

Live messages support variable placeholders that survive draft reloads, and sending is blocked until any unresolved placeholders are filled in.

## [](#customer-engagement-detection-in-universal-chat)Customer Engagement Detection in Universal Chat

13 Jul 2026

Agents can now see whether the customers are actively

## [](#browser-notifications-for-live-conversations)Browser Notifications for Live Conversations

9 Jul 2026

Opt-in browser notifications alert you to new Live message or conversation even when the tab is in the background or the window has lost focus. Clicking a notification takes you straight to the relevant conversation. Toggle it from the bell in the sidebar's capacity indicator.

![](https://pub-6e850a88e7c944bfb05bc715893a058d.r2.dev/Release%20Notes/BrowserNotifications.png)

## [](#inline-email-attachments)Inline Email Attachments

8 Jul 2026

Attachments in email bodies now render inline at their actual position in the text — images as images, other files as a compact download chip — on both the conversation and journey screens.

## [](#refreshed-app-design)Refreshed App Design

3 Jul 2026

A visual refresh across core interface components — buttons, cards, inputs, search, tables, and more — for a cleaner, more consistent look.

## [](#see-when-customers-and-other-agents-are-typing)See When Customers and Other Agents Are Typing

26 Jun 2026

Agents can now see whether a customer or a fellow agent is typing. This is useful for an agent, as it gives others a few moments to provide additional information.

Customers cannot see whether an agent is typing or not.

## [](#send-questions-via-sms)Send Questions via SMS

25 Jun 2026

Agents handling voice-and-SMS conversations can now send feedback questions over SMS, in addition to email and in-app. Question content is shown for SMS and SALTED channels, and customer reactions now appear on bot messages.

![](https://pub-6e850a88e7c944bfb05bc715893a058d.r2.dev/Release%20Notes/SMS%20Questions.png)

## [](#live-conversation-direct-invitation)Live Conversation Direct Invitation

24 Jun 2026

Direct invitation to conversation now appears in the sidebar of the invited agent only with the option to Join or Decline. If the invitation is not accepted on time, it will move to the Help Needed section where anyone can start working on it.

## [](#admin-memo-on-the-live-homepage)Admin Memo on the Live Homepage

23 Jun 2026

Account admins can now set a markdown-formatted memo that appears below the greeting on the Live conversations homepage.

## [](#live-conversation-alerts)Live Conversation Alerts

22 Jun 2026

Live conversations can now be flagged with alerts, including automatic detection of bot failures. A new Alerts settings page lets you configure them.

## [](#send-questions-via-email)Send Questions via Email

22 Jun 2026

You can now send feedback questions to customers by email and let them reply from a link. Replies open on a dedicated page, answers are saved automatically as customers fill them in and additional feedback can be added.

![](https://pub-6e850a88e7c944bfb05bc715893a058d.r2.dev/Release%20Notes/Questions%20in%20Email.png)

## [](#a-new-live-conversations-homepage)A New Live Conversations Homepage

18 Jun 2026

The Live page now greets you by time of day and shows whether there's anything in the help-needed queue, with a one-click "join next" button when conversations are waiting.

![](https://pub-6e850a88e7c944bfb05bc715893a058d.r2.dev/Release%20Notes/Live%20Conversations%20Homepage.png)

## [](#native-charts-in-ask)Native Charts in Ask

18 Jun 2026

Ask now renders pie and XY charts as interactive visuals instead of static diagrams, and adds a preview of the scenario payload.

## [](#one-call-at-a-time-across-tabs)One Call at a Time Across Tabs

16 Jun 2026

Salted now tracks your active call across all open tabs and devices, so you can no longer start or join a second call while you're already on one.

## [](#reorganized-universal-chat-settings)Reorganized Universal Chat Settings

15 Jun 2026

Universal Chat settings now list your brands directly in the main settings sidebar, and each brand splits into a Brand tab (name, color) and a Chat tab for Universal Chat settings.

## [](#clearer-needs-help-indicator)Clearer "Needs Help" Indicator

12 Jun 2026

Conversations that need agent attention now show a blue dot on the corner of the conversation icon, instead of tinting the whole icon — making room for the new conversation alerts and easier to spot in the conversation overview page.

![](https://pub-6e850a88e7c944bfb05bc715893a058d.r2.dev/Release%20Notes/Help%20Needed%20Flag.png)

## [](#open-links-in-the-same-window)Open Links in the Same Window

9 Jun 2026

You can now create a link for Universal Chat that does open the link in the same window in which the Universal Chat currently is without opening a new browser window.

## [](#live-overview-conversation-column-redesign)Live Overview - Conversation Column Redesign

3 Jun 2026

Instead of a single aggregate count, each agent's conversations now appear as individual channel-icon slots — giving supervisors an immediate picture of workload, capacity, and where help is needed. Slot color shows conversation state: green for active, grey for waiting for a customer, and orange for help needed. Empty slots use a solid border up to the active limit and a dashed border in the "including waiting for customer" extension, making both concurrency thresholds visible. Actions like ‘Assign More’ or ‘Join Conversation’ can now be done directly from the slots.

## [](#streamlined-joining-of-conversations)Streamlined Joining of Conversations

28 May 2026

A new Join Next button at the top takes you straight into the next conversation waiting for an agent, with the New Conversation button right beside it. Below the main actions, a capacity panel shows how many conversations you're handling against your target, along with how long the longest-waiting customer has been waiting — so you can see at a quick glance whether to take on more.

![](https://pub-6e850a88e7c944bfb05bc715893a058d.r2.dev/Release%20Notes/Live%20Sidebar%20-%20Actions%20and%20Capacity.png)

## [](#better-omni-channel-support-in-navigation)Better Omni-Channel Support in Navigation

28 May 2026

Every conversation now shows its channel on the right, and voice calls are clearly marked. When a customer is calling in on one of your conversations, an Answer button appears on its sidebar row — it reads Jump In when a colleague is already on the call. To keep things focused, you can't start or join another call while you're already on one, and joining is paused when you've reached your maximum number of concurrent conversations.

![](https://pub-6e850a88e7c944bfb05bc715893a058d.r2.dev/Release%20Notes/Live%20Sidebar%20-%20Open%20conversation%20call.png)

## [](#link-to-start-conversation)Link to Start Conversation

26 May 2026

You can now easily start a new conversation from another application or a spreadsheet by opening a link to Salted CX. This lets you add a button in your CRM to start a call, send an email, and more. You can also create a simple formula in your spreadsheet to generate call links if you have a list of customers to call.

Learn how to [create new conversation links](https://help.salted.cx/en/articles/1781795869-links-to-salted-cx?v=24f5d3a2a8dc81f49249000c3e502787).





## [](#outbound-emails)Outbound Emails

25 May 2026

You can now send outbound emails from Live Conversations. If an agent has permission, they can now see the New Conversation button, which lets them type a contact to a customer and start a new outbound email conversation.





## [](#refreshed-design-of-universal-chat)Refreshed Design of Universal Chat

21 May 2026

Universal Chat now feature softer, more rounded look with improved spacing. Sender names and avatars (customizable in settings) appear below each message for better readability. File and image attachments have been redesigned — they now sit outside the bubble, aligned to the sender's side. Question buttons are now smaller and lighter, leaving more room for the conversation itself.

![](https://pub-6e850a88e7c944bfb05bc715893a058d.r2.dev/Release%20Notes/Updated%20Universal%20Chat.png)

The conversation list as well now has a more spacious, airy layout, with each entry showing how long ago the conversation took place as a clear headline.

![](https://pub-6e850a88e7c944bfb05bc715893a058d.r2.dev/Release%20Notes/Updated%20Universal%20Chat%20-%20All%20Conversations.png)

## [](#universal-chat-waiting-for-agent-message)Universal Chat Waiting for Agent Message

24 Apr 2026

You can now optionally inform customers in Universal Chat that their conversation is waiting for an agent. This feature is optional, and you can choose which message to show customers. When enabled, the customer is aware that a conversation is in the Needs Help section in Live Conversations. This provides greater transparency to your customers.

![](https://pub-6e850a88e7c944bfb05bc715893a058d.r2.dev/Release%20Notes/Universal%20Chat%20Waiting%20for%20Agent%20Message.png)





## [](#customize-the-universal-chat-avatars)Customize the Universal Chat Avatars

23 Apr 2026

You can now choose whether the customer will show who is responding to them from your side. You can customize whether the customer will be able to distinguish between the bot and the agent messages. You have the following options:

- No Avatars — The messages will not show who is the message author.

- Generic Avatar — The message will only show different icon for agents and different icon for the bot.

- Name — The message contains the full first name of the agent or the full name of the bot.

![](https://pub-6e850a88e7c944bfb05bc715893a058d.r2.dev/Release%20Notes/Customize%20the%20Universal%20Chat%20Avatars.png)





## [](#show-whole-conversations-in-sidebar)Show Whole Conversations in Sidebar

21 Apr 2026

Whenever you click an engagement in Ask or elsewhere in Salted CX, the sidebar now shows the entire conversation, not just the specific engagement. The conversation helps you see what happened before the agent engagement and better understand the context. For example, if you click on an engagement handled by the agent, you will also see that previously the conversation was handled by a bot, so you will understand what led up to the escalation and what information the agent had available from the bot engagement.





## [](#show-thinking-in-ask)Show Thinking in Ask

20 Apr 2026

The Ask now shows the thinking process. So when you ask a question, you have more visibility into what is happening behind the scenes. This helps you to understand how far along the AI is with responding to your question.

![](https://pub-6e850a88e7c944bfb05bc715893a058d.r2.dev/Release%20Notes/Steps%20in%20Ask.png)





## [](#engagement-descriptions-in-the-customer-journey)Engagement Descriptions in the Customer Journey

16 Apr 2026

The customer journey shows the current engagement summary so you can get the gist of the conversation without reading the entire transcript. This helps you quickly understand complex interactions and decide whether you need to spend more time on understanding the conversation.

![](https://pub-6e850a88e7c944bfb05bc715893a058d.r2.dev/Release%20Notes/Engagement%20Summary%20in%20CJ.png)





## [](#agent-home)Agent Home

13 Apr 2026

Agent Home is a screen that shows agents an overview of their performance and the feedback they receive from customers, Team Leaders, and Auto QA. Agents see how they are doing compared to their team and their past performance. Agents can review the feedback they got and either acknowledge it or dispute it. This feedback loop helps maintain good behavior, drive agent behavior change when necessary, and improve the quality assurance process while keeping agents aligned with it.

![](https://pub-6e850a88e7c944bfb05bc715893a058d.r2.dev/Release%20Notes/Agents%20Home.png)





## [](#vitals-screen)Vitals Screen

9 Apr 2026

The Vitals Screen enables you to monitor how Auto QA performs. It gives you visibility into your team's performance across individual metrics. It also helps you to review feedback from agents and other users on the reviews they have received. It enables you to check whether there is a large volume of disputes based on the feedback they have received.

![](https://pub-6e850a88e7c944bfb05bc715893a058d.r2.dev/Release%20Notes/Vitals.png)





## [](#filter-needs-help-by-channel)Filter Needs Help by Channel

7 Apr 2026

You can now filter Needs Help by Channel. This enables the agent to focus on handling specific channels — Chat or Emails. This is useful if you have different SLAs for the channels or if you have dedicated people focused on a specific channel.





## [](#auto-update-of-salted-cx)Auto Update of Salted CX

2 Apr 2026

The Salted CX user interface now automatically updates without requiring users to refresh the application. The auto update does not require any user action and happens when the users navigate between screens, such as jumping from one conversation to another, so no work in progress is lost when the auto update happens.





## [](#always-visible-call-player-in-customer-journey)Always Visible Call Player in Customer Journey

31 Mar 2026

The call audio player now keeps playing a call even when you scroll far away in a customer journey. This enables you to keep listening to conversations even when you explore other areas of the customer journey to better understand the customer experience.





## [](#pass-conversation-attributes-from-your-logic)Pass Conversation Attributes from Your Logic

30 Mar 2026

Your Logic bot implementation can now update conversation attributes during the conversation. This enables updating data visible in analytics and provides better visibility into conversations within the same segment. As attributes can change over the lifetime of the conversation, each engagement saves the attributes' values upon completion. So you can have multiple engagements in the same conversation with different attributes — for example, a bot can set that the outcome of their engagement was escalation to an agent, and an agent can tell that the outcome of their engagement was successfully resolved customer request.





## [](#modern-compact-navigation)Modern Compact Navigation

27 Mar 2026

Navigation in Salted CX is now on the left and more compact. This gives you more vertical space to see more of the actual conversations with the customer and longer conversations in Ask when you dig deeper into what is happening in the conversation.





## [](#attachments-in-messages)Attachments in Messages

26 Mar 2026

Live Conversations and Customer Journey now show files and images as attachments to messages, not as separate turns. This enables your bot to retrieve the file attachments as one item together with the customer message. This gives your bot, implemented in your logic, a better understanding of context because they see both the customer message and all files at once. Also, users see that the attachments were part of the message.





## [](#feedback-on-unsuccessful-agent-action)Feedback on Unsuccessful Agent Action

23 Mar 2026

When the agent presses a button in Live Conversations, and Your Logic bot cannot be reached due to a network error, or when Your Logic is unavailable, we show a message visible only to the agent that the action failed, so they are aware of the issue and can choose an alternative way to act.





## [](#emails-in-live-conversations)Emails in Live Conversations

23 Mar 2026

You can now receive emails in Live Conversations, so agents can handle them in the same user interface as chats without having to care about the channel. The agents can also follow up by email on chat conversations if the customer has an associated email.





## [](#force-change-agent-activity)Force Change Agent Activity

20 Mar 2026

Team Leaders and Supervisors can now change an agent's activity on the Overview screen. When agents leave their activity in a state that does not reflect reality, Team Leaders can choose a different activity. For example, when an agent goes on break, they leave their activity in an available state.





## [](#improved-reviews-in-customer-journey)Improved Reviews in Customer Journey

18 Mar 2026

Customer Journey now shows reviews as a list that is easier to read and uses available screen space more effectively to show you more feedback from conversations. This is especially useful when using our Auto QA features, which provide extensive feedback for every conversation.





## [](#custom-llm-for-translations)Custom LLM for Translations

13 Mar 2026

You can use a custom LLM service for translations in Salted CX. In case you have a preferred service for example because of good negotiated pricing, you can ask Salted CX to use the service.





## [](#better-attribution-of-reviews-to-engagements)Better Attribution of Reviews to Engagements

11 Mar 2026

Your Logic can now ask for customer satisfaction and other feedback and attribute it to another participant in the conversation. For example, when your bot asks for customer satisfaction after an agent engagement in a conversation, it can tell that the satisfaction should be attributed to the agent, not to the bot asking the question.





## [](#salted-cx-translation-service)Salted CX Translation Service

10 Mar 2026

Salted CX now offers a custom LLM-powered translation service that provides out-of-the-box real-time translation for Live Conversations. The built-in translation service is the easiest way to handle international customers in digital channels. Salted CX enables setting up a sequence of translation services to use as a fallback if the previous one does not handle the translation.





## [](#customer-metadata-in-live-conversations)Customer Metadata in Live Conversations

5 Mar 2026

You can now provide customer-related metadata when embedding our Universal Chat on your website, or update it from Your Logic bot implementation as the conversation progresses. Customer-related metadata enables filtering and segmenting conversations by customer country, region, marketing segment, and similar criteria.





## [](#silent-messages)Silent Messages

27 Feb 2026

Silent messages are messages that do not notify the customers or agents unnecessarily. These can be closing messages such as “Goodbye.”, “Have a nice day.”. These can be messages sent after the customer has already resolved the issue, and they are intended to close the conversation politely, but you do not want to reopen the conversation with the customer.





## [](#ask-about-customer-journey-and-conversation)Ask about Customer Journey and Conversation

24 Feb 2026

You can now ask about the complete customer journey or a conversation, even when they are really complex and involve many different agents and bots. This helps you to understand complete customer experiences across channels and multiple engagements with your company.





## [](#pick-activity-on-logout)Pick Activity on Logout

18 Feb 2026

When users log out and are not in an offline activity, they are prompted in the logout dialog to choose a logout activity. This prevents agents from appearing available when they are not giving you a better understanding of the current staffing level.





## [](#acknowledge-and-dispute-coaching-sessions)Acknowledge and Dispute Coaching Sessions

16 Feb 2026

Agents can now respond to coaching. They can acknowledge or dispute feedback they receive from their team leaders. Getting agents’ feedback to coaching is essential for keeping agents aligned with the expectations, enforcing desired bahavior and drive behavior change for unwanted behavior.





## [](#switch-agent-activity)Switch Agent Activity

16 Feb 2026

Agents can now indicate their activity from the application navigation. Their indicated status is also visible on the Overview screen to their Team Leaders and others. This gives people instant visibility into the current staffing.





## [](#agent-team-in-overview)Agent Team in Overview

13 Feb 2026

The Overview Screen now shows the agent team so you can focus on the agents you manage. You can sort all available agents, so all agents in the team are visible next to each other.





## [](#notification-about-new-message)Notification about New Message

11 Feb 2026

You can define custom buttons visible to agents. These buttons enable agents to trigger actions in Your Logic or to open web pages in a new browser window. Thanks to this, the agent can seamlessly integrate with other systems without having to search across systems.





## [](#compact-visualization-of-turns)Compact Visualization of Turns

10 Feb 2026

Message turns are now focused on reading the conversation content, and all other information is on the right side away from what you want to primarily read.





## [](#ask-about-agent)Ask about Agent

9 Feb 2026

You can now ask about the agent in their profile to understand their performance. Ask about the agent's focus, which only focuses on the engagements of that agent, getting you a better understanding of the agent’s strengths and weaknesses.





## [](#ask-about-selected-engagements)Ask about Selected Engagements

9 Feb 2026

You can now ask about





## [](#inactive-conversation-events)Inactive Conversation Events

5 Feb 2026

You can now set up Salted CX to send Your Logic an event in regular intervals if there is no activity in the conversation for the given time. This enables Your Logic implementation to respond to trigger scheduled actions, such as proactively reaching to the customer, updating customers on their request (instead of staying silent), closing conversations, etc.





## [](#invite-external-agents-from-your-logic)Invite External Agents from Your Logic

2 Feb 2026

You can now invite external agents to conversations from Your Logic. External agents do not have to be users os Salted CX. External agents receive an invitation email with a link that grants access to only one conversation, and their agent desktop is restricted to that conversation.

Inviting external agents via a bot lets you deflect customers to partners who might be better suited to help in some cases. This saves your agents’ time as they do not have to act as messengers in between. You still maintain full visibility into the entire customer experience.





## [](#enhanced-improve-reply)Enhanced Improve Reply

15 Jan 2026

When agents now press two dots to improve their reply, we use more metadata to help construct a better-tailored reply to the current conversation.





## [](#overview-in-live-conversations)Overview in Live Conversations

6 Jan 2026

You can now have a detailed overview of the traffic in Live Conversations. The Overview screen lists all agents that are available or are engaged in at least one conversation. You can see in what activity the agents are, for how long and how many conversations they handle.

You can jump to conversations from the screen to check how agents are doing.





## [](#engagement-completed-event-in-your-logic)Engagement Completed Event in Your Logic

22 Dec 2025

When any agent completes, leaves, or resolves an engagement, Your Logic receives an event. This enables closing the conversation using a bot, so the agent does not have to spend time on the closing. This is a great opportunity for bots to check whether the customer request was resolved and collect customer satisfaction.





## [](#update-conversation-from-universal-chat)Update Conversation from Universal Chat

22 Dec 2025

You can now update conversation metadata from the web page to provide more information for Your Logic. This enables the passing of important information about the conversation that the bot and agent can use to resolve the customer request faster without asking the customer unnecessary questions.





## [](#prevent-customers-from-posting-from-universal-chat)Prevent Customers from Posting from Universal Chat

22 Dec 2025

You can now prevent customers from responding while Your Logic is still processing a previous message. This enables simpler bots that struggle to handle messages customers might send in the meantime. This leads to better-structured conversations. However, due to its impact on the customer experience, this feature is optional, and you must enable it in Universal Chat settings.





## [](#complete-conversations-from-your-logic)Complete Conversations from Your Logic

22 Dec 2025

You can now complete the conversion from Your Logic. Completing a conversation indicates to the customer that their conversation is closed. The customer can still respond to a completed conversation.





## [](#your-logic-working-indication-in-universal-chat)Your Logic Working Indication in Universal Chat

22 Dec 2025

You cannot let customers in Universal Chat know that Your Logic is currently working on their request, or whether they should wait for an agent. You can decide whether to inform your customers about the wait for an agent as well.





## [](#receive-contacts-and-location-from-whatsapp)Receive Contacts and Location from WhatsApp

22 Dec 2025

You can now receive shared location and contacts from WhatsApp customers.





## [](#ask-ad-hoc-questions-from-your-logic)Ask Ad-Hoc Questions from Your Logic

15 Dec 2025

You can now ask ad-hoc questions from Your Logic. Ad-hoc questions enable to generate questions dynamically based on the current conversation without having them created in the Salted CX. You can formulate the question and include any number of custom answers. Each answer can also have a custom title. When the customer chooses one of the answers you will receive request from Salted CX to Your Logic.





## [](#start-new-conversation-from-your-logic)Start New Conversation from Your Logic

15 Dec 2025

Start a new conversation from Your Logic. This enables you to send outbound WhatsApp messages.





## [](#save-notes-in-live-conversations)Save Notes in Live Conversations

12 Dec 2025

Users can now save notes in Live Conversations. The notes enable to share information between agents and other users that is not visible to customers. This enables users to provide important context and updates directly in the conversation.





## [](#offered-conversations)Offered Conversations

11 Dec 2025

We now send an event that a customer opened our Universal Chat to Your Logic. This enables your bot to proactively send dynamic welcome message or initial menu options to the customer. Your bot can perform any actions as if the conversation was in progress. Only when a customer responds the conversation is switched to in progress status and appears in Live Conversations screen.

You can enable offered conversations from Universal Chat brand settings. This feature is disabled by default not to produce unexpected traffic to your bot.





## [](#translation-service-with-custom-dictionary)Translation Service with Custom Dictionary

10 Dec 2025

We now integrate with DeepL to provide translations with a custom dictionary. If the primary translation service becomes unresponsive we now use a fallback translation service without a custom dictionary to provide a temporary fallback functionality.

Update to the dictionary currently requires involvement of our professional services.





## [](#push-agents-to-conversations)Push Agents to Conversations

9 Dec 2025

Supervisors and Team Leaders can now force assign conversations to agents from the Live Overview screen.





## [](#participant-activity-in-live-conversations)Participant Activity in Live Conversations

8 Dec 2025

Live Conversations now shows timer since the last customer and last agent message to give you idea how long the participants are waiting for each other. Agents can use this information to make informed decisions about the urgency to respond and whether to wait for the customer.





## [](#conversation-urgency)Conversation Urgency

7 Dec 2025

You can now manage urgency of each conversation to influence in which order they are sorted in the queue offered to agents. This enables your bot or other business logic to sort the conversations to manage response times based on channel, customer business value, situation the customer tries to resolve or any other factor.

See [Conversation Urgency](https://help.salted.cx/en/articles/1765376502-conversation-urgency) for more details.





## [](#report-queues-by-who-ask-for-help)Report Queues by Who Ask for Help

4 Dec 2025

You can now filter the waiting customers in reporting by whether they are waiting because Your Logic asked for help or an agent asked for help. This helps to distinguish between escalations from bot and escalations from a fellow agents (for example to a supervisor or a team leader).





## [](#reference-service-data-set-in-live-conversations)Reference Service Data Set in Live Conversations

4 Dec 2025

You can now link live conversations to items in Service data set. This enables you to segment engagements by to what service they are related to. You can use Ingest API to load data associated with individual services.

Service data set enables you attribute conversations to services and products you are trying to sell or support.





## [](#translated-questions-and-answers)Translated Questions and Answers

4 Dec 2025

Live Conversations now translate questions and answers. The translations are done on the fly and cashed to provide consistent wording.





## [](#ask-questions-to-agents-from-your-logic)Ask Questions to Agents from Your Logic

4 Dec 2025

Your Logic can now ask questions to agents. This enables to enforce process adherence and save agents’ time. Agents can be engaged just at critical points where they need to make decisions that your bot cannot or should not due — such as confirming high impact translations.





## [](#auto-greeting-messages)Auto Greeting Messages

2 Dec 2025

When agents join a conversation, they can receive a message proposal that informs customers they have joined the conversation. Agents can review the message before sending, or they can decide not to use it.

You can set up multiple phrasings of such a message to have more variability. The messages can contain variables, allowing them to include information from the conversation context such as agent name, customer name and custom properties.





## [](#conversation-language-in-analytics)Conversation Language in Analytics

27 Nov 2025

Conversation language is now available in analytics. You can now segment and filter all metrics based on the customer language and understand whether your performance, customer satisfaction and other metrics differ in individual languages.





## [](#web-chat-localization)Web Chat Localization

22 Nov 2025

Our Universal Chat is now available in the following languages: Arabic, Catalan, Czech, Dutch, German, Finnish, French, Hungarian, Italian, Polish, Portuguese, Slovak, Spanish, Swedish, Turkish.





## [](#concurrency-targets)Concurrency Targets

21 Nov 2025

You can now set how many conversations in parallel agents are allowed to handle. Agents cannot join more conversations if they are at their maximum capacity.

You can also set how many conversations at minimum the agents should handle. If an agent has less than the targeted number of conversations and there is a conversation waiting in the Needs help their are encouraged to join an additional conversation.





## [](#unlimited-number-of-custom-buttons)Unlimited Number of Custom Buttons

20 Nov 2025

You can now have an unlimited number of custom buttons in Live Conversations. If there are too many buttons to fit on the screen the extra buttons are automatically collapsed to a menu so they remain available for agents.





## [](#take-over-auto-coaching)Take Over Auto Coaching

19 Nov 2025

Reviewers can now edit and save auto coaching that is in progress. This enables the team leaders to review the proposal by AI and have a final say before the feedback gets back to the agent.





## [](#live-overview-screen)Live Overview Screen

19 Nov 2025

You can now see overview of agents that are now engaged in handling the conversations from the customer.





## [](#option-to-block-free-text-answer-in-web-chat)Option to Block Free Text Answer in Web Chat

13 Nov 2025

Your Logic can now tell our Universal Chat to prevent customers to send free text answers. This option leads to more structured guided customer experience and can improve bit response times and save costs on LLMs for certain scenarios.

You can control this option for each question or menu you use in Universal Chat. For example have closed set of options initially and enable free text answer once the customer gets into a menu where the custom input becomes useful or necessary.

As always we recommend giving customers freedom in modality they choose so we encourage you not to overuse this feature.





## [](#longest-waiting-customer-in-needs-help)Longest Waiting Customer in Needs Help

13 Nov 2025

Live Conversations now show how long the longest does the longest waiting customer wait in Needs Help. Agents also have button that joins the conversation with the longest waiting customer.





## [](#improve-reply)Improve Reply

12 Nov 2025

Agents can improve their messages before sending them to a customer. Agents can write very short replies capturing the gist of the content to share with the customer and let Salted CX complete the reply based on you communication style.

Type two subsequent dots `..` in the response area and Salted CX proposes improved version of the sent message based on your communication style instructions.





## [](#manage-canned-replies)Manage Canned Replies

6 Nov 2025

You can now manage canned replies that agents can use in Live Conversations. Each canned reply has a shortcut that you can use. Canned replies are available in Live Conversations so agents can quickly send them based on what they need to tell the customer in a given situation.





## [](#manage-working-on-it-messages)Manage “Working on it” Messages

30 Oct 2025

You can now manage messages that send the customer the message that an agent is working on it. When an agent presses the “Working on it” button we chose a random message. This makes the conversations more varied and natural for both customers and agents.





## [](#open-customer-journey-from-live-conversations)Open Customer Journey from Live Conversations

23 Oct 2025

You can now open the customer journey from Live Conversations. This enables you to view complete cradle to grave conversation history with the current customer no matter using which channel or platform you used to talk to the customer.

Even when you used Salesforce or other platform supported by Salted CX in the past and now use Live Conversations agents can still see what happened during the legacy times in a single user interface.





## [](#supervising-live-conversations)Supervising Live Conversations

23 Oct 2025

Users with supervise permissions can now view contents of conversations without joining them. This enables them to quickly skim through what is currently happening in their teams. They can join the conversations if necessary.

Agents without the supervise permissions still cannot see the contents before joining to prevent them from cherry picking what they handle.





## [](#live-conversation-info)Live Conversation Info

23 Oct 2025

Agents in Live Conversations can now view information related to the conversation and update it if necessary. Conversation information enables the maintenance of free-text information for situation awareness and the exchange of information between agents and other stakeholders. Unlike notes that flow with the conversation, information is easily accessible at the top of the view.





## [](#canned-replies-in-live-conversations)Canned Replies in Live Conversations

23 Oct 2025

Agents can now send canned replies to customers. Each canned reply has a shortcut that you they can use to quickly find them and use them.





## [](#improved-colors-of-turns)Improved Colors of Turns

21 Oct 2025

The colors of individual turns are now more pronounced making it easier to recognize whether the messages are from the customer, agent, external agent, bot or system (for example system issues).





## [](#filter-needs-help-by-participants)Filter Needs Help by Participants

21 Oct 2025

Users can now filter Needs Help by participants who are currently engaged in the conversation. This enables agents or team leaders to focus on conversations that were escalated form the bot or the conversations that are handled by a fellow agents who need help.





## [](#wait-for-customer-button)Wait for Customer Button

20 Oct 2025

Agents now have a button that tells that they are waiting for a reply from the customer. This makes the conversation less pronounced. The time a conversation spends in waiting for customer status is reported in analytics and you can choose to exclude it from the engagement and handling time.





## [](#filter-all-in-progress-conversations-by-participants)Filter All in Progress Conversations by Participants

15 Oct 2025

You can now filter All in Progress section by participants. This makes it easy for supervisors to see conversations that are handled only by bot, or by agents.





## [](#new-live-messages-in-tab)New Live Messages in Tab

7 Oct 2025

Live Conversations now show in the browser tab when attention by an agent is necessary. Agents can work in different apps open in their browser without having to switch to Live Conversations just to check whether there is a new message.





## [](#highlight-conversations-with-new-messages)Highlight Conversations with New Messages

7 Oct 2025

Live Conversations that have new messages since the time last time when the agent had the conversation open now show a badge with the number of the new messages. The badge is color coded to show whether the new messages are from customer, fellow agents, external agents or bots.





## [](#participants-in-live-conversations-navigation)Participants in Live Conversations Navigation

1 Oct 2025

We now show the number of participants in a Live Conversations navigation to enable agents make bette decisions on what conversations to join.





## [](#leave-all-conversations-at-once)Leave All Conversations at Once

30 Sep 2025

Agents can now leave all their conversations at once. When an agents leave for a break or they go home they can ensure that somebody else attends to the customers. Agents can click on the number of the live conversations and choose from the menu why they need to leave them.





## [](#info-about-web-page-open-by-customer)Info About Web Page Open by Customer

29 Sep 2025

Universal Chat now keeps Your Logic updated about where on what web page the customer currently is. This enables Your Logic to taylor responses based on what content the customer sees when asking the questions.

Agents also see the current page the user is at in Live Conversations which gives them more context related to the customer request. Agents can click on the link to open the same page the customer is currently viewing.





## [](#show-all-live-conversations-in-progress)Show All Live Conversations in Progress

25 Sep 2025

If you have a given permission you can view all conversations in progress even when you are not engaged in them and they do need help.





## [](#send-image-from-universal-chat)Send Image from Universal Chat

25 Sep 2025

Customers can now send images from our Universal Chat.





## [](#restrict-viewing-of-visualizations-tab)Restrict Viewing of Visualizations Tab

24 Sep 2025

You can now use permissions to prevent users from viewing visualizations so they can view only dashboards that provide options to have much more guided experience for people viewing reporting data.





## [](#intuitive-filters-in-ask)Intuitive Filters in Ask

23 Sep 2025

The Ask feature now offers more intuitive filters, so you can easily narrow down your selection to the most relevant conversations you are exploring.

![](https://media.notiondesk.so/upload/6a9ac7d7786be158631941.png)

## [](#open-visualizations-from-dashboard)Open Visualizations from Dashboard

15 Sep 2025

You can now open individual visualizations from dashboards. You can use this to quickly edit individual charts and tables used in any dashboard.

## [](#join-conversation-screen)Join Conversation Screen

12 Sep 2025

Live Conversations now show a screen before joining the conversation to prevent agents from cherry picking conversations.





## [](#ask-for-help)Ask for Help

11 Sep 2025

The agents can ask for help from other agents. In case the agent does not know how to continue handling the customer.





## [](#number-of-live-conversations-in-navigation)Number of Live Conversations in Navigation

10 Sep 2025

Live Conversations now show how many conversations are in the individual sections which gives a quick overview your agents are currently facing and understand whether you need to make an action to ensure can handle the load.





## [](#reactions-in-universal-chat)Reactions in Universal Chat

2 Sep 2025

You can now allow customers to send reactions from universal chat. Under each message from the agent or bot the customer has a thumbs up and thumbs down button that enable quick expression of the satisfaction with the message the customer got.

When customers press one of the buttons Your Logic receives the information and can respond to it. For example a bot can decide to escalate in such scenario. The customer feedback is also available in reporting.





## [](#associate-score-and-description-with-answers)Associate Score and Description with Answers

2 Sep 2025

You can now add a description to an answer within a question to describe in detail what the answer means and what are the exact criteria to give this answer.





## [](#ask-about-dashboard)Ask About Dashboard

26 Aug 2025

You can now ask about data in the individual dashboard. Ask enables you to have questions about the content of the conversations or reviews related to conversations in the visualization. If the dashboard contains multiple visualizations, you can choose which visualization you would like to ask about, as they may contain different conversations.

![](https://media.notiondesk.so/upload/6a9ac7dc93f35927901859.png)

## [](#review-verification-details-in-dashboards-and-visualizations)Review Verification Details in Dashboards and Visualizations

18 Aug 2025

You can now utilize the Verification Comment and Verified By [Review](https://help.salted.cx/en/articles/model-review) attributes to build custom visualizations. These attributes contain details on who [acknowledged or disputed the received feedback](https://help.salted.cx/en/articles/1755230871-acknowledge-and-dispute-reviews?v=24f5d3a2a8dc81f49249000c3e502787). With this information available in the [Logical Model](https://help.salted.cx/en/collections/1755206106-logical-model), you can now view these without opening the customer journey for every single acknowledged or disputed review.

## [](#save-selection-from-visualization)Save Selection from Visualization

15 Aug 2025

You can now save a list of engagements or reviews in a visualization as a [named selection](https://help.salted.cx/en/collections/1755248079-visualizations#2575d3a2a8dc80cf8794d7cdea720960). The selection is a static list of the engagement or reviews that are present in the visualization at the time when you created the selection. The list does not change over time. This enables you to use these engagements and reviews later, for example, as training materials, a sample for testing Auto QA reviews.

## [](#favorite-dashboards-and-visualizations)Favorite Dashboards and Visualizations

13 Aug 2025

You can now mark dashboards and visualizations as favorite. Favorite dashboards and visualizations are on top of the navigation which makes it easy to get back to them. Favorites are individual for each user so everybody can pick what they need to see most without impacting their colleagues.

![](https://media.notiondesk.so/upload/6a9ac7de60e8a901146527.png)

## [](#session-history-in-ask)Session history in Ask

19 Jul 2025

## [](#ask-about-visualization)Ask about Visualization

5 Jun 2025

You can now ask questions about engagements and reviews in any visualization that contains them. This helps you understand why certain conversations have lower customer satisfaction, longer talk times, or worse outcomes than expected. The AI analyzes only conversations that match the filters you've selected in the visualization, making it easy to focus on the conversations that matter most.

After asking your first question, you can continue the conversation about the same selected conversations.

![](https://media.notiondesk.so/upload/6a9ac7e0bf4d0132640527.png)

## [](#external-agent-data-set)External Agent Data Set

28 May 2025

[External Agent](https://help.salted.cx/en/articles/model-external-agent) data set is used to associate external agents with a conversations. External agents are agents that are not employees in you company. This might be partners, vendors and similar businesses that help you with the customer requests. External agent can be represented by an entire company using a complex system to handle the customer conversations. Separate data set for external agents gives you better visibility into conversations that involve a 3rd party.

You can now use [External Agents](https://help.salted.cx/en/articles/model-external-agent) using drag and drop to build [custom visualizations](https://help.salted.cx/en/articles/visualizations-custom), use in filters, etc.

![](https://media.notiondesk.so/upload/6a9ac7e2e1eb8770439656.png)





## [](#ask)Ask

26 May 2025

You can now ask AI about any conversations or (customer) reviews that match a search criteria to better understand them without going through them one by one. Ask selects a large random sample of conversations that match the search criteria, and based on their content and/or reviews, it answers your questions, including references to examples that you can verify.

You can click on any example in the purple box to open a quick view of the entire context related to the example. This way, you can easily check for the root cause and find additional details.

![](https://media.notiondesk.so/upload/6a9ac7e4d6df6761864817.png)

## [](#links-to-coaching-sessions)Links to Coaching Sessions

22 May 2025

You can now copy link to a specific coaching session. This enables you to send agents and other stakeholders such as HR links to specific feedback the agent received. If the user has the required permissions the link shows them details of the coaching sessions. They can read the performance reviews and all comments performed during the session.





## [](#agents-profile-grouped-by-teams)Agents Profile Grouped by Teams

19 May 2025

Agents in the Agent Profile navigation are now grouped by teams. You can now easily see all agents in that team together so it is easy for team leaders to focus on their agents especially if they work in larger organization. The search also shows the team of the found agents.

![](https://media.notiondesk.so/upload/6a9ac7e75f091442884836.png)





## [](#markdown-in-review-comments)Markdown in Review Comments

14 May 2025

You now show content in review comments as markdown. This enables you to use simple formatting in comments to highlight important statements, better structure the comments and provide clickable links to training materials, guidelines and specific conversations and other content in Salted.

![](https://media.notiondesk.so/upload/6a9ac7e92cc9a471679593.png)





## [](#automatically-suggest-what-to-search-for-in-conversations)Automatically Suggest What to Search for in Conversations

7 May 2025

You can now in write a high level description of an issue that you want to search for in the conversations. Salted CX automatically creates possible different sub-issues, tries to search for them and if they actually appear in the conversations it adds it as a possible answer.

![](https://media.notiondesk.so/upload/6a9ac7eb26d73684330261.png)

## [](#from-semantic-search-to-discover)From Semantic Search to Discover

30 Apr 2025

When you use semantic search for finding anything that comes to your mind right away you can now smoothly transition to Discover screen to explore any issue in more detail and setup auto review of all conversations to continuously search for conversations with that issue. When you open Discover screen all your search criteria are transferred.

![](https://media.notiondesk.so/upload/6a9ac7ed0b98e639326232.png)

## [](#discover)Discover

23 Apr 2025

Discover screen enables you to explore conversations by their content on scale. You can use the screen to breakdown one issue into multiple sub-issues and search for conversations where the issue manifests itself. You can click on any found turn and open related conversation to understand the entire context and additional details.

Discover screen is a great starting point to create auto reviewers that look at all conversations and mark them if the issue is found in them. As with semantic search you can use all filtering criteria to narrow the search only to conversations you want to focus on.

![](https://media.notiondesk.so/upload/6a9ac7eee5e65469345611.png)

## [](#links-to-conversations-in-ask-about)Links to Conversations in Ask About

10 Apr 2025

When you use Ask about to understand what is happening in the conversations you will now get links that point to conversations that best represent topics mentioned in the answer. When you click on the finding customer journey opens in new browser window. This helps you to understand in great detail what exactly happened in the conversation.

![](https://media.notiondesk.so/upload/6a9ac7f19a39b319399181.png)

Links in semantic search help you to understand wider context related to found conversations. Links in agent profile help you to find specific examples of conversations you can use for coaching the agent.

When you copy the response from Ask the copied text contains hyperlinks back to Salted CX. In case you share the response with your colleagues they can click on the references and open the related conversations if they have permissions to view them.





## [](#dynamic-data-in-dashboard-text)Dynamic Data in Dashboard Text

3 Apr 2025

You can now reference metrics directly in the rich text areas in the dashboards. Dynamic data in text areas enables to show up to date metric values in plain text language that quickly communicates highlights in a natural easy to understand language.

![](https://media.notiondesk.so/upload/6a9ac7f3823aa885951649.png)





## [](#dashboards-and-visualizations-in-questions)Dashboards and Visualizations in Questions

2 Apr 2025

You can now add dashboards and visualizations to questions. This enables you to check reviews related to that question from every perspective relevant for you company. You can add any dashboard or visualization that contains the filter for question. The dashboard or visualization is automatically filtered to the currently open question.

![](https://media.notiondesk.so/upload/6a9ac7f5a8bef168109239.png)

You can use the dashboard to watch number of auto reviews, average customer score, check whether QM people provide enough feedback to agents, etc.

## [](#email-alerts-from-dashboards)Email Alerts from Dashboards

2 Apr 2025

Users can now setup email alerts to watch metrics in the dashboards. You can choose which metric you want to watch. If a visualization is segmented by attributes you can watch the total number or just a number for a subset of data.

For triggering the alert you can use comparison to static numbers or metric change compared to a previous time period. This enables you get email when your customer satisfaction drops below a required threshold, or when there is an unexpected spike in the volume of conversations.

![](https://media.notiondesk.so/upload/6a9ac7f7ab7b5542373342.png)

Learn more in [article on alerts](https://help.salted.cx/en/articles/dashboards-alerts).

## [](#filtering-of-reviews-in-agent-profile)Filtering of Reviews in Agent Profile

20 Mar 2025

Agent profile now has improved list of reviews that provides more information and enables you to filter by any column so you can focus on specific feedback the agents receive in their conversations.

![](https://media.notiondesk.so/upload/6a9ac7fa0f62b563776486.png)

## [](#acknowledge-and-dispute-reviews-in-agent-profile)Acknowledge and Dispute Reviews in Agent Profile

20 Mar 2025

You can now acknowledge and dispute reviews from the agent profile. This enables agents to provide feedback if a review is not correct or they do not believe it is fair. Acknowledging reviews can be part of the quality management process.

![](https://media.notiondesk.so/upload/6a9ac7fd1a62b525172527.png)

## [](#servicenow-incidents-ingest)ServiceNow Incidents Ingest

13 Mar 2025

![](https://www.notion.so/icons/warning_yellow.svg?mode=light)

This feature is in Preview and its behavior is likely to change based on user feedback. The feature also may have lower availability and have more maintenance windows.









We now support importing of ServiceNow incidents and conversations that are related to the incidents. As with any other data source ServiceNow data can be combined with data from other platforms.

See [ServiceNow integration](https://help.salted.cx/en/articles/integration-servicenow) for more details.

## [](#international-semantic-search)International Semantic Search

11 Mar 2025

Semantic search now works much better with non-English languages. You can search using any of the newly supported languages and get results from customer talking in any of the supported languages.

The list of currently supported languages in semantic search in alphabetical order:

Albanian, Arabic, Armenian, Bulgarian, Burmese, Catalan, Croatian, Czech, Danish, Dutch, English, Estonian, Finnish, French, Galician, Georgian, German, Greek, Gujarati, Hebrew, Hindi, Hungarian, Indonesian, Italian, Japanese, Korean, Kurdish, Latvian, Lithuanian, Macedonian, Malay, Marathi, Mongolian, Norwegian Bokmål, Persian, Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovenian, Spanish, Swedish, Thai, Turkish, Ukrainian, Urdu, Vietnamese

The returned results will differ depending on the language combination, how close the languages are and how much training data are available for the individual languages.

## [](#translation-of-customer-feedback)Translation of Customer Feedback

11 Mar 2025

We now translate customer comments you receive in customer satisfaction surveys to English. You can also see the customer comments in their original language in a tooltip.

## [](#better-rendering-of-visualizations)Better Rendering of Visualizations

6 Mar 2025

We have updated visualization rendering to make visualization easier to read and more appealing:

- Labels in charts have now more spacing around them making them easier to attribute to specific data points.

- Labels in charts are less likely rotated making them easier to read.

- Minimum and maximum values for chart axes now roundup to whole numbers when possible.

- Better alignment on zero value in dual axes charts.

## [](#service-data-set)Service Data Set

4 Mar 2025

Service data set enables you to associate conversations with a product or partner on behalf which you handle the customer conversations. There are several use cases for Services data set:

- Associate outbound sales conversations with offered products

- Attribute customer care conversations to specific products

- Attribute conversations to partners on whose behalf your contact center handles the conversations

The following table contains the newly added data set attributes:

| Property | Type | Description |
|---|---|---|
| Service | [PID](https://help.salted.cx/en/collections/1755206106-logical-model?v=24f5d3a2a8dc81f49249000c3e502787#2565d3a2a8dc8010b907f9c8aeac496e) | The service or a product that the conversation is related to. |
| Service ID | Label for Service | External ID for the service. |
| Service Name | Label for Service | Human readable name or the service. |
| Partner | [Entity](https://help.salted.cx/en/collections/1755206106-logical-model?v=24f5d3a2a8dc81f49249000c3e502787#2565d3a2a8dc8040887dfa7ea6952826) | Partner that is associated with the service or product. Partner enables you to group multiple services and products. |
| Partner Manager | Entity | The person who is currently responsible for managing the relationship with the partner for the given service or product. |
| Region | Entity | Geographical location of the service based on any segmentation used by the company. Ir might be a city for local operations or large region such as Europe, APAC for international operations. |
| Service Attribute 1 | Entity | Custom attribute associated with the service. |
| Service Attribute 2 | Entity | Custom attribute associated with the service. |
| Service Attribute 3 | Entity | Custom attribute associated with the service. |
| Service Status | Enumeration | The current service status enables to identify whether i |
| Vertical | Entity | The vertical in which the service or product is present. |







## [](#manually-isolate-contacts)Manually Isolate Contacts

25 Feb 2025

You can now see all the contacts associated with the current customer on top of the customer journey. You can use the menu to isolate individual contacts. Isolated contacts are not linked with other contacts to form customer journey. You can use this feature to prevent problematic contacts from external systems such as `no@email.com` , `555-123-4567` from connecting unrelated conversations.

We also detect such problematic contacts automatically if they lead to connecting too many unrelated conversations. In this case we isolate the contact automatically.

![](https://media.notiondesk.so/upload/6a9ac8017bfcd198965713.png)

## [](#list-contacts-mentioned-in-messages)List Contacts Mentioned in Messages

25 Feb 2025

If there is a contact such as phone or email mentioned in any conversation in the customer journey that is not yet associated with the customer we list these contacts in a separate section that enables you to view these contacts. You can use the menu to navigate to that contact information.

![](https://media.notiondesk.so/upload/6a9ac8035cc33856857043.png)

## [](#part-of-this-journey-indicator)Part of This Journey Indicator

25 Feb 2025

Even for contacts that are redacted to reduce exposure of protected personal information we show an indicator whether the contact is the part of the current journey (indicated by a full circle ●) or the contact is not part of the current customer journey (indicated by an empty circle ○).

![](https://media.notiondesk.so/upload/6a9ac804ef9ee604217572.png)

Customers may often mention phone numbers, emails and other contact information that is not their own. The indicator enables you to ensure these contacts are not associated with the current customer journey.

## [](#freshdesk-tickets)Freshdesk Tickets

20 Feb 2025

![](https://www.notion.so/icons/warning_yellow.svg?mode=light)

This feature is in Preview and its behavior is likely to change based on user feedback. The feature also may have lower availability and have more maintenance windows.









We now support importing Freshdesk tickets to Salted CX. As with any other data source ServiceNow data can be combined with data from other platforms.

See [Freshdesk Integration](https://help.salted.cx/en/articles/integration-freshdesk)

## [](#dashboards-and-visualizations-tabs-in-agent-profile)Dashboards and Visualizations Tabs in Agent Profile

17 Feb 2025

You can now add tabs with custom dashboards and visualizations directly into the agent profile. All dashboards and visualizations are automatically filtered to the current agent. You can change all other filters. You can also go to the dashboard or visualization editor straight from the agent profile.

![](https://media.notiondesk.so/upload/6a9ac806c78db538127908.png)

## [](#ask-about-engagements-and-turns)Ask about Engagements and Turns

10 Feb 2025

Ask about is now visible all the time in the customer journey enabling you to get more details about what is happening in the conversation right from the right panel without the need to open a dialog. You can also now quickly choose whether you want to ask about a specific turn/message or about an entire engagement.

![](https://media.notiondesk.so/upload/6a9ac8087f951718932746.png)

## [](#more-space-in-the-right-panel)More Space in the Right Panel

10 Feb 2025

Feedback, Reviews and Similar Turns are now separate tabs which saves a significant screen space. Depending on what you focus on you can now view more content that matters to you.

![](https://media.notiondesk.so/upload/6a9ac80a22067203368529.png)

## [](#exact-match-and-full-text-search)Exact Match and Full-Text Search

28 Jan 2025

You can now use exact match search (case insensitive) if you surround your searched term with quotes — for example `“Premium Package”`. This enables you to focus on very specific phrases mentioned in the conversation such as product names, company names, special codes, etc.

You can also use full-text search that is a bit broader than exact match but does not search for all the various expressions with similar semantic meaning. You can use tilde to use full-text search — for example `~”cancel”`.

You can combine exact match and full-text search and semantic search — for example `“Premium Package” not recognized by the travel agency`.

![](https://media.notiondesk.so/upload/6a9ac80ba9c67805594217.png)

## [](#recent-searches)Recent Searches

28 Jan 2025

We automatically save several recent searches automatically, so you can return to them later. When you focus the search field the recent searches automatically pop-up and are filtered as you type. The recent searches are also visible when you open an empty semantic search.

![](https://media.notiondesk.so/upload/6a9ac80ce3f2b108877880.png)

## [](#saved-searches)Saved Searches

28 Jan 2025

You can now save search criteria in semantic search so you can search again in the future by one click. Semantic search remembers all search criteria except date range as you can use semantic search only in the recent conversations.

![](https://media.notiondesk.so/upload/6a9ac80e66cc9780316144.png)

## [](#share-searches)Share Searches

28 Jan 2025

You can share mark searches as shared so other people in you company can use them as well. This enables you to quickly highlight to you colleagues what conversations they can focus on.

## [](#search-by-contacts)Search by Contacts

21 Jan 2025

You can now paste a phone number, email or any customer ID into semantic search and we will find the customer journey associated with the customer. The customer associated with the contact is shown above the search results from the conversation content.

![](https://media.notiondesk.so/upload/6a9ac80fc2343956838450.png)

## [](#search-by-permanent-identifiers)Search by Permanent Identifiers

21 Jan 2025

You can now use search to find different pieces of conversations in search. When you search for Salted CX permanent identifier (they look like this `f0f3c07e-edaa-46f7-afaf-4942fc47c971` ) the search results will show you a link to the moment in the customer journey related to item with the PID you search for.

Search by PID supports Customer, Contact, Conversation, Engagement, Turn, Review and Transactions.

![](https://media.notiondesk.so/upload/6a9ac8112fd21704206687.png)

## [](#transactions-in-customer-journey)Transactions in Customer Journey

14 Jan 2025

Transactions are now visible in the customer journey. Transactions enable you to see sales that an agent made during the conversation. You can also see refunds or compensations in case the agents take care of customer complains.

![](https://media.notiondesk.so/upload/6a9ac812928d9959738927.png)

You can use our Ingest API to load information about the transactions to Salted CX. You can also monitor performance related to transactions (volume, revenue, discounts, etc.) in dashboards and visualizations.

Transactions can also be used in dashboards and visualizations to measure the agents’ performance and identify who is a great sales person, who makes customers happy while not offering excessive compensation, etc.

## [](#generic-transaction-attributes)Generic Transaction Attributes

14 Jan 2025

Generic transaction attributes enable you to attach extra data to each transaction that are specific for your business. This enable you to filter and segment transactions by attributes that are not provided by us out of the box but are important for you. You can use this for example to identify high-risk transactions, transactions handled exceptionally, attribute transactions to a project, campaign, etc.

See [Transactions data set](https://help.salted.cx/en/articles/model-transaction).

## [](#accounts-ingest-from-salesforce)Accounts Ingest from Salesforce

6 Jan 2025

If a Salesforce contact is part of an account in Salesforce we now group customers into organizations so multiple people from the same company can be recognized.

## [](#salesforce-comments)Salesforce Comments

6 Jan 2025

Salesforce comments are now visible in our customer journey. The comments can you give more details about the conversations such as information that users share between themselves when handling a case within Salesforce. The extra context gives you extra visibility on how agents and other stakeholders collaborate to resolve the customer issues.

## [](#related-contacts-in-ingest-api)Related Contacts in Ingest API

3 Jan 2025

For each contact such as phone number, email or a customer ID you can now list multiple related contacts. This enables you to contribute to the customer profile and connect more conversations into the customer journey.

If you have a CRM or a customer address book you can import contact relationships to Salted CX. We can then use these relationships between the contacts to link the customer conversations into a single customer journey even when the source contact center platforms do not contain the relationship.

## [](#detailed-error-messages-in-ingest-api)Detailed Error Messages in Ingest API

3 Jan 2025

You will now get detailed error message when you try to upload data in unsupported data format. This helps you to get your integration working much faster.

## [](#highlighted-participants)Highlighted Participants

20 Dec 2024

We now highlight turns by participants by a more pronounced strip on the left side of the messages. This makes it easier to recognize participants on wider array of displays. The colors remain the same — customers are green, agents are blue, bots are purple and system messages are grey.

![](https://media.notiondesk.so/upload/6a9ac81509d92597415829.png)

## [](#permissions-set)Permissions Set

16 Dec 2024

We have now added new permission sets that contain permissions for the specific role so you do not have to list permissions individually.

| Permission Set | Description |
|---|---|
| AGENT\_ALL\_CONTENT | Agents with complete view of the data. This means that the agent has unrestricted visibility into metadata and content but actions they can perform are still limited. |
| ANALYST | Access to analytics tools that enable to explore both metadata and content. Users can create custom visualizations, dashboards and metrics. |
| AUTO\_QA\_MANAGER | Access to quality management including Auto AI features. |
| REVIEWER | Features for manual quality assurance. |
| TEAM\_LEADER\_QA | Access to tools that are useful for team leaders including ability to customize QA process - edit forms and questions. |
| TEAM\_LEADER | Access to tools that are useful for team leaders. |
| VIEW\_CONTENT | View content of the conversations — such as recordings, messages, email bodies, transcripts, etc. |
| VIEW\_METADATA | View conversation metadata. |
| VIEW\_PROTECTED | View all the data including the ability to unmask protected information such as phones and emails. |
| FULL\_ACCESS | All permissions EXCEPT experimental features. |



## [](#automatically-isolate-contact)Automatically Isolate Contact

9 Dec 2024

Customer profile now detects large clusters of contacts (phone number, emails, CRM customer IDs, etc.) that are linked to a single customer. This may happen for example when the customers or agents provide invalid or dummy contacts such as no@email.com, 555-55555, etc.

When there is a large cluster of such contacts we automatically detect contacts that are root causes for such clusters and isolate them so they do cause multiple people to look like one customer in Salted CX. You can still isolate contacts manually even when they do create large clusters directly form the customer journey.

![](https://media.notiondesk.so/upload/6a9ac816f354a973345307.png)

## [](#saved-views-in-dashboards)Saved Views in Dashboards

2 Dec 2024

You can now save the current filters in dashboards. Saved views enable you get back to the filtering criteria with just 2 clicks. You can name your saved views so it is easy to keep them organized.

Saved views are a great way to focus on individual agents, teams, queues, topics and any other subset of conversations. You can choose which saved view is default for you.

![](https://media.notiondesk.so/upload/6a9ac8187c697208738910.png)

## [](#smaller-visualizations-in-dashboards)Smaller Visualizations in Dashboards

2 Dec 2024

In dashboards you can make charts and tables smaller to fit more data into the dashboard. You can now to much more dense dashboards.

## [](#ask-about-semantic-search)Ask about Semantic Search

25 Nov 2024

You can now ask about results in semantic search. When you want to understand what is a common pattern in the search results. You can use ask about to get better understand the results overall or instead of reading them individually.

![](https://media.notiondesk.so/upload/6a9ac81a922bb805113326.png)

## [](#customer-profile)Customer Profile

21 Nov 2024

We now automatically connect conversations from multiple connected platform across different channels. We extract from each platform as many relationships between individual contact information as possible. These contact information can phone numbers, emails, handles on social networks, user IDs or any other identifier you use.

![](https://media.notiondesk.so/upload/6a9ac81cc47f9386314953.png)

Customer profile builds customer journeys that include complete customer experiences without artificial borders of the individual channels.

Customer Profile also supports our Ingest API. You can use Ingest API to load more relationships between contacts if you have them available. This enables to glue more conversations to customer journey they belong to.

## [](#customer-review-topics)Customer Review Topics

18 Nov 2024



Topics screen shows you automatically detected topics from customer satisfaction surveys. Topics enables you to uncover new issues mentioned by the customers. You can see how many times the topic appeared in the last 30 days to decide whether it is worth you attention.

![](https://media.notiondesk.so/upload/6a9ac81f37f7d302026873.png)

All new topics automatically land to No Category. You can then use the Topic screen to give topics your preferred name if the automatically generated can be better. You can also organize the new topics to categories that fit your business and can be addressed together.

You can use “Ignore” category for topics you are not interested to watch.

## [](#question-categories)Question Categories

11 Nov 2024

Question categories group questions into logical categories. Categories make the questions easier to navigate. You can also use question categories in visualizations and dashboards fro filtering or segmentation. For example you can have a category focused on agent performance, customer experience, etc. and you do not have to pick individual questions to show all metrics related to those areas.

## [](#ask-about-agent)Ask About Agent

4 Nov 2024

You can use ask about agent to ask questions about the conversations in which the agent was engaged. Ask about takes random sample of engagements and provides you with the answer that can be useful during coaching session and find you a conversations that you might want to check.

![](https://media.notiondesk.so/upload/6a9ac8219361c230913075.png)

## [](#ingest-api)Ingest API

23 Oct 2024

Ingest API opens the power of Salted CX to platforms and applications that are not natively supported by Salted CX. Ingest API enables to upload data that create or update any entity in our Logical Model. This enables to get the same set of features as any supported platform gets.

For example you can use Ingest API to:

- Load conversations from unsupported platforms

- Expand conversations to include IVR, Menus and other parts of conversation done outside of your primary platforms

- Add additional events that happened during the conversation, or actions agents or customer did

- Add transactions to conversations to be able to report on sales performance of agents

These are just examples. Please check our [Logical Model](https://help.salted.cx/en/collections/1755206106-logical-model) documentation to see all data you can create and enhance.

## [](#ask-about-engagement)Ask about Engagement

16 Oct 2024

If you have long engagements you can now use Ask About to give you more information about it. You can use Ask About to give you summary, check whether agent behaved as expected, whether there are unanswered customer questions, etc.

![](https://media.notiondesk.so/upload/6a9ac8241cbb9532558209.png)

## [](#visualization-switcher)Visualization Switcher

9 Oct 2024

You can now add Visualization Switcher to dashboards. Visualization switcher enables to fit multiple visualizations users can switch between into one slot. You can use Visualization Switcher to have alternative perspectives on the same issue, having different visualizations that focus on different important items.

![](https://media.notiondesk.so/upload/6a9ac826c9db0884950213.png)

## [](#redaction-of-protected-information-in-customer-journey)Redaction of Protected Information in Customer Journey

4 Oct 2024

We now redact protected information in the customer journey to reduce the users’ exposure to information that they do not need for their work but can contain personally identifiable information (PII) or similar information that may be misused or exfiltrated from your company.

Users with the given permission can reveal the individual pieces of protected information. To reveal the information users have to choose the reason for revealing the protected information. We log these individual requests for auditing purposes so it then possible to identify what data users viewed.

![](https://media.notiondesk.so/upload/6a9ac829ac1ca295876743.png)

[Learn more about protected information](https://help.salted.cx/en/articles/protected-information)

## [](#visualizations-screen)Visualizations Screen

15 Sep 2024

We have now a screen that is dedicated to viewing individual visualizations. The visualizations screen is now similar to dashboards screen. You can use left hand navigation to view all available visualizations and search for them.

Open visualizations fill the entire screen to take advantage of all the available space. This is especially useful for tables that show all the rows that fit on the screen.

![](https://media.notiondesk.so/upload/6a9ac82bb4443079579330.png)

## [](#automatic-drill-downs-from-visualizations)Automatic Drill Downs from Visualizations

15 Sep 2024

We now add automatic drill downs from attributes in visualization to customer journey, agent profile, questions and forms. Drill downs enable you to explore interesting data points much faster and get to root causes faster and get more context.

## [](#filter-by-metric)Filter by Metric

15 Sep 2024

If a visualization has a metric filter in its definition you can now adjust the filtering criteria when viewing the visualization. You do not need to edit the visualization to adjust the filters.

## [](#filter-top-bottom-items)Filter Top/Bottom Items

15 Sep 2024

If a visualization has a top/bottom filter in its definition you can now adjust the filtering criteria when viewing the visualization. You do not need to edit the visualization to adjust the filters.

## [](#share-links-to-visualizations)Share Links to Visualizations

15 Sep 2024

Visualizations now have their permanent link that you can use to share them with other users. This enables you to collaborate with co-workers when you discover something interesting without having to take screenshots, exporting the data or having to put your visualization into a dashboard.

## [](#export-option-in-user-interface-requires-permission)Export Option in User Interface Requires Permission

15 Sep 2024

Option to export data as Excel or CSV from the application user interface now requires a permission `reporting.export` . Keep in mind that the user has technically access to the data via the user interface and can copy the data from their browser. Users also have access to the data via API. So this permission does not prevent users to get data they already have access to.

## [](#engagement-summary)Engagement Summary

18 Sep 2024

Engagement summary now shows the agent and what channel they used to join the conversation. Additionally you can choose three additional properties to show for each engagement. You can choose any attribute or fact from our [Logical Model](https://help.salted.cx/en/collections/1755206106-logical-model).

![](https://media.notiondesk.so/upload/6a9ac82e8b7ae805445304.png)

## [](#original-platform-icon)Original Platform Icon

18 Sep 2024

Engagements now indicate with icon from which data source they are imported. Each platform supported out of the box has its own icon so you have immediate visibility on which platform the communication happened. When you click the icon Salted CX opens the engagement in the original platform as it did with the older icon.

![](https://media.notiondesk.so/upload/6a9ac8312a4d0209200952.png)

## [](#freshdesk-tickets-ingest)Freshdesk Tickets Ingest

2 Sep 2024



We now support tickets in Freshdesk and create agent engagements based on agent involvement in the tickets. This enables to have visibility into the volumes and effort involved in handling the customer and see the communication in the customer journey where you can use all Salted CX quality assurance and AI features.

[Learn more about all available integrations](https://help.salted.cx/en/collections/1755256026-integrations)

## [](#edit-coaching-in-progress)Edit Coaching in Progress

28 Aug 2024

You can now leave coaching sessions in progress and return to them later. As long as the coaching session is not completed the user who created the coaching session can edit it.

Learn more about coaching

## [](#used-form-in-reporting)Used Form in Reporting

28 Aug 2024

The [Review](https://help.salted.cx/en/articles/model-review) data set now has new entity Used Form that you can use for filtering and segmentation. Used Form entity represents what war a user used to provide the review. Used Form attribute is available for coaching sessions and also for reviews provided from the customer journey.

## [](#ask-about-engagement)Ask About Engagement

14 Aug 2024

Each engagement now has an option to ask Salted CX AI any question about it. This enables to quickly some up an engagement or answer some specific questions about what happened in the engagement.

![](https://media.notiondesk.so/upload/6a9ac833df7a6118618559.png)

You can choose whether you prefer a Concise or Detailed answer.

## [](#open-agent-profile-from-customer-journey)Open Agent Profile from Customer Journey

14 Aug 2024

Now when you click on any agent that was engaged in the conversation with the customer in customer journey you will go to the agent profile that gives you more information about the overall agent performance.

## [](#coaching-sessions-tracking)Coaching Sessions Tracking

12 Aug 2024

Agent profile tracks coaching sessions. When Team Leaders meet with agents for coaching and discuss performance they can now track outcome of these sessions — briefly sum up the agent performance and identify the next steps.

You can create custom forms to use duŕing coaching sessions to keep the coaching sessions structured and evolve them over time.

![](https://media.notiondesk.so/upload/6a9ac8362d5de296605556.png)

Learn more about coaching

## [](#rollups-in-tables)Rollups in Tables

8 Aug 2024

You can now Rollup aggregation method in tables. Rollup chooses an aggregation method based on the used metric. So if the original metric is an average then rollup is an average as well. If the original metric is a sum then the rollup is sum also. Thanks two this you can fit different aggregations into a single footer row.

Rollup also uses the underlying metric to calculate the value without the segmentation in the table which is more often the result you are looking for especially for averages. While the average metric calculates an average of individual rows in the table (average of averages) the rollup calculates the average of the underlying data which is typically what you want.

![](https://media.notiondesk.so/upload/6a9ac8385ea56740710245.png)

## [](#date-filter-in-semantic-search)Date Filter in Semantic Search

4 Aug 2024

You can now focus on findings in a specific date range. This is useful to check if there are specific days when a spike in a behavior happened or when a trend started to change. We also show a chart with number of findings in individual days. The chart gives you an idea whether the number of findings in trending in some direction or if there are any spikes.

![](https://media.notiondesk.so/upload/6a9ac83a7238c987270156.png)

## [](#exclude-findings-in-semantic-search)Exclude Findings in Semantic Search

4 Aug 2024

You can now look use phrases that you do not want to exclude from the search. You can also use multiple phrases to exclude so if your semantic search results contain turns you do not expect to see, you can incrementally filter them out.

## [](#highlighting-in-findings-semantic-search)Highlighting in Findings Semantic Search

4 Aug 2024

In case a message or a piece of transcript is longer, we now highlight the phrases that are the closest to what you search for. This helps to better understand why a result appeared in the search results.

## [](#listing-on-aws-marketplace)Listing on AWS Marketplace

30 Jul 2024

Salted CX is now listed at AWS Marketplace. Listing on AWS Marketplace enables customers using AWS to have Salted CX billing included in their other infrastructure costs. Customers can now create a new Salted CX account themselves.

[Go to Salted CX at AWS Marketplace](https://aws.amazon.com/marketplace/pp/prodview-wyzljwueduh54)

## [](#customer-summary)Customer Summary

18 Jul 2024

You can now choose three customer-related metrics and attributes you would like to see about the customer. The options include metrics on how much you have engaged with the customer in the past and also attributes from the [customer](https://help.salted.cx/en/articles/model-customer) data set.

You can click on any of the three fields and get a menu with the choices. The menu also shows you all values for the current customer. If you want just quickly check a value you can just peek into the menu without changing what the customer summary shows by default. Customer journey remembers the choices per user so each user can see what is the most important for them.

![](https://media.notiondesk.so/upload/6a9ac83bf3d2b634219923.png)

## [](#voice-calls-from-aircall)Voice Calls from Aircall

8 Jul 2024



We now import voice calls from Aircall. The voice calls are represented as conversations and engagements to reporting. The engagements are visible in the customer journey. You can click on an engagement to open the original call in Aircall.

## [](#agent-profile)Agent Profile

19 Jun 2024

The new tab Agents in Salted CX lists all currently active agents. You can use search to find agents you are interested in. Agent profile shows the agent name and key attributes related to the organization hierarchy.

If a user has a permission to see only their engagements they will see only their own agent profile and will not see the navigation that enables to go to other agents’ profiles.

## [](#reviews-in-agent-profile)Reviews in Agent Profile

19 Jun 2024

The first tab in the customer profile shows all reviews related to any engagement attributed to the agent. The reviews in the customer profile are loaded in real-time when you open the agent profile so you do not need to wait for 15-minute loads into reporting dashboards and visualizations.

Agents can use their agent profile to check what feedback they get. Agents can jump to customer journeys to check more context. They can also acknowledge and dispute feedback they have got.

![](https://media.notiondesk.so/upload/6a9ac83dd9669896546877.png)

## [](#amazon-connect-chats-in-customer-journey)Amazon Connect Chats in Customer Journey

17 Jun 2024

We now import chat transcripts and process individual chat messages with AI to create auto reviews that point you to conversations that may need your attention. As with other platforms, you can tag and review individual chat messages for manual quality assurance and use those examples to refine configured prompts and knowledge. They are not used to train or fine-tune the underlying AI models.

Salted CX supports Amazon Connect chats even without Amazon Lens enabled.

## [](#amazon-connect-call-transcripts-in-customer-journey)Amazon Connect Call Transcripts in Customer Journey

17 Jun 2024

We now import voice transcripts from Amazon Connect. You can now show individual times when the customer and agent talk as individual turns in the customer journey. This enables you to do any actions with the individual messages such as doing reviews. Salted CX also processes 100% of voice transcripts with AI to create auto reviews.

Amazon Lens must be enabled for call transcripts.

## [](#amazon-connect-sentiment-reporting)Amazon Connect Sentiment Reporting

17 Jun 2024

If Amazon Lens is enabled we now import sentiment when provided by Amazon. This enables you to see the sentiment in dashboards and customer journeys. You can easily find pieces of conversations in which customer expresses dissatisfaction. You can combine sentiment provided by Amazon with auto reviews that Salted CX provides.

## [](#support-for-flex-insights-attributes)Support for Flex Insights Attributes

14 Jun 2024



We now process Flex Insights attributes from Twilio TaskRouter tasks. This enables your users to take advantage of additional data that you have already provided to Twilio TaskRouter without any additional implementation effort.

## [](#single-choice-auto-reviewers)Single Choice Auto Reviewers

10 Jun 2024

Single-choice reviewers enable you to find opportunities and categorize them. This is useful for breaking out one issue or opportunity in conversations into multiple categories that represent a different flavor of the issue that you can address separately. As with every auto reviewer, provide a few representative examples to define and validate the configured review criterion.

![](https://media.notiondesk.so/upload/6a9ac8403184b993091037.png)

## [](#provide-training-input-for-single-choice-auto-reviewers)Provide Training Input for Single Choice Auto Reviewers

10 Jun 2024

You can provide feedback to auto reviewers whether the automatic reviews are correct and what is the correct answer. This enables to improve the [accuracy of auto reviews](https://help.salted.cx/en/articles/1755254757-auto-reviews-accuracy) over time.

![](https://media.notiondesk.so/upload/6a9ac8420f193377856526.png)

## [](#twilio-flex-support)Twilio Flex Support

7 Jun 2024



We import Twilio Flex (TaskRouter) tasks to build customer journeys of them. We organize the data into conversations in our [Logical Model](https://help.salted.cx/en/collections/1755206106-logical-model). The following types of engagements are created for the tasks:

- Agent Engagements — whenever an agent engages with the customer as part of their tasks. This enables reporting on performance metrics such as handling time, wrap-up time, the overall volume of handled conversations, etc.

- Queue Engagements — whenever a customer is waiting in a queue you can report on the wait time, the number of customers leaving before they connect with an agent, etc.

- Invitation Engagements — whenever an agent is invited to a conversation (in Twilio Flex a reservation is created) the invitation engagements enable you to find agents who reject or miss those invitations.

You can use Salted CX as a replacement for Flex Insights with all the additional features of Salted CX including automatic and agile manual quality assurance, content analytics, visualization in customer journey and all others.

## [](#twilio-messaging-transcripts)Twilio Messaging Transcripts

7 Jun 2024

We import chat transcripts from Twilio Messaging to our customer journey. The chat transcripts are shown as individual turns in the customer journey. You can do reviews for individual turns. The turns are also automatically reviewed by Salted CX AI to find conversations that need your attention.

## [](#twilio-flex-agent-activity)Twilio Flex Agent Activity

7 Jun 2024

We import data on agent status transitions so you can monitor whether agents spend their time in the available state and other metrics related to WFM.

## [](#zingtree-bulk-export-api-support)Zingtree Bulk Export API Support

3 Jun 2024



We now use newly introduced Zingtree bulk export API to retrieve session data from Zingtree. The new bulk export API enables to import larger volume than 6,000 per day limit and makes Zingtree usable for larger customers.

## [](#color-segmentation-in-scatter-charts)Color Segmentation in Scatter Charts

30 May 2024

You can now use an attribute to color different data points in scatter chats. The color is great for grouping individual items into clusters and see whether an issue is specific a single item or it is a common across multiple items. For example you can see whether one agent is an outlier in a performance or an entire team is affected.

![](https://media.notiondesk.so/upload/6a9ac84665f24049335323.png)

## [](#attribute-and-facts-organized-by-data-set)Attribute and Facts Organized by Data Set

30 May 2024

The attributes and facts are now organized by data set in the visualization editor. This makes it easier to find the items that you are looking for.

![](https://media.notiondesk.so/upload/6a9ac8480a239047173657.png)

## [](#repeater-visualization)Repeater Visualization

17 May 2024

The repeater visualization is a great way how to show multiple metrics for a list of items that provides a lot of information in a very compact form. If you want to have an overview of queues, teams or agents, repeater enables you to show multiple metrics for each and you chan choose to visualization for all of the metrics (overall number, bar chart and line chart). Thanks to this you can immediately see whether the key metrics are improving over time or not.

![](https://media.notiondesk.so/upload/6a9ac849ea24d030902922.png)

## [](#dependent-filters-in-dashboards)Dependent Filters in Dashboards

17 May 2024

You can now filter visible values in a dashboard filter by another filter on the dashboard. For example, you can use a team filter to narrow down the agents you can pick from in the agent filter.

![](https://media.notiondesk.so/upload/6a9ac84bc3f99602369798.png)

## [](#filter-available-values-in-dashboard-filters-by-metric)Filter Available Values in Dashboard Filters by Metric

17 May 2024

You can now filter visible values in a dashboard filter by a metric. If the metric has non-empty value for the given attribute value the value will be visible as an option. You can use this feature for example to show only agents that have some activity, show only outcomes that have some auto reviews, etc. Less values in filters make it easier to find those that a relevant for the given dashboard.

![](https://media.notiondesk.so/upload/6a9ac84d7ec66568686149.png)

## [](#rich-text-in-dashboards)Rich Text in Dashboards

17 May 2024

You can now add rich text widgets to dashboards to provide users with more information, highlight important sentences, and provide links to more business-related information or documentation. You can even include images in dashboards. One image can often be worth thousands of words.

![](https://media.notiondesk.so/upload/6a9ac84f608e6220705677.png)

Read more about the [rich text in dashboards](https://help.salted.cx/en/articles/dashboards-rich-text).

## [](#acknowledge-reviews)Acknowledge Reviews

24 April 2024

Agents and other people can now acknowledge reviews. This enables you to have a process that ensures that agents or team leaders on their behalf can acknowledge reviews from reviewers (team leaders, supervisors, and QA people), auto reviewers, and even customers. Acknowledging reviews helps to ensure your agents are in the loop of the quality assurance process and they are aware of feedback on their performance.

We have separate permissions that enable users to acknowledge auto reviews, manual reviews, and feedback from customers. The [permission](https://help.salted.cx/en/articles/permissions) also has a scope to be able to acknowledge any review or only reviews associated with engagements the agent handled.

![](https://media.notiondesk.so/upload/6a9ac851bcdf3961737127.png)

## [](#dispute-reviews)Dispute Reviews

24 April 2024

Agents and other people can now dispute reviews. This enables you to have a process that ensures that agents or team leaders on their behalf can dispute reviews from reviewers (team leaders, supervisors, and QA people), auto reviewers, and even customers. Disputing reviews is a great tool to ensure the review process is fair as agents have a strong incentive to dispute negative feedback whether given by people or auto reviewers. Disputed auto reviews also help to monitor and improve the [accuracy of auto reviewers](https://help.salted.cx/en/articles/1755254757-auto-reviews-accuracy).

We have separate permissions that enable users to dispute auto reviews, manual reviews, and feedback from customers. The [permission](https://help.salted.cx/en/articles/permissions) also has a scope to be able to dispute any review or only reviews associated with engagements the agent handled.

## [](#agent-permission-set)Agent Permission Set

24 April 2024

We now support [permission set](https://help.salted.cx/en/articles/permissions) specifically with permissions suitable for agents. The permission set contains permission an agent typically needs for their work. The permission set allows you to give agents multiple permissions without listing them individually. The permission set is managed by Salted CX and we add permissions to it when we add a new feature that agents typically should have access to. This unlocks agents more functionality over time without you having to update settings in your identity provider.

You can still use additional permissions in combination with the [agent permission set](https://help.salted.cx/en/articles/permissions) to give agents access to more features.

## [](#salesforce-integration-case-priority)Salesforce Integration — Case Priority

22 April 2024

We now extract the Priority field from Salesforce Cases and store them in the [Engagement](https://help.salted.cx/en/articles/model-engagement) ⏵ Priority attribute. You can use the Priority attribute to segment any metric. This may be useful if you have different criteria for handling customers based on priority. You can also use Priority to filter for high-priority items and focus on them.

## [](#salesforce-integration-case-record-type)Salesforce Integration — Case Record Type

22 April 2024

We now extract Case Record Type from Salesforce Cases and store them in the [Engagement](https://help.salted.cx/en/articles/model-engagement) ⏵ Category attribute. You can use the Category attribute to segment any metric. The Category attribute.

## [](#salesforce-integration-engagements-in-progress)Salesforce Integration — Engagements in Progress

22 April 2024

We now extract engagements that are in progress and attach turns to them. So when you have longer conversations you can already see what is going on in them even when they are not completed. The engagements that are in progress can be easily identified by the [Engagement](https://help.salted.cx/en/articles/model-engagement) ⏵ Engagement Status attribute.

## [](#salesforce-integration-mixing-omni-channel-with-other-engagements)Salesforce Integration — Mixing Omni-Channel with Other Engagements

22 April 2024

We now better attribute communication and time spent in engagements. You can use the [Engagement](https://help.salted.cx/en/articles/model-engagement) ⏵ Flow attribute to find out whether the Engagement was done using Salesforce Omni-Channel or other flows including Salesforce Tasks or ad-hoc emails.

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

We recommend using Salesforce Omni-Channel for as much communication as possible because it provides the best visibility into agents’ performance.





## [](#new-attributes-and-facts-in-logical-model)New Attributes and Facts in Logical Model

18 April 2024

We have added new attributes and facts to our logical model. New attributes provide more dimensions for data segmentation and more options for filtering. We intend to use the newly added attributes and facts to enhance our existing and future integrations and bring more granular data to Salted CX.

The following table lists all added facts and attributes.

| Data Set | Attribute or Fact | Type | Description |
|---|---|---|---|
| [Activity](https://help.salted.cx/en/articles/model-activity) | Scheduled Time | Fact | The time the agent was supposed to be in the given activity. |
| [Agent](https://help.salted.cx/en/articles/model-agent) | Manager | Entity | The agent’s current manager. |
| [Agent](https://help.salted.cx/en/articles/model-agent) | Role | Entity | The agent role serves to classify the current role of that agent and enables them to split into groups with specific common features like Rookies, Veterans, etc. |
| [Engagement](https://help.salted.cx/en/articles/model-engagement) | Outcome Type | Enumeration | The high-level type of the outcome enables us to categorize outcomes to known values that can be reported on. |
| [Engagement](https://help.salted.cx/en/articles/model-engagement) | Category | Entity | The high-level category of the engagement. Use of this attribute is typically customer-specific. |
| [Engagement](https://help.salted.cx/en/articles/model-engagement) | Engaged Location | Entity | The location of the agent in the time of the engagement. |
| [Engagement](https://help.salted.cx/en/articles/model-engagement) | Engaged Organization | Entity | The organization in which the agent was in the time of the engagement. |
| [Engagement](https://help.salted.cx/en/articles/model-engagement) | Engaged Role | Entity | The role in which the customer was during their engagement. |
| [Engagement](https://help.salted.cx/en/articles/model-engagement) | Engagement Attribute 1 | Entity | General purpose attribute that can be used for storing data that are account specific. |
| [Engagement](https://help.salted.cx/en/articles/model-engagement) | Engagement Attribute 2 | Entity | General purpose attribute that can be used for storing data that are account specific. |
| [Engagement](https://help.salted.cx/en/articles/model-engagement) | Engagement Attribute 3 | Entity | General purpose attribute that can be used for storing data that are account specific. |
| [Engagement](https://help.salted.cx/en/articles/model-engagement) | Flow | Entity | The flow through which the conversation went. Flow is typically a process that leads to handling of the engagement. It can be a simple direct call or a very complex flow handling a customer based on business-specific preferences. |
| [Engagement](https://help.salted.cx/en/articles/model-engagement) | Priority | Entity | The priority of the engagement categorized into discreet buckets such as High, Normal, Low. |
| [Engagement](https://help.salted.cx/en/articles/model-engagement) | Engagement Fact 1 | Fact | General purpose fact that can be used for storing data that are account specific. |
| [Engagement](https://help.salted.cx/en/articles/model-engagement) | Engagement Fact 2 | Fact | General purpose fact that can be used for storing data that are account specific. |
| [Engagement](https://help.salted.cx/en/articles/model-engagement) | Engagement Fact 3 | Fact | General purpose fact that can be used for storing data that are account specific. |
| [Review](https://help.salted.cx/en/articles/model-review) | Confidence Level | Enumeration | The confidence level of an auto review that categorizes them based to different levels. Each level has a different ratio of true positives and false possessives. This enables to focus to focus on [high precision or high recall use cases](https://help.salted.cx/en/articles/1755254757-auto-reviews-accuracy). |
| [Review](https://help.salted.cx/en/articles/model-review) | Verified | Enumeration | The indicator whether the review is correct, incorrect or eventually acknowledged and disputed by agents. |
| [Review](https://help.salted.cx/en/articles/model-review) | Version | Attribute | The version of the reviewer used for this review. This attribute is used for Auto reviews to compare different models. |



## [](#create-auto-reviewers)Create Auto Reviewers

15 April 2024

For each question that is the type of tag, you can now create a so-called Auto Reviewer. Auto Reviewer is an AI-powered service that automatically checks 100% of conversations to find patterns in them. Each pattern an Auto Reviewer finds is then visible in the reporting and the customer journey.

Thanks to Auto Reviewers you can get quantitative data on the pattern occurrence in 100% of the conversations. You can report on the number of total auto reviews or the number of conversations containing them (deduplicating multiple findings in one conversation). You can filter by any attribute to focus on auto reviews in specific engagements only or segment the auto reviews by any attribute as well.

## [](#selecting-review-examples)Selecting Review Examples

15 April 2024

Auto Reviewers need clear examples of the pattern they should identify. We introduced the ability to select which manual reviews are used as examples when refining and validating an Auto Reviewer's configured prompts and knowledge.

Existing manual reviews can provide a useful starting point. Reviewers should still check that each selected example matches the intended criterion. These examples are not used to train or fine-tune the underlying AI models.

## [](#agent-access-to-engagements)Agent Access to Engagements

10 April 2024

We now have granular permissions that enable you to restrict the visibility of data in reporting and the [customer journey](https://help.salted.cx/en/collections/1755250527-customer-journey) to engagements that the agent handled. Engagements and dependent items such as reviews that are not associated with the agent will not be included in the reports and not be visible in the customer journey.

Learn more about agent access in the [permissions article](https://help.salted.cx/en/articles/permissions).

## [](#agent-reviews)Agent Reviews

10 April 2024

As agents can now have access to Salted CX you can enable them to review engagements they have handled. Each review provided by an agent has the attribute [Review](https://help.salted.cx/en/articles/model-review) ⏵ Review Type equal to Agent. You can use the Review Type attribute to easily distinguish reviews that an agent provided for their engagements.

## [](#mark-auto-reviews-as-correct-or-incorrect)Mark Auto Reviews as Correct or Incorrect

25 Mar 2024

You can now mark auto reviews as Correct, Incorrect, and Unclear to give feedback on Salted CX auto reviews. This feedback helps identify where the configured prompts, knowledge, or evaluation criteria should be refined. Correct and Incorrect examples can also be used to evaluate future auto-review quality and reduce [false positives](https://help.salted.cx/en/articles/1755254757-auto-reviews-accuracy).

Users need dedicated permission to provide this feedback. Customer reviews and feedback are not used to train or fine-tune the underlying AI models.

![](https://media.notiondesk.so/upload/6a9ac85493a06987415461.png)

## [](#similar-turns)Similar Turns

18 Mar 2024

Now whenever you click any turn (for example a chat message) in our customer journey we show you similar turns based on our semantic search engine. This enables you to jump directly to similar situations to the one you have found. Similar turns use actual content of the conversation and its meaning to determine what is close.

You do not have to guess or know all the different ways customers express themselves to find more examples of any situation in your conversations. The similar turns that you have already visited are less empathized and any turn that received some feedback is marked with circles that indicate it in their bottom right corner. So you know what is the next best turn to explore.

![](https://media.notiondesk.so/upload/6a9ac856e8810928412279.png)

Remember you can use tags to mark any interesting piece of conversation you find. So you can return to it later, show it in dashboards and let the auto reviewers search 100% of conversations to find similar situations in them.

## [](#cross-filtering-dashboards)Cross-filtering Dashboards

12 Feb 2024

Dashboards now enable you to click on any attribute in any chart to filter the entire dashboard to that attribute. Cross-filtering enables really fast data exploration without spending time to set up drill-downs manually for every attribute. Cross-filtering is enabled by default for every dashboard.

![](https://media.notiondesk.so/upload/6a9ac858b24f4709239664.png)

Learn more about [filtering dashboards](https://help.salted.cx/en/articles/dashboards-custom#8a3f76e545a247f29fa65253286de644).

## [](#multiple-date-filters-to-dashboards)Multiple Date Filters to Dashboards

12 Feb 2024

You can now use multiple date filters on a single dashboard. When you use multiple filters the filtering criteria are included on both date dimensions at the same time. You can use this for example to list reviews of any agent engagement in the past 30 days that a reviewer did yesterday.

![](https://media.notiondesk.so/upload/6a9ac85aaea8e002347796.png)

Learn more about [filtering dashboards](https://help.salted.cx/en/articles/dashboards-custom#8a3f76e545a247f29fa65253286de644).

## [](#pass-filters-in-url-on-drill-down)Pass Filters in URL on Drill-Down

8 Feb 2024

When creating custom dashboards that drill down to your applications — for example, to see an agent employee card, more information about the customer, etc., you can now include currently applied filters in the dashboard in the URL. This enables the destination web application to apply the same filters that users had applied in Salted CX. This enables you to show more relevant content on the destination web page on drill down.

![](https://media.notiondesk.so/upload/6a9ac85c60815224108374.png)

Learn more about [drill-downs from dashboards](https://help.salted.cx/en/articles/dashboards-drill-down).

## [](#drill-down-hierarchy-in-dashboards)Drill-Down Hierarchy in Dashboards

5 Feb 2024

Dashboards now enable simple setup of drill downs based on natural hierarchies or granularity such as drilling from years to months to days to hours. Drilling can also copy organization hierarchy and other structures in customer conversations.

![](https://media.notiondesk.so/upload/6a9ac85e557db175710130.png)

You can also define your drill-down paths that copy natural hierarchies in your company.

Learn more about drill-downs in [Custom Dashboards](https://help.salted.cx/en/articles/dashboards-custom)

## [](#dependent-filters-in-dashboards)Dependent Filters in Dashboards

5 Feb 2024

Items available in filters can now be filtered by other filters using dependent filters. You can use one filter to limit options in another filter. For example, when you have a team selected only agents from that team are shown in the dependent filter.

![](https://media.notiondesk.so/upload/6a9ac8605cc79500726373.png)

Learn more in [Custom Dashboards](https://help.salted.cx/en/articles/dashboards-custom)

## [](#reset-filters)Reset Filters

5 Feb 2024

Quickly return filters to their default state on the dashboard. You do not have to go through all the filters and manually choose the values. You can now just click the reset button and all filters are set to default values.

![](https://media.notiondesk.so/upload/6a9ac86186973300258167.png)

Learn more about [filters in dashboards](https://help.salted.cx/en/articles/dashboards-custom).

## [](#salesforce-integration-customer-satisfaction-surveys)Salesforce Integration — Customer Satisfaction Surveys

1 Feb 2024

Salted CX now supports customer surveys that you send to your contacts. Salted CX attributes the survey results to an engagement that precedes the survey results. You can now find conversations where customers are not happy really easily. They might help you discover more opportunities for improvement.

![](https://media.notiondesk.so/upload/6a9ac863698fb546283185.png)

Learn more about [Salesforce data in Salted CX](https://help.salted.cx/en/articles/integration-salesforce).

## [](#salesforce-integration-agent-activity)Salesforce Integration — Agent Activity

1 Feb 2024

You can now report on agent activity (also called agent status or aux codes). This enables you to understand whether your agents are available to engage with your customers and unlocks a wide range of metrics focused on efficiency and managing agent workload.

Learn more about [Salesforce data in Salted CX](https://help.salted.cx/en/articles/integration-salesforce).

## [](#salesforce-integration-task-based-engagements)Salesforce Integration — Task-based Engagements

29 Jan 2024

Salted CX now imports Salesforce Tasks that are related to communication as engagements. Tasks carry fewer metrics and attributes compared to Omni-Channel AgentWork but they still make the customer journey complete.

The new engagements are visible in the [customer journey](https://help.salted.cx/en/collections/1755250527-customer-journey) along with the Salesforce Omni-Channel engagements. Check [Salesforce Data in Salted CX](https://help.salted.cx/en/articles/integration-salesforce) for details on how Salesforce objects are translated into the Salted CX [logical model](https://help.salted.cx/en/collections/1755206106-logical-model).

## [](#salesforce-integration-ad-hoc-email-engagements)Salesforce Integration — Ad-hoc Email Engagements

29 Jan 2024

Customer Journey now includes emails that are sent directly from the Case screen without an associated task or Salesforce Omni-Channel AgentWork. These individual email messages now each produce a single engagement.

## [](#zingtree-integration)Zingtree Integration

22 Jan 2024



You can now connect Zingtree to Salted CX. ZingTree enables building menus customers use for self-service on your website. This enables you to deflect significant traffic away from human agents.

Zingtree integration enables you to:

- See customers using self-service and their success rate in resolving the issues.

- Segment volume by the path the customers go through in Zingtree.

- Measure the time the customer spends in Zingtree.

- Understand how many customers and in what cases they need to be connected to human agents.

Learn more about [Zingtree integration](https://help.salted.cx/en/articles/integration-zingtree).

## [](#salesforce-integration-omni-channel-agent-work)Salesforce Integration — Omni-Channel Agent Work

15 Jan 2023

Salted CX now extracts data from Salesforce. Currently, only agent engagements handled in Salesforce Omni-Channel are imported. As with other data sources Salted CX transforms Salesforce data into our Logical Model and all conversations can be combined with conversations from other platforms. You can also connect multiple Salesforce instances to a single Salted CX account.

Salted CX imports metadata related to Salesforce Omni-Channel AgentWork which contains the most granular information about agents’ performance including handling time, wait time and other metrics.

Learn more about [Salesforce data in Salted CX](https://help.salted.cx/en/articles/integration-salesforce).

## [](#timezone-and-first-day-of-the-week)Timezone and First Day of the Week

12 Dec 2023

You can now choose the timezone and the first day of the week on account and user level. On the user level, you can choose to keep the account setting or use your own. Timezone and the first day of the week impact how data are segmented in reporting and how dates and times are shown all over the application including [Customer Journey](https://help.salted.cx/en/collections/1755250527-customer-journey).

![](https://media.notiondesk.so/upload/6a9ac8656527d296156437.png)

## [](#date-and-time-format)Date and Time Format

12 Dec 2023

You can also choose a date and time format for both the account and user level. You can also choose to use account settings. Available formats are Chinese, Czech, Dutch, English — GB, English — US, French, German, Japanese, Portuguese — Brazil, Portuguese — Portugal, Russian, and Spanish.

For more information on account and user settings check Application Settings.

## [](#visited-turns-in-semantic-search)Visited Turns in Semantic Search

4 Dec 2023

Recently visited turns in [Semantic Search](https://help.salted.cx/en/collections/1755269222-search-and-discover) are now less saturated than other turns so you can easily distinguish turns you have reviewed recently. This helps you to focus on discovering new similar behaviors.

![](https://media.notiondesk.so/upload/6a9ac86743aba551162029.png)

## [](#hide-recently-visited-turns)Hide Recently Visited Turns

4 Dec 2023

Use the check box in [Semantic Search](https://help.salted.cx/en/collections/1755269222-search-and-discover) to hide all recently visited turns. This helps you to see only turns that you are yet to explore. Hiding visited turns is very useful when you have a lot of findings to go through and you do not want to go back to those you have already reviewed.

![](https://media.notiondesk.so/upload/6a9ac868d8c1a409503759.png)

## [](#customer-journey-peek)Customer Journey Peek

4 Dec 2023

When you now click on an Engagement, Conversation, or Customer the customer journey opens as an overlay on the currently open dashboard without navigating away. You can quickly skim through a lot more conversations. When you find something that needs a deeper look of feedback you can open [Customer Journey](https://help.salted.cx/en/collections/1755250527-customer-journey) with all of its features.

You can now hold Ctrl on Windows or Command on Mac to open the customer journey in a new browser window or tab.

We have also significantly improved the performance of loading individual customer journeys so they open almost instantaneously.

## [](#free-text-questions-in-reviews)Free Text Questions in Reviews

4 Dec 2023

You can now use free text questions in reviews. This enables you to keep qualitative feedback associated with engagements or individual turns. The form designed to provide feedback to agents uses free text questions. You can use them to tell agents in greater detail what are their opportunities for improvement and encourage them to keep doing a great job.

![](https://media.notiondesk.so/upload/6a9ac86a9910b195683046.png)

## [](#locked-and-hidden-filters)Locked and Hidden Filters

4 Dec 2023

When editing dashboards you can now make filters locked or hidden. This option influences how dashboard filters look when viewing a dashboard. Locked filters are visible in the dashboard but viewers cannot change them. Hidden filters are invisible but criteria in them are applied to the dashboard.

![](https://media.notiondesk.so/upload/6a9ac86c40079053350755.png)

## [](#amazon-connect-integration)Amazon Connect Integration

20 Nov 2023

Salted CX now takes conversation metadata from Amazon Connect and enables it to show them side by side with metadata from other supported platforms. As with any other platform, Salted CX translates all the Amazon Connect data into our unified easy to use [Logical Model](https://help.salted.cx/en/collections/1755206106-logical-model).

You get visibility into key KPIs across all connected platforms. You can show KPIs based on traffic from Amazon Connect and other platforms seamlessly in one chart, table, or even in a single number. Or you can filter specifically just for conversations coming from Amazon Connect.

As with any other integration, you can have multiple Amazon Connect instances in one Salted CX account alongside other connected platforms to that account.

With the Amazon Connect Integration, you will get the benefits of the Salted CX features including:

- Access to data on conversations and agent activity

- Out-of-the-box dashboards on top of key contact center KPIs

- Building custom dashboards, charts, tables, and metrics

- Drill down from dashboards to [Customer Journey](https://help.salted.cx/en/collections/1755250527-customer-journey) showing all conversations with a single customer in one pane

- Navigate to any call or chat in Amazon Connect from the Customer Journey

- Use annotation and feedback tools for Agile QA in Customer Journey to collect feedback for agents and collect input for process improvements

As this feature is in Beta we continue working on Amazon Connect integration improvements to provide more granularity in reporting for additional scenarios that may happen in Amazon Connect.

## [](#highlighted-engagements-and-turns-that-have-a-review)Highlighted Engagements and Turns that Have a Review

9 Nov 2023

Each engagement or turn that is reviewed now has 4 circles indicating what types of reviews it received. A full circle indicates there is at least one completed review of the given type.

- Purple – Auto review provided by AI

- Green – Review from a customer

- Blue – Review from the agent

- Azure – Review from a reviewer

The engagements with reviews are also highlighted in the customer journey summary.

![](https://media.notiondesk.so/upload/6a9ac86ea4384132680057.png)

## [](#see-reviews-in-customer-journey)See Reviews in Customer Journey

9 Nov 2023

[Customer Journey](https://help.salted.cx/en/collections/1755250527-customer-journey) now shows all reviews associated with an engagement or a turn. This includes reviews from customers, AI, agents themselves, and reviewers.

Every engagement and turn can have many reviews associated with them. All of them are shown in the Review results.

![](https://media.notiondesk.so/upload/6a9ac870af858322228548.png)

## [](#choose-review-form)Choose Review Form

9 Nov 2023

You can now choose what form you will use for providing feedback and reviews to engagements and turns. Salted CX remembers the last form you selected for engagements and individual types of turns — customer, agent, and bot.

![](https://media.notiondesk.so/upload/6a9ac872b2266082578250.png)

## [](#built-in-review-forms)Built-in Review Forms

9 Nov 2023

Salted CX now contains a set of built-in forms that enable you to start with agile quality assurance right after logging into Salted CX for the first time. You can now start browsing conversations and mark anything useful in them with zero setup.

The forms are available in the menu [Customer Journey](https://help.salted.cx/en/collections/1755250527-customer-journey).

## [](#larger-pivot-tables)Larger Pivot Tables

2 Nov 2023

Pivot tables are useful for analyzing larger volumes of data and some users hit the limits of pivot table visualization. So the following limits are now higher.

- Number of column attributes: Remains 20

- Number of row attributes: Increased to 50 (previously 20)

- Number of metrics: Increased to 100 (previously 20)

## [](#semantic-search)Semantic Search

20 Oct 2023

Semantic Search is a new way to discover what customers and agents talk about in their conversations. Semantic Search searches in conversations in the last 7 days for anything you can think of. Unlike full-text search, the sentence you are looking for does not have to share any single word with the actual findings. Salted CX uses AI to find turns in conversations that have similar meaning to your search even when customers or agents use different wording that you are not aware of.

When you find turns that are similar to your search you can click on them and jump to the customer journey with that turn. This helps you to better understand the context and find more turns like the one you have clicked.

![](https://media.notiondesk.so/upload/6a9ac8740d3e8503145857.png)

Check [Semantic Search](https://help.salted.cx/en/collections/1755269222-search-and-discover) for more information.

## [](#drill-downs-to-agent-and-queue-dashboards)Drill Downs to Agent and Queue Dashboards

19 Oct 2023

The built-in dashboards now contain drill-downs to the agent dashboard when they show data for agents. This enables you to quickly jump to a 360-degree look at an agent's performance. This gives you one place to check on how an agent is doing.

Drill-downs also lead to dashboards showing individual queues, channels, and outcomes to give you detailed information about them. Essentially any item that is bold in dashboards takes you further and enables you to explore those in depth.

![](https://media.notiondesk.so/upload/6a9ac8759caef914110537.png)List of engagements with an option to click on individual agents, queues, and channels to drill into their dashboards

## [](#headline-insight-customization)Headline Insight Customization

19 Oct 2023

The headline insight has now more options to customize the comparison between the primary and secondary value. You can customize how the difference value is calculated, whether to show an arrow pointing up or down depending on the trend. You can also choose color and label depending on whether the primary value, is greater, lower, or the same as the secondary value. This enables you to communicate whether the change is trending in a positive or negative direction.

![](https://media.notiondesk.so/upload/6a9ac8771de80190139398.png)Options available in the headline insights editor

## [](#headlines-trends-in-built-in-dashboards)Headlines Trends in Built-in Dashboards

19 Oct 2023

The built-in dashboards take advantage of the customization options in headline insights and show comparisons of the key metrics with the previous period. By default, the KPIs compare the last 30 days with the previous 30 days. However, the comparison respects the dashboard filters so you can pick different timeframes and then the headlines compare the metric with that of the previous time frame.

![](https://media.notiondesk.so/upload/6a9ac8786a527014503395.png)How changes in headlines are visualized in dashboards

## [](#transposing-pivot-tables)Transposing Pivot Tables

16 Oct 2023

You can now transpose tables — switch rows for columns. You can show metrics on individual rows rather than columns. Transposing a table is useful when you have a low of metrics but very few possible values as scrolling vertically are in many cases more convenient.

Transposed table also enables to list of lot of metrics in a very compact space.

## [](#column-and-row-totals-in-pivot-tables)Column and Row Totals in Pivot Tables

16 Oct 2023

We have expanded the functionality of table totals. You can now use aggregate functions for both columns or rows, i.e., both totals (showing the total sum of the whole column or row) and sub-totals (showing aggregates within individual attributes). For example, you can generate a column that shows the total sum of the values of individual rows.

## [](#pyramid-charts-and-funnel-charts)Pyramid Charts and Funnel Charts

16 Oct 2023

You can use Pyramid and Funnel Charts to show conversation rates from one stage to another. You can put multiple metrics that you want to show in the chart or choose an attribute to segment into individual segments in the charts.

![](https://media.notiondesk.so/upload/6a9ac87a06aed011469823.png)

## [](#waterfall-chart)Waterfall Chart

16 Oct 2023

You can now build waterfall charts to see how individual numbers contribute to a total value. You can either use individual metrics or a single metric segmented by an attribute.

![](https://media.notiondesk.so/upload/6a9ac87bd531c409399517.png)

## [](#dependency-wheel)Dependency Wheel

16 Oct 2023

The dependency wheel shows state transitions.

![](https://media.notiondesk.so/upload/6a9ac87da47af773371066.png)Example dependency wheel insight showing engagements in individual queues and outcomes they produce

## [](#sankey-diagram)Sankey Diagram

16 Oct 2023

Sankey diagram shows the same data as the dependency wheel. It is more useful for situations when the values in from and to buckets are different.

![](https://media.notiondesk.so/upload/6a9ac87fee8d8238777272.png)Example sankey diagram insight showing engagements in individual queues and outcomes they produce

## [](#drill-down-to-turns-and-reviews)Drill down to Turns and Reviews

26 Sep 2023

You can now set up dashboards to drill to a turn or an engagement that was reviewed. This enables you to jump directly to the place within the [Customer Journey](https://help.salted.cx/en/collections/1755250527-customer-journey) that received any feedback from AI, customers, or people in your contact center. This is very useful when conversations and engagements in the customer journey are longer.

You can now jump directly to the spot where the customer sentiment changed, where the agent stopped following the company policy, and to many other interesting spots in the conversation.

## [](#highlight-the-current-position-in-the-customer-journey)Highlight the Current Position in the Customer Journey

26 Sep 2023

Customer Journey now highlights the conversations in the summary where you scrolled in the detailed conversations pane. You can now better see the context of the conversation, what preceded it, and what followed.

![](https://media.notiondesk.so/upload/6a9ac881605d8785178882.png)

## [](#scroll-to-selection)Scroll to Selection

26 Sep 2023

When you select an engagement or a turn and scroll away in the customer journey you can press a button to scroll back to selection. Now you can explore all the conversations without spending a few valuable moments to get back to where you were.

![](https://media.notiondesk.so/upload/6a9ac8826bbc4406601464.png)

## [](#searchlight-highlighting-long-response-times)Searchlight Highlighting Long Response Times

12 Sep 2023

Searchlight now highlights every turn that has a long response time and also shows a number of such turns in the summary.

## [](#open-conversations-in-their-source-platform)Open Conversations in Their Source Platform

12 Sep 2023

You can now open conversations in their source platform from [Customer Journey](https://help.salted.cx/en/collections/1755250527-customer-journey). Engagements from Zendesk and Salesforce now have links that enable you to open them in the source platform. This is useful when you want to do any actions based on what you find in the customer journey or explore related information only available in the source platform.

![](https://media.notiondesk.so/upload/6a9ac8838358b980636703.png)

## [](#parallel-conversations)Parallel Conversations

12 Sep 2023

Our [Customer Journey](https://help.salted.cx/en/collections/1755250527-customer-journey) keeps all exchanges in a conversation together sorted by time so you can understand the customer experience and the natural flow of the conversation. In case another conversation with the customer starts while the customer is still engaged in the original conversation Customer Journey now shows that this is the case and gives you a link to jump to the beginning of the conversation.

This happens for example when a customer sends an email message regarding another topic while still engaged in a chat.

## [](#agent-names-in-customer-journey-overview)Agent Names in Customer Journey Overview

12 Sep 2023

In case an engagement is not assigned to a queue [Customer Journey](https://help.salted.cx/en/collections/1755250527-customer-journey) now shows the name of the agent who handled the engagement. This helps to better visualize direct and outbound conversations.

## [](#engagements-and-turns-tagging)Engagements and Turns Tagging

31 Aug 2023

You can now tag engagements and individual turns in [Customer Journey](https://help.salted.cx/en/collections/1755250527-customer-journey). Use tags to provide feedback on potential improvements that can be made.

Tagging engagements and turns is our first step towards agile quality management.

## [](#drill-down-from-attributes)Drill Down from Attributes

24 Aug 2023

In Dashboards you can now set up drill down from attributes. Previously only metrics could be used for drill downs. Drill downs from attributes enable you to have more options to look at the data from different perspectives. You can click on an Agent in a report to have an Agent score card or you can click on a queue in the same report to view statistics for that queue.

![](https://media.notiondesk.so/upload/6a9ac8858e2a2274998993.png)

## [](#option-to-allow-one-value-in-filters)Option to Allow One Value in Filters

24 Aug 2023

You can now restrict a filter to allow users to pick only a single value in dashboards. This is useful for building agent scorecards, dashboards focused on a single queue performance and similar dashboards.

![](https://media.notiondesk.so/upload/6a9ac8870e2fd853196489.png)

Learn more in [Custom Dashboards](https://help.salted.cx/en/articles/dashboards-custom)

## [](#continuous-lines-and-areas-in-charts)Continuous Lines and Areas in Charts

24 Aug 2023

You can choose to connect line and area chats even when there are missing values between data points. When you have sparse data this helps you to better understand relationships and trends.

![](https://media.notiondesk.so/upload/6a9ac888c7ff0699155593.png)

Learn more in [Insights](https://help.salted.cx/en/articles/visualizations-custom)

## [](#rename-dashboard-filters)Rename Dashboard Filters

24 Aug 2023

You can now rename filters on dashboards. If you use a different vocabulary from ours or you want to communicate a specific meaning of a filter in a dashboard you can rename it.

![](https://media.notiondesk.so/upload/6a9ac88a42a4e770308061.png)

Learn more in [Custom Dashboards](https://help.salted.cx/en/articles/dashboards-custom)

## [](#eu-region)EU Region

17 Aug 2023

Salted CX infrastructure is now available in EU — Ireland. When you have an account in the Salted CX EU Region your data in our infrastructure does not leave the region. All storage and all processing happens within the EU.

![](https://media.notiondesk.so/upload/6a9ac88b2c785377798662.png)

## [](#zendesk-integration)Zendesk Integration

19 Jun 2023

![](https://www.notion.so/icons/warning_yellow.svg?mode=light)

This feature is in Preview and its behavior is likely to change based on user feedback. The feature also may have lower availability and have more maintenance windows.









![](https://media.notiondesk.so/upload/6a9ac88cdbf58086226700.png)

The integration with Zendesk extracts these data from Zendesk:

- Email tickets and chats including individual messages transformed into [conversations](https://help.salted.cx/en/articles/model-customer-journey-structure#532baca81c6f443fa52373c897de1b36), [engagements](https://help.salted.cx/en/articles/model-customer-journey-structure#283fad16f29244278bcf15dfa3ae58a4), and [turns](https://help.salted.cx/en/articles/model-customer-journey-structure#9daf09f040f44ca48d216cfb8df65ee4)

- Customer satisfaction transformed into [Reviews](https://help.salted.cx/en/articles/model-review)

The following features are available for Zendesk integration:

- Built-in dashboard showing engagement volume and customer satisfaction

- A user interface to create custom dashboards, insights, and metrics

- Drill down from dashboards to individual Zendesk tickets to view the conversation content

- Data is updated every 15 minutes

## [](#single-sign-on)Single Sign On

19 Jun 2023

Salted CX supports single sign-on with identity providers that support either SAML or OIDC including but not limited to [Okta](https://help.salted.cx/en/articles/identity-provider-okta) and [Google](https://help.salted.cx/en/articles/identity-provider-google). Salted CX requires customers to use an identity provider for all users to align authentication in Salted CX with the company policy. All users are managed by our customers centrally in their identity provider.

Single Sign On currently supports:

- SAML authentication using an external identity provider.

- OIDC authentication using an external identity provider.

- Setting permissions for individual users by custom user attributes in an identity provider.

![](https://media.notiondesk.so/upload/6a9ac88e785fe802384786.png)

---

## Setup Integration with ElevenLabs

Source: https://help.salted.cx/en/articles/1781863332-setup-integration-with-elevenlabs


Article short description

This setup guides you through the integration of your voice bot in ElevenLabs with Salted CX so your voice agent can handle inbound calls and escalate them to a human agent if it does not know how to handle the conversation.

This guide assumes you already have a voice agent created in ElevenLabs.

## [](#setup-webhooks)Setup Webhooks

This section enables ElevenLabs to inform Salted CX about calls it handled.

1. Go to Settings in the navigation on the left h[ttps://elevenlabs.io/app/agents/settings](https://elevenlabs.io/app/agents/settings)

![](https://media.notiondesk.so/upload/6a58821b19ee5679265869.png)

1. Scroll to Post-Call Webhook section

2. Press Select Webhook button

![](https://media.notiondesk.so/upload/6a58821e13b3e642028013.png)

1. Into the Enter a valid display name for the webhook field enter the Salted CX endpoint

![](https://media.notiondesk.so/upload/6a588220ecf37336374028.png)

1. Into Enter a valid callback URL field enter `https://api.eu.salted.cx/api/v1/live/webhooks/elevenlabs/post-call`

2. Press Create button

3. Click Copy to Clipboard to copy the value from Webhook Secret field

![](https://media.notiondesk.so/upload/6a588223b31b5285540231.png)

1. Share the copied token securely with Salted CX (using OnePassword or other tools of your choice)

## [](#setup-authentication)Setup Authentication

Authentication ensures that Salted CX accepts only calls from your ElevenLabs bot and nobody else can control your conversations in Salted CX.

1. In Settings scroll to Auth Connections section

2. Press Add Auth button

3. Press Bearer Token menu item

![](https://media.notiondesk.so/upload/6a5882268e99b261522452.png)

1. Enter Salted CX EU as Name (or use name of your choice)

![](https://media.notiondesk.so/upload/6a58822952141948930689.png)

1. In Auth Type select Bearer Token

2. Enter Salted CX as Provider (or use name of your choice)

3. Paste the token you received from Salted CX to Token field

![](https://media.notiondesk.so/upload/6a58822c06e34060238745.png)

1. Press Create auth connection button

2. Make sure Transcript, Audio, and Call Initiation Failures are checked

![](https://media.notiondesk.so/upload/6a58822ec7011110500677.png)

## [](#import-phone-number)Import Phone Number

This settings makes sure that we can forward the phone call to ElevenLabs.

1. Go to Phone Number from the navigation on the left <https://elevenlabs.io/app/agents/phone-numbers>

![](https://media.notiondesk.so/upload/6a5882317d64f806307402.png)

1. Press the Import number button

![](https://media.notiondesk.so/upload/6a58823419495952270157.png)

1. Click From SIM Trunk menu item

2. Into the Label field fill in your name for the phone number. For example `Customer Support Europe`

3. Into the Phone number filed fill the international format of the phone number without spaces, dashes and brackets. The phone number should look like `+1234567890`

4. In the SIP Trunk Username fill a value provided by Salted CX. Ask the Salted CX team if you do not have it.

![](https://media.notiondesk.so/upload/6a588237247b2881531989.png)

1. In the SIP Trunk Password field fill the password provided by Salted CX. Ask the Salted CX team if you do not have it.

2. In the Agent section click on the menu showing No agent value

![](https://media.notiondesk.so/upload/6a58823a639d5491885387.png)

1. Choose your voice agent from the menu

2. Optionally choose branch from which to take the agent.

![](https://media.notiondesk.so/upload/6a58823d7367c592398171.png)

Now you have a SIP phone number connected to your agent, so inbound calls are routed to that agent.

## [](#enable-escalations)Enable Escalations

This setup creates a tool that can be used by

1. Go to Tools from the navigation on the left <https://elevenlabs.io/app/agents/tools>

![](https://media.notiondesk.so/upload/6a5882406b5af526270929.png)

1. Click Add webhook tool button

2. Into the Name field fill a self-describing name such as `escalate_to_human_agent`

![](https://media.notiondesk.so/upload/6a58824323397148963608.png)

1. Into Description field describe under which circumstances the tools should be used by the agent. For example:

```json
Transfer the call to a human agent. Use when the customer asks for a human, when you cannot resolve their question, or when the conversation requires capabilities you don't have (booking, refund, account changes, etc.). Always tell the customer you'll connect them to a person.

Always escalate when rebooking or making changes to a trip that is coming in less than 7 days.
```

1. In Method menu select POST value

2. In the URL field fill the value `https://api.eu.salted.cx/api/v1/live/webhooks/elevenlabs/escalate`

3. In Authentication menu pick the authentication you have created previously

![](https://media.notiondesk.so/upload/6a588245b3baa727062460.png)

1. In Body parameters section ⏵ Properties add `conversation_pid`

![](https://media.notiondesk.so/upload/6a5882486e7ff023607296.png)

1. Into description fill whatever you want for example `ID of the conversation`

2. Set Data type to String

3. Into Identifier field fill `conversation_pid` value

4. Make sure Required is check

5. Set Value Type to Dynamic Value

6. Into Variable Name field fill `sip_conversation_pid`

7. Press Add tool button

![](https://media.notiondesk.so/upload/6a58824b457f5790975060.png)

Now you have an escalation tool that your voice agent can use to forward the calls to the agents.

## [](#route-escalations-to-specific-agents-optional)Route Escalations to Specific Agents (Optional)

By default an escalated call goes to the shared Needs Help queue, where any available agent can pick it up. The escalate tool also accepts optional body parameters that control which human agent receives the call. Add any of them in the Body parameters ⏵ Properties section of the escalate tool, the same way you added `conversation_pid` (but leave Required unchecked).

| Identifier | Data type | Description |
|---|---|---|
| `target_agent_pid` | String | Salted CX ID (UUID) of the specific agent who should receive the call. |
| `agent_selection_strategy` | String | `Best Available` — Salted CX picks the least busy available agent. Any other value is ignored. |
| `timeout` | Number | Seconds the invited agent has to accept the call. Default `30`. Values outside 1–900 are clamped to that range. |
| `on_timeout` | String | `All` (default) — after the timeout the call goes to the shared Needs Help queue. `Next Agent` — the strategy picks another agent. |



How the agent is selected, first match wins:

1. If `target_agent_pid` is set, that agent is invited.

2. Otherwise, if `agent_selection_strategy` is `Best Available`, Salted CX selects the least busy available agent.

3. If neither is set, no agent matches, or the invited agent does not accept in time (with `on_timeout` = `All`), the call goes to the shared Needs Help queue.

The caller stays on hold with music the whole time. Invalid values never block the escalation — they are ignored and the call falls back to the Needs Help queue behavior.

For each parameter you can choose how the value is provided:

1. Constant — set a fixed value, for example `agent_selection_strategy` = `Best Available` if every escalation should use strategy-based routing.

2. LLM Prompt — describe when and how the model should fill the value, for example for `target_agent_pid`: `The UUID of the requested agent, only if the customer asked for a specific person; otherwise omit.` Any values the model may use (such as agent UUIDs) must be provided to it, for example via dynamic variables or the system prompt.

## [](#add-escalation-tool-to-the-agent)Add Escalation Tool to the Agent

In this section, we will link the escalation tool so your voice agent can forward customers to its human colleagues.

1. In the navigation on the left slick on the voice agent you want to use for your agent

![](https://media.notiondesk.so/upload/6a58824e4a36a918676615.png)

1. Press Add tool button

2. Press the tool you have created in the previous section. The name we have used in this guide is `escalate_to_human_agent`

![](https://media.notiondesk.so/upload/6a58825106e80919583702.png)

Congratulations. Your ElevenLabs setup should now be complete. Try calling your phone number to check if everything works as expected.

---

## Dates and Times

Source: https://help.salted.cx/en/articles/model-dates


Data sets in [Logical Model](https://help.salted.cx/en/collections/1755206106-logical-model) reference several different time attributes. Every time attribute has one-minute granularity, unlike metrics that have second-level precision.

| Date and Time | Description and Usage |
|---|---|
| Conversation Start Time | The time when the entire conversation started. The conversation started time is the same for every engagement related to that conversation. A conversation start time is available for all engagements that are part of a conversation. |
| End Time | The time when the engagement ended including the wrap-up phase if the wrap-up happened after the engagement with the customer. If the engagement is still in progress the end time is not available for that engagement. |
| Interval Time | The time into which an agent activity is attributed. |
| Review Time | The time when a review was completed - the answer was provided. |
| Start Time | Time when an engagement started. Every engagement that we report on has a start time. The exact meaning of Start Time depends on [Engagement Type](https://help.salted.cx/en/articles/model-engagement#6990f6b859e04786b4c6a67fa2216008). For Agent Engagements the start time represents the time when an agent started to be occupied by handling the customer which is either the time when agent and customer connected or the time when agent started to prepare for the engagement. |



## [](#segment-by-date-and-time)Segment by Date and Time

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

All reporting is done in an account-wide timezone. For changing the time zone for your account, please contact us.





You can use date and times to segment data in insights to show metric values for all the individual time frames. All date and times are in the calendar year.

![](https://media.notiondesk.so/upload/698d90e6dc9c8558774278.png)

These segmentation options are possible, sorted from the longest time periods to the most granular:

- Year

- Quarter

- Month

- Week

- Day

- Hour

- Minute

Click More options to see additional options:

- Quarter of Year

- Month of Year

- Week of Year

- Day of Week

- Day of Month

- Day of Year

- Hour of Day

- Minute of Hour

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

You can use the the same level of segmentation when creating custom metrics.

*Tags: Logical Model*


---

## Acknowledge and Dispute Reviews

Source: https://help.salted.cx/en/articles/1755230871-acknowledge-and-dispute-reviews


Users in Salted CX can provide feedback to individual reviews. Users can acknowledge and dispute reviews of any type whether it is provided by a Reviewer, Customer or a automatically using auto reviews.

Users can acknowledge and dispute reviews in [customer journey](https://help.salted.cx/en/collections/1755250527-customer-journey) or in the agent profile by clicking on the review.

![](https://media.notiondesk.so/upload/698d91276f6df550691737.png)Option to acknowledge and dispute reviews in the customer journey

## [](#acknowledging-reviews)Acknowledging Reviews

The most common use for acknowledging reviews it to make sure the agent received the feedback and the agent team leader supervisor has a confirmation:

- Acknowledging reviewers’ feedback helps to explicitly confirm that agent is aware of the feedback and can learn from it.

- Acknowledging auto feedback helps to ensure AI provides accurate feedback that is aligned with the human perspective.

- Acknowledging customer feedback helps to reinforce agents’ understanding of the customer.

## [](#disputing-reviews)Disputing Reviews

Disputing reviews is a great way to uncover misalignment, unfairness or different expectations from people.

- Dispute reviewers’ feedback helps to ensure fairness and detect possible misalignment between the agent and team leaders and supervisors on the expectations. You should resolve every disputed review by talking to both agent and the reviewer.

- Disputing an auto review helps identify where the configured prompts or knowledge should be refined to improve future auto reviews. It does not train or fine-tune the underlying AI models.

- Dispute customer reviews enables agent to highlight cases when the customer is not really fairly representing the situation. You can use this feedback to exclude these customer surveys from scoring or discuss with agents in case the agent perception is not accurate.

## [](#auto-review-verification)Auto Review Verification

The options Correct, Unclear and Incorrect take precedence over acknowledging and disputing reviews. If one of these options is selected the user that does not have the permissions `review.auto.verify` cannot override them.

## [](#permissions)Permissions

There are granular permissions that enable users to review and/or dispute specific types of reviews. Permissions enable you to give users the exact permissions that are necessary to follow your quality assurance process.

| Permission |  |  |
|---|---|---|
| review.agent.acknowledge | Acknowledge agent reviews. | `*` |
| review.agent.dispute | Dispute agent reviews. | `*` |
| review.auto.acknowledge | Acknowledge auto reviews. | `*` — acknowledge any auto review `ME` — acknowledge only auto reviews of engagements that are associated with and turn (of any type) related to those engagements |
| review.auto.dispute | Dispute auto reviews. | `*` — dispute any auto review `ME` — dispute only auto reviews of engagements that are associated with and turn (of any type) related to those engagements |
| review.customer.acknowledge | Acknowledge customer reviews. | `*` — acknowledge any customer review `ME` — acknowledge only customer reviews of engagements that are associated with and turn (of any type) related to those engagements |
| review.customer.dispute | Dispute customer reviews. | `*` — dispute any customer review `ME` — dispute only customer reviews of engagements that are associated with and turn (of any type) related to those engagements |
| review.review | Review engagements and turns by answering questions, providing tags and answers to questions. | `*` — review any engagement or turn `ME` — review only engagements that are associated with and turn (of any type) related to those engagements |
| review.reviewer.acknowledge | Acknowledge manual reviews. | `*` — acknowledge any manual review done by a reviewer `ME` — acknowledge only manual reviews of engagements that are associated with and turn (of any type) related to those engagements |
| review.reviewer.dispute | Dispute manual reviews. | `*` — dispute any manual review done by a reviewer `ME` — dispute only manual reviews of engagements that are associated with and turn (of any type) related to those engagements |

---

## Conversation Urgency

Source: https://help.salted.cx/en/articles/1765376502-conversation-urgency


Article short description

Conversation Urgency is a number that indicates how important it is to handle the conversation relative to other conversations. Urgency is used to sort conversations in the Needs Help section of the Live Conversations navigation.

The Urgency is a hint, and Live Conversations and the exact behavior may differ in the future to maximize agent productivity and improve customer experience.

The current sort order in Needs help is as follows:

- First conversations are sorted by urgency from the highest to the lowest, with conversations that have no urgency set at the bottom.

- All conversations with the same urgency are sorted from the longest waiting to the shortest waiting.

## [](#how-to-manage-urgency)How to Manage Urgency

You can set the urgency in two contact points:

- When embedding Universal Chat. This enables you to set the initial urgency for the conversation.

- Update the value from Your Logic. You can update urgency using Conversation Update action send from Your Logic. You can change the value over the course of the conversation based on your business criteria.

## [](#factors-for-urgency-computation)Factors for Urgency Computation

Salted CX leaves it up to you how you calculate the conversation urgency or whether you use urgency at all. Here are a few factors you can consider:

- Channel. In each channel the customer may have different expectation on how soon they will get a reply. You typically want to handle web chats first as customers may leave the page, messaging apps such as WhatsApp second as there is no risk of the customer leaving the page and mails last as the expectation for response times are typically lower.

- Reason for contact. You can have a menu, automatic reason detection or other mechanisms that tell you what type of request does the customer have. You might categorize these reasons and put reasons that require timely resolutions first — for example if a customer is in the airport and they have issue with the departure there is a time constrain for the resolution.

- Severity. The actual or perceived severity of the customer issue. For example customers asking for a refund may be sorted from the highest requested refund value to the lowest.

- Customer business value. You might want to handle the most important customers first. You can decide based on the total business value the customer generated in the past, potential future generated value, etc. For example customers who need help to unblock purchasing high value product or a service might get a urgency.

- Sentiment, mentions of legal action, asks for escalations to managers. You can use the content of conversations to decide for urgency based on the customer frustrations, requests for supervisors/managers, mentions of threats, etc.

- Customer reputation. You might use customer reputation to deprioritize customers that take significant amount of your agents time to talk about low-value requests. If the customer has a really bad reputation (fraud attempts, frequent unjustified request) you can even decide not to ever let them talk to the agent and force completing the conversations with them.

- Repeated contact. Repeated contact may indicate unresolved ongoing requests and may lead to customer frustration and you might want to prioritize conversations that were re-opened by the customer.

The decision on which factors to use and what weight to assign to each is entirely up to you. You are not limited to the options above. You can also use different strategies for calculations.

## [](#urgency-tiers)Urgency Tiers

One strategy for calculating urgency is to put conversations into tiers, then let Salted CX sort them within each tier by how long the customer waits. This is typically very easy to understand and leaves most of the granular prioritization to the waiting time.

A typical example is channel-based tiers:

| Channel | Urgency |
|---|---|
| Web Chat | 3 |
| WhatsApp | 2 |
| Email | 1 |



The tiers can be multi-level:

| Channel | Reason | Urgency |
|---|---|---|
| Web Chat | Legal | 33 (30 + 3) |
| Web Chat | Departure Issue | 32 (30 + 2) |
| Web Chat | Other | 31 (30 + 1) |
| WhatsApp | Legal | 23 (20 + 3) |
| WhatsApp | Departure Issue | 22 (20 + 2) |
| WhatsApp | Other | 21 (20 + 1) |
| Email | Legal | 13 (10 + 3) |
| Email | Departure Issue | 12 (10 + 2) |
| Email | Other | 11 (10 + 1) |



In this example, the Channel has urgency over Reason. We multiply the Channel urgency by a value greater than the highest urgency a Reason has to ensure that lower-urgency channels do not overflow into higher-urgency channels. You can use more levels if needed, using the same principle.

## [](#weighted-urgency)Weighted Urgency

You can choose to manage urgency entirely based on the weight of individual factors that contribute to it. This enables very granular control, but you have to be careful not to produce unexpected orders. It also allows a high-urgency email to be above a low-urgency chat.

First, you decide the weight for individual factors:

| Factor | Weight |
|---|---|
| Channel | 5 |
| Reason | 3 |
| Severity | 2 |
| Customer Business Value | 2 |



Then you assign urgency to the individual values in a given factor:

| Factor | Value | Urgency |
|---|---|---|
| Channel | Web Chat | 3 |
| Channel | WhatsApp | 2 |
| Channel | Email | 1 |
| Reason | Legal | 5 |
| Reason | Departure Issue | 4 |
| Reason | Other | 2 |
| Severity | High | 3 |
| Severity | Normal | 2 |
| Severity | Low | 1 |
| Customer | VIP | 10 |
| Customer | Normal | 3 |
| Customer | Low Value | 1 |



The final urgency is then a weighted sum of those values. For example: WhatsApp Channel, Legal Reason, High Severity for a Low Value Customer would be calculated as `(Channel Weight x WhatsApp Urgency) + (Reason Weight x Legal Urgency) + (Severity Weight x High Urgency) + (Customer Business Value x Low Value Urgency)` = `(5 x 2) + (3 x 5) + (2 x 3) + (2 x 1)`.

## [](#tiers-with-weighted-urgency)Tiers with Weighted Urgency

This is a combination of the previous two methods. You can strictly separate urgency into tiers based on certain factors, and then assign a weight within each tier. This makes ordering more predictable at a high level and maintains detailed control at the lower level.

This is useful when you want to guarantee clear segmentation on the high level (eliminating one disadvantage of the Weighed Urgency).

*Tags: Live Conversations, Your Logic*


---

## Silent Messages

Source: https://help.salted.cx/en/articles/1771513081-silent-messages


Article short description

Salted CX detects messages that are silent (greetings, thank you) at the end of the conversation. This prevents unnecessary reopening the conversation.

## [](#your-logic)Your Logic

Your Logic still receives every message, even when they are silent. Every turn and trigger contains flag that indicates whether the message is silent. Your Logic can respond in any way you want. You can use `silent` attribute to quickly decide whether and how to respond to such messages.

```java
{
	"trigger": {
		"type": "MESSAGE",
		"silent": true 
	},
	
	"turns": [
		{
			"type": "MESSAGE",
			"silent": true
		}
	]
}
```

Silent messages have however the following behavior:

- When Your Logic is not available the conversation is not marked as ask for help

- When Your Logic encounters an error the conversation is not marked for help

## [](#live-conversations)Live Conversations

In Live Conversations the silent messages have the following impact:

- Agents are not notified by sound

- Agents are not notified in the browser tab

- The indicator that shows there is something new in the conversation is smaller

---

## Involving Agents in Quality Assurance

Source: https://help.salted.cx/en/articles/qa-agent-review


Agents are one of the possible sources of human feedback for customer conversations. The advantage of agents is they collectively handle 100% of conversations so if any issue arises. For this single reason encouraging agents to provide meaningful feedback helps improve operations.

Salted CX distinguishes these sources of human feedback:

- Agents. Any feedback agents provide for their engagements. Although there is a strong incentive for agents to provide feedback strongly biased in their favor there are great ways to extract value as agents handle 100% of conversations that are not self-service only.

- Customers. Customers provide feedback roughly for 10% to 20% of conversations. This sample is large enough to provide statistically significant feedback. Customer feedback is also essential to make sure your quality process is aligned with the customer's perception. Ideally, there should be a correlation between scores from agents, reviewers, and customers.

- Team Leaders, Supervisors, and QA people. Other people in your contact center provide feedback that makes sure the agents maintain a certain level of quality and the processes and tools well support the agents to achieve their performance. In most environments, contact centers can provide these reviews for around 1% of conversations.

You can use the attribute [Review](https://help.salted.cx/en/articles/model-review) ⏵ Review Type in reporting to distinguish between the source of the review.





## [](#why-involve-agents)Why Involve Agents

Involving agents in your quality assurance process provides an additional source of human perspective and may help uncover or quantify more issues and opportunities.

The reasons to involve agents:

- You align agents with the quality metrics you watch. When agents see their results and can respond to them they are reminded what quality metrics are watched, what behavior is encouraged, and what behavior is discouraged.

- Human coverage for a high percentage of conversations. As agents handle 100% of conversations that are not self-service they are in the best position to capture anything worth noting. That is not the case for manual reviews with around 1% coverage or customer reviews with 10% to 20% coverage. Agents can raise issues they experience via a standardized tool and process.

- A feedback loop that encourages fairness. AI-powered auto reviews and manual reviews are not always accurate. The ability of agents to acknowledge or dispute them helps reviewers validate findings and identify where the configured prompts, evaluation instructions, or knowledge should be refined. This feedback does not train or fine-tune AI models.

There are also good reasons why not to involve agents in the quality assurance process, minimize the time they spend doing it, or pause the process in some cases.

Reasons not to involve agents in the quality process:

- Agents spend time when involved in the quality process. Every second that the agent does not spend handling the customers does not directly contribute to performance. You may want to use only agent time when you have an extra capacity relative to the number of conversations.

- Your quality assurance process is in an early phase. Make sure you have a well-defined what exactly you want from agents and be very specific about what you want from them before asking them to do additional work.

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

When asking agents to perform additional tasks and activities always make sure their performance is not negatively impacted. Test any changes on the subset of agents (one team) and compare their key performance metrics such as customer satisfaction, number of handled engagements, engagement time, etc. with their performance before introducing the changes.





## [](#how-agents-can-be-involved)How Agents Can Be Involved

You have several options on how to involve agents in quality assurance. You need to manage the balance between agents’ depth of involvement and thus the time they spend with it with the value you extract by involving agents in the process.

### [](#acknowledge-and-dispute-reviews)Acknowledge and Dispute Reviews

You can ask agents to acknowledge or dispute reviews on their engagements.

Acknowledging reviews by agents helps you:

- Make sure that agents have a good understanding of expectations and they gradually build a better understanding of what you and your customers require from them.

- Ensure that agents are aware of any feedback they receive in case you.

### [](#comment-on-customer-perspective)Comment on Customer Perspective

You can ask agents to guess how would the customer rate them. For engagements that also have the customer score, you can then report on differences between the agent estimate and the actual customer score. Looking at these differences can help you find multiple potential issues such as agent empathy with the customers, different customer expectations from your agents’ or company expectations, etc.

The advantage of letting agents estimate customer satisfaction is that you will get an estimate of customer satisfaction for cases in which the customer has not responded to the survey. This helps you to increase the coverage. To ensure this estimate is accurate you have to ensure that the agents are aligned with the customer's perspective on the engagements that have an actual customer review.

### [](#let-agents-mark-issues-out-of-their-control)Let Agents Mark Issues Out of their Control

Many factors are out of agents’ control while still influencing customer satisfaction and agent performance. Agents have an incentive to identify those as resolving them can make their lives easier and have a positive influence on their overall performance.

Examples of issues you can ask agents to mark:

- Issues with the business process or policy. Agents feel that their processes (including scripts)or policies hurt their performance or prevent them from resolving customer issues.

- Issues with agent tools. Agents feel their agent desktop, other applications, and tools may prevent agents from resolving customer requests or slowing them down. Marking such cases may help to quantify these issues and help with their prioritization.

- Issues with customers. While your goal is to serve your customers there might be cases when the customer behavior is not acceptable and you want to protect your business and agents from abuse. Agents can mark these instances so these issues are addressed later.

### [](#let-agents-mark-issues-in-their-control)Let Agents Mark Issues In their Control

It may sound counter-intuitive to ask agents to let their management know that they have done something wrong. With a proper incentive structure for that behavior, it is possible though.

Examples of issues you can ask agents to mark:

- “I did not know what to do.” — Helpful for coaching or improving training materials.

- “I did not understand what the customer wanted.” — Helpful for having a closer look at what customers want and an opportunity to reach back to the customer.

- “I made a mistake.” — You encourage agents to be honest about cases when they feel they have not done a great job. One incentive that you can use is to guarantee that self-reported issues will not be held against them. For example, conversations that have a self-reported problem will not be included in quality scores.

---

## Auto Reviews Accuracy

Source: https://help.salted.cx/en/articles/1755254757-auto-reviews-accuracy


Auto reviews as any other AI feature have a certain level of accuracy. The accuracy is different based on the specific use case and it is influenced by how clearly it is possible to identify the issue from the conversation content.

Salted CX includes features that let you review auto findings and provide feedback. This feedback helps identify where the configured prompts, evaluation instructions, or knowledge should be refined; it does not train or fine-tune AI models.

## [](#metrics-for-auto-reviews-accuracy)Metrics for Auto Reviews Accuracy

The below image shows the meaning of individual metrics that we use to evaluate the accuracy of our auto reviews. These metrics enable you to understand what trade-offs you can make when using AI for discovering and monitoring issues in conversations.

![](https://media.notiondesk.so/upload/689de2477bddf669769915.png)

| Value | Description |
|---|---|
| True Positives | Correct Auto Reviews — Occurrences in engagements that were correctly found by the Auto Reviewer. |
| False Negatives | Occurrences in engagements that were NOT found by the Auto Reviewer. |
| False Positives | Incorrect Auto Reviews — Auto reviews that are INCORRECTLY created when there is no occurrence. |
| True Negatives | Engagements that do not have the occurrence and are not marked by auto reviews. |
| Precision | Formula: `(True Positives) / ((True Positives) + (False Positives))`Tells what percentage of all auto reviews is correct. 100% precision means that every single auto review is correct. 0% precision would mean that all auto reviews are incorrect. For comparison, the precision of manual reviews depends on the calibration of individual people and who is the final arbiter of truth. You can measure the precision of manual reviews during calibration sessions by choosing a reference person (arbiter) and comparing other people’s reviews with that person. You can expect 80% or higher precision for manual reviews. |
| Recall | Formula: `(True Positives) / ((True Positives) + (False Negatives))`Tells what percentage of all the actual occurrences in conversations are reported in auto reviews. 100% recall means that all occurrences in conversations have an auto review. 0% recall means that there is no auto review even though there are actual occurrences in the conversations. For comparison, recall for manual reviews when working on quality assurance based on random samples is typically around 1%. This is given simply by the fact that manual reviews are performed on a very low number of conversations compared to the overall volume. |



## [](#balancing-precision-and-recall)Balancing Precision and Recall

No AI we are aware of are able to find all occurrences (have 100% recall) without falsely identifying (having 100% precision) something as an occurrence if it does not match the expected criteria. You will often balance precision and recall depending on the use case.

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

Note that even people are generally unable to achieve 100% recall with 100% precision. This is due to border cases when it is hard to tell for some people. So if you let two people look at the same conversations they are likely to disagree in some cases with each other. People typically use calibrations to lower number of such cases. However even well calibrated people do not agree on every single case. 





![](https://media.notiondesk.so/upload/689de24b7a393007101543.png)Difference between findings when focusing on high precision and focusing on high recall, manual reviews shown for reference

Balancing between high precision and recall depends on the use case. In Salted CX you can use the metric Confidence of individual auto reviews to decide what you want to include in your visualizations and dashboards. In most cases you will want visualizations and dashboards to be somewhere between high precision and high recall.

### [](#high-precision)High Precision

When focusing on the high precision you will get results that contain low number of false positives (incorrect auto reviews). This is approach is good for discovering issues that are not critical and reporting overall trends of individual issues.

Advantages:

- Most of the findings are correct.

- Spending less time going through the auto reviews.

Disadvantages:

- You might miss a lot of conversations within important content for understanding all different variations of the given issue.

Uses:

- Rough understanding how common an issue is.

- Watching longer term trends to ensure actions to address an issue have an actual impact on the conversations.

- Finding outliers (agents, teams, etc.) performing better or worse than others.

### [](#high-recall)High Recall

When focusing on high recall you will get potentially a high number of false positives (incorrect auto reviews) but you are much less likely to miss an actual occurrence. High recall is useful for situations when you want to minimize chance of missing an issue and you are willing to pay by your time to walk through high number of incorrect findings.

Advantages:

- Significantly reducing a chance of missing a conversation containing the given issue.

- Chance of discovering similar issues to the one you search for.

Disadvantages:

- Spending more time going through the incorrect auto reviews.

Uses:

- Find behavior that can have a severe impact on the company such as legal, regulatory and privacy issues. Finding customers exposed to this behavior can help you to proactively resolve the issue and minimize associated risks.

---

## Build Menus using Your Logic

Source: https://help.salted.cx/en/articles/your-logic-menus


Article short description

You can use Your Logic to guide users through structured menus instead of relying solely on free text conversation. Menus offer several advantages over chat messages:

- For common issues it is often easier for customers just to choose a menu option rather than describing the issue in text.

- Customer responses are easier and more reliable to process. You do not need to apply AI to understand the request.

Salted CX [Universal Chat](https://help.salted.cx/en/articles/universal-chat) enables to show menus while enabling customers to reply by both clicking an answer or by writing a free text.

## [](#show-menu-options-to-the-customer)Show Menu Options to the Customer

Your Logic can ask Salted CX to ask the customer questions on your behalf. Your Logic converts your question to work properly in both Universal Chat and WhatsApp. You do not have care about differences across platforms.

Keep in mind you can use your code to generate the menus. This gives you total control on what options you offer to the customer and the order in which you provide them. You can take into consideration the customer attributes and the current issue you are trying to resolve. You can also A/B test different menu orders.

Learn about [Update Conversation](https://help.salted.cx/en/articles/your-logic-actions) how to offer the customers dynamic menus.

## [](#listen-to-responses)Listen to Responses

Whenever a user clicks on any menu item you will receive that event into Your Logic and you can react to it. When you receive a response you can respond in any way that you see fit.

Learn about [Answer](https://help.salted.cx/en/articles/your-logic-requests) in what format Salted CX sends answers.

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

Remember that the customer can ignore the menu options and send you free text. Your Logic must be ready to process both options. It you have a very simple implementation that only supports menus and cannot process chat you can escalate the conversation to a human using [Needs Help](https://help.salted.cx/en/articles/your-logic-actions).

*Tags: Universal Chat, Your Logic*


---

## Universal Chat Integration

Source: https://help.salted.cx/en/articles/universal-chat-integration


Article short description

To integrate Universal Chat to your web page, you should take the following steps:

- Setup a brand. In [Universal Chat Settings](https://help.salted.cx/en/articles/universal-chat-settings?v=24f5d3a2a8dc81f49249000c3e502787) you can customize how the universal chat behaves and looks. You also can list domains that are allowed to include Universal Chat.

- Include integration code into your web page. Use the code that you get form Universal Chat Settings and paste it into your web page to show the web chat to the customer.

- Pass customer ID to the chat. This is optional but highly recommended as it enables to link the customer to their data.

## [](#setup-a-brand)Setup a Brand

You can [set up a Universal ](https://help.salted.cx/en/articles/universal-chat-settings)Chat brand directly in the Salted CX app. The brand enables you to customize the behavior and look of the chat. You can set up multiple brands to provide different customer experiences for different segments of your customers.

![](https://www.notion.so/icons/warning_yellow.svg?mode=light)

Ensure that your domains where Universal Chat is to be used are added in the brand setup. Salted CX prevents using Universal Chat connected to your account on domains not listed in the brand setup.





## [](#include-code-in-page)Include Code in Page

Copy the integration code for the brand of your choice from [Universal Chat Settings](https://help.salted.cx/en/articles/universal-chat-settings) and paste into into your web page. The code has two parts. Include the following snippet in the `head` section of the HTML file:

```javascript
<script type="module" src="https://saltedcx.github.io/universal-chat-web-component/universal-chat.js"></script>
```

Place the following code at the end of your `body` of your HTML file:

```javascript
<universal-chat accountid="<domain name in Salted CX without region>" brandId="<unique identifier of the brand from Universal Chat brand settings>"></universal-chat>
```

Make sure you list your website domain in the allowed domains section of the settings. The brand can only be embedded into the domains you list there.

Example of implementation using JavaScript only```javascript
const scriptElement = document.createElement('script');
scriptElement.type = 'module';
scriptElement.src = 'https://saltedcx.github.io/universal-chat-web-component/universal-chat.js';

const chatElement = document.createElement('universal-chat');
chatElement.setAttribute('accountid', '<domain name in Salted CX without region>');
chatElement.setAttribute('brandId', '<unique identifier of the brand from Universal Chat brand settings>');

document.body.appendChild(scriptElement);
document.body.appendChild(chatElement);
```





## [](#pass-customer-data-to-chat)Pass Customer Data to Chat

Passing customer data enables linking the chat session to a specific customer. This enables [Your Logic](https://help.salted.cx/en/collections/1755764337-your-logic) and human agents to access the customer data. Salted CX requires that you digitally sign the data in a save environment (server side) so the bad actor cannot impersonate somebody else. Salted CX verifies the data on the server side as well.

![](https://media.notiondesk.so/upload/68b164da92491814319807.png)

## [](#custom-data-format)Custom Data Format

You need to provide the data in a format supported by Universal Chat. The data are in JSON format.

The payload

| Property | Type | Description |
|---|---|---|
| `conversation` | Object | Structured object containing information about the conversation. |
| `customer` | Object | Structured object containing information about the customer. |



### [](#conversation-object)Conversation Object

Properties in the `conversation` object:

| Property | Type | Description |
|---|---|---|
| `custom` | JSON | Custom JSON that contain conversations that is customer specific. |



### [](#customer-object)Customer Object

Properties in the `customer` object.

| Property | Type | Description |
|---|---|---|
| `contact` | [Contact](https://help.salted.cx/en/articles/universal-chat-integration?v=24f5d3a2a8dc81f49249000c3e502787#25a5d3a2a8dc8059bc6fe07a402dbcae) Object | The contact this chat session is associated with. This can be either an internal customer ID or some global identifier such as email. |
| `displayName` | String | Name of the customer that agents will see. This name SHOULD not contain protected personal information. We recommend using the first name. The length of the value is limited to 100 characters. |
| `relatedContacts` | Array of [Contacts](https://help.salted.cx/en/articles/universal-chat-integration?v=24f5d3a2a8dc81f49249000c3e502787#25a5d3a2a8dc8059bc6fe07a402dbcae) | The list of related contacts to the customer. These contacts enable to link the customer to other conversations in the [customer journey](https://help.salted.cx/en/collections/1755250527-customer-journey). So if you have a past conversations in other channels you will see them in the customer journey with the current Universal Chat session. Learn more about [Customer Profile](https://help.salted.cx/en/articles/customer-profile) |



### [](#contact-object)Contact Object

Properties in the `contact` objects.

| Property | Type | Description |
|---|---|---|
| `type` | String | Type of the contact. Use `Email` and `Phone` value for emails and phones. You can use other values to distinguish the contact type, for example `Customer ID` for internal customer IDs. |
| `externalId` | String | The actual contact information — ID, phone, email, value. The length of the value is limited to 100 characters. |



```json
{
	 "conversation": {
		  "custom": {
		  }
	  }

	"customer": {
		"contact": {
			"type": "Customer ID",
			"externalId": "9e065dd3-14e2-4c67-832c-03b320be65c1"
		},
		"displayName": "Carmen",
    "firstName": "Carmen",
    "lastName": "Sanchez",
    "language": "en",
		"relatedContacts": [
			{
				"type": "Email",
				"externalId": "carmen.sanchez@email.com"
			},
			{
				"type": "Phone",
				"externalId": "+420123456789"
			}
		]
	}
}
```

Example customer data payload![](https://www.notion.so/icons/warning_yellow.svg?mode=light)

Do NOT include any data that you do not want your customers to see. The customer can see the payload of the data. Customers cannot tamper with the data due to the digital signature.





## [](#create-a-jwt-token)Create a JWT token

To pass data to Salted CX, you need to create a JWT token that contains the customer data, expiration time, signature, and a few other properties required by JWT.

- Generate a private and public key pair.

- Store your private key in your secrets manager where your server code can access it.

- Paste your public key for verifying the signature of the requests. Go to [Universal Chat settings](https://help.salted.cx/en/articles/universal-chat-settings) and paste the value Customer Data Signature Key.

Once you have encryption keys setup you need to implement creation of JWT token with the desired payload.

```json
{
  "header": {
    "alg": "RS256",
    "typ": "JWT"
  },
  "payload": {
	  "conversation": {
		  "custom": {
			  
		  }
	  }
  
    "customer": {
      "contact": {
        "type": "Customer ID",
        "externalId": "9e065dd3-14e2-4c67-832c-03b320be65c1"
      },
      "displayName": "Carmen",
      "firstName": "Carmen",
      "lastName": "Sanchez",
      "language": "en",
      "relatedContacts": [
        {
          "type": "Email",
          "externalId": "carmen.sanchez@email.com"
        },
        {
          "type": "Phone",
          "externalId": "+420123456789"
        }
      ]
    },
    "iat": 1730314320,
    "exp": 1730400720
  },
  "secret": "your-256-bit-secret"
}
```

Example JWT token containing the payloadExample JavaScript code for generating a JWT token```javascript
import fs from "node:fs";
import path from "node:path";

import { importPKCS8, SignJWT } from "jose";
import { v4 as uuidv4 } from "uuid";

async function generateSaltedCXToken(customerData) {
	try {
		const privateKeyPEM = fs.readFileSync(path.join("private.key"), "utf8");
		const privateKey = await importPKCS8(privateKeyPEM, "RS256");

		return await new SignJWT(customerData)
			.setProtectedHeader({ alg: "RS256", kid: "key-1" })
			.setIssuedAt()
			.setExpirationTime("24h")
			.sign(privateKey);
	} catch (error) {
		console.error("Error generating JWT token for Salted CX:", error);
	}
}

const jwtToken = generateSaltedCXToken(
		{
			customer: {
				contact: {
					type: "Customer ID",
					externalId: uuidv4(),
				},
				displayName: "Display Name",
				relatedContacts: [
					{
						type: "Email",
						externalId: "customer@email.com",
					},
					{
						type: "Phone",
						externalId: "+420123456789",
					},
				],
			},
		});
```





![](https://www.notion.so/icons/warning_yellow.svg?mode=light)

Always create the JWT token with customer data in a secure, controlled environment that the customer cannot access (e.g., a server). Do NOT generate it in the browser on the customer side.





### [](#pass-customer-data-via-javascript)Pass Customer Data via JavaScript

You need to have the JWT token available on the client side (browser) to pass to Salted CX. The exact way to make it available depends on the tech stack that you are using. Your JavaScript code can retrieve it using AJAX, from cookies or local storage, or any other method that works in your environment.

Once you have the JWT token available in the browser, you can pass it to Salted from the browser.

```javascript
window.SaltedCX.setContext(jwtToken);
```

Example code to pass the customer data to Salted CX## [](#embedding-in-ios)Embedding in iOS

The `webView` in the iOS app must handle links with `target="_blank"` to support downloading documents from Universal Chat. To achieve that, the WebView Coordinator should implement the following method:

```objective-c
 // Handle target="_blank" links by opening them in Safari
func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
    if let url = navigationAction.request.url {
        print("Opening link in Safari: \(url.absoluteString)")
        UIApplication.shared.open(url)
    }
    return nil
}
```

## [](#embedding-in-android)Embedding in Android

To ensure that customers get all the features of Universal Chat. You have to ensure the Android app has all the required permissions.

Ensure the `AndroidManifest.xml` contains the following permissions:

```java
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
```

When using `WebView` ensure that these settings are set:

```java
// Enable JavaScript
webView.settings.javaScriptEnabled = true
webView.settings.domStorageEnabled = true
webView.settings.databaseEnabled = true
webView.settings.cacheMode = WebSettings.LOAD_DEFAULT

// Enable file access
webView.settings.allowFileAccess = true
webView.settings.allowContentAccess = true

// Set DownloadListener to handle file downloads
webView.setDownloadListener { url, userAgent, contentDisposition, mimetype, contentLength ->
	val intent = Intent(Intent.ACTION_VIEW)
	intent.data = Uri.parse(url)
  startActivity(intent)
}
```

*Tags: Universal Chat*


---

## Challenges with AI-Powered Quality Assurance

Source: https://help.salted.cx/en/articles/1755222058-challenges-with-ai-powered-quality-assurance


In many companies AI-powered quality assurance is a new tool that people are not used to. This can bring some challenges that you want to be aware before using AI so you can get your colleagues aligned.

## [](#finding-issues-is-easier-than-solving-them)Finding Issues is Easier than Solving Them

Naturally, issues are easier to find than it is to solve them. There might be many technical, process, and regulatory reasons why an issue is not easy to solve. Any issue found in the contact center also competes with other priorities.

### [](#recommendations)Recommendations

There is no silver bullet for every possible issue. Solving every issue you find is rarely possible. Solving every issue is also rarely necessary. Prioritization is the key. You can use the traditional prioritization method to compare the effort versus value.

![](https://media.notiondesk.so/upload/689de248bde1d265000151.png)

Priority of each item is based on:

- Criticality (vertical axis) — How bad it is when this problem appears in a conversation. Low criticality can be punctuation issues, minor clarity issues, etc. High criticality are typically legal, compliance and privacy issues. You can roughly categorize issues based on knowledge of your business.

- Effort (horizontal axis) — How difficult is to solve the issue. Low effort could be actions such as talking to an agent, adding extra info to training, etc. High effort could be technical issues that need to be fixed in you platform, process issues, issues requiring cross-team coordination, etc.

- Quantity (bubble size) — How often the issue happens in your conversations. Auto Reviews in Salted CX help you to quantify this. Use data from Salted CX to either justify effort spent on a solution or use the data for leaving the solution for later.

Each of the above metrics is approximate and it is often difficult to calculate them precisely. Human judgement is necessary when using these indicators to prioritize issues to resolve.

How to approach discovered issues that do not have an immediate low effort solution:

- Start watching the issue quantity in reporting. This makes sure that the issue does not happen more frequently in the future which could influence its priority. Watching the trend also enables you to confirm any taken action has an actual impact.

- Let other people know about issues you find. This tells people that you are aware of the issue and the reason the issue is not resolved has a reason — low priority, high effort, it is work in progress, blocker on a vendor side etc. The good place to track these issues is your issue tracking such as Asana, JIRA, Trello and similar tools. You can also create a form in Salted CX that contains list of these issues.

- Consider partial non-perfect solutions. It is tempting to resolve any issue completely and perfectly. This is not always necessary. Perfect solution may be an order of magnitude more difficult to implement than a good solution or an acceptable solution. Involving coworkers when thinking about these steps can help with different perspectives and ideas how to tackle issues from different angles.

- Build any higher effort solution iteratively. Try to deliver solution in smaller chunks. You can check in reporting what impact each iteration has. If the issue becomes rare enough after an iteration you can decide not to build the next iterations.

## [](#working-with-approximate-numbers)Working with Approximate Numbers

The [accuracy of AI](https://help.salted.cx/en/articles/1755254757-auto-reviews-accuracy) depends on the specific scenario you would use it for. In every case, the accuracy will not be 100% percent. This would be also the case for people if they were performing the same job. It is practically impossible to perfectly calibrate people. However, when people review conversations this is not that visible as they review only a small subset of conversations.

Most people do not have much experience when working with an approximate numbers.

### [](#recommendations)Recommendations

Salted CX also provides features that help to improve accuracy and mitigate the impact of inaccuracies:

- Every Auto Reviewer should go through calibration to ensure that the findings really represent moments in conversations you intended to detect.

- Provide feedback to auto reviews. Quality assurance people can mark any AI finding as Correct, Unclear, or Incorrect. This feedback can help identify where the configured prompts or knowledge should be refined. It is not used to train or fine-tune the underlying AI models.

- Let agents acknowledge and dispute auto reviews. While AI searches for potential issues in agent behavior there is a natural incentive for an agent to dispute the findings. Agents can use agent profile to provide feedback to auto reviews.

## [](#transparency)Transparency

With easy access to issues found in conversations it is easy for anybody in the company to check what is currently happening. Communication and transparency is critical to ensure everybody is on the same page.

To maximize transparency:

- List you current issues in priority order in a single list or board. A shared list of the current issues helps everybody to see issues in the perspective.

- Have a clear process to report new findings. Ensure people have a way to report a new issues they discover either in dashboards in the customer journey. They also have to have a confidence that once they report anything it is acted on even if that means just giving it a low priority.

- Information at users’ fingertips. When you have a dashboard use the description sections to give users more information about how to use the dashboard and what conclusions to get out of the dashboard. If you create custom metrics also provide similar details to their description.

---

## Universal Chat Settings

Source: https://help.salted.cx/en/articles/universal-chat-settings


You can setup Universal Chat by going pressing the gear button in the top right corner of the screen and then clicking Universal Chat ![:r1:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/cbece7ea-90d1-42be-b944-7d3a40472c0a/Circle_1.png) in the left hand navigation.

![](https://media.notiondesk.so/upload/68ac556b3e07b800031893.png)

## [](#brands)Brands

You can have multiple different settings of Universal Chat represented by a brand. Switch brand by clicking the Brand navigation ![:r2:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/828ec6f6-6da7-41e1-ab7d-81f376318b90/Circle_2.png). All settings are related to the currently selected brand. Apply the changes by clicking the Save button ![:r15:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/35f1ed65-db33-49c8-ab30-85f2008e76a8/Circle_15.png).

You can use brands in case you handle conversations for multiple different brands or websites or you want to have web chats that provide a different customer experience. Each brand can have a different customer-facing look and feel and different behavior. The pool of the agents who handle the conversations across all brands within one account is the same.

[Engagements](https://help.salted.cx/en/articles/model-engagement) have Brand attribute that enables you do distinguish between conversations handled in individual brands. This is useful in analytics for A/B and other reporting on.

## [](#brand-customization)Brand Customization

Additionally you can customize other brand attributes:

- Brand color ![:r4:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/49964e58-e0e9-40b5-b973-00c416e5d0bc/Circle_4.png) — The color universal chat has when collapsed in the bottom right corner and color of other dominant user interface elements.

- Allowed Domains ![:r5:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/a8d7fc85-01c2-4beb-ae57-18073a27a40e/Circle_5.png) — Allowed domains restrict which web sites can include the Universal Chat that is associated with you account. Universal Chat will not work on other domains to prevent customers contacting you from outside of your website.

- Message on opening a chat ![:r6:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/22961b53-f52d-4017-87e3-e0ab43ddd029/Circle_6.png) — The message that sticks on top of the chat window all the time. The best use of this message is to set the right expectations with users. One of the example could be response times the customers can expect, whether they there is a bot involved in the conversation, etc.

- Customer message placeholder ![:r7:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/9e5e9e5f-9b80-4656-8d16-a78ef863eb57/Circle_7.png) — Message that shows in the customer text field. Should be a statement that invites customers to conversation.

- Agent messages background ![:r8:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/bd34cd7e-cbac-4650-9d97-2a4412a47520/Circle_8.png) — The color of the chat bubbles sent by anybody from your company. Universal Chat does not distinguish between bots and agents.

- Agent messages text ![:r9:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/72b59471-92ba-446c-94f7-8d19849cfc6a/Circle_9.png) — The text color in the agent chat bubbles.

- Customer messages background ![:r10:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/39cc41d0-405c-4a91-bb9a-f1c584d8fb1a/Circle_10.png) — The color of the chat bubbles sent by the customer.

- Customer messages text ![:r11:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/3ee86a8a-caf2-477b-accb-27c2e2a315ea/Circle_11.png) — The text color in the customer chat bubbles.

Make sure you press Save button ![:r15:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/35f1ed65-db33-49c8-ab30-85f2008e76a8/Circle_15.png) to apply the changes.

## [](#integration-with-website)Integration with Website

To pass information about the customer to Salted CX follow the guide in the article [Universal Chat Integration](https://help.salted.cx/en/articles/universal-chat-integration). Paste you public key to Public key for customer data verification ![:r13:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/ecf5bec7-0640-4f5a-928c-0f89d29f37ba/Circle_13.png). This key enables Salted CX verify that information passed form your website to Universal Chat are created by you and not altered by the customer.

Use the code ![:r14:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/6ffa2e34-8d07-42f5-a33e-f3cdb7891ba5/Circle_14.png) that the page shows you in your web application in any page where you want to show the Universal Chat. The code is specific for each brand and contains identifier of the brand. Make sure you have selected the brand you intend to use on the website.

## [](#privacy)Privacy

When you include Universal Chat in your website or application ensure that your privacy policy covers the scenario that Salted CX stores the user session in browser cookies. Below is an example statement that covers data collection by Salted CX. The statement is provided as is without guarantee that it will be aligned with your privacy policy.

Use of Cookies in Web Chat

Our website incorporates a web chat feature provided by Salted CX. This web chat uses cookie containing a unique session identifier to enable you to continue the conversations after you close and re-open the browser window. The unique session cookie is associated with your conversation history and activity.

We use this information to: • Provide continuity in your conversations when you return to our website. • Improve the quality and functionality of customer support.

Your chat data is stored securely and is not shared with any unauthorized third parties. You can manage or disable cookies via your browser settings; however, doing so may limit the functionality of the web chat feature.

For more information on how Salted CX processes chat data, please refer to [Salted CX Privacy Policy](https://www.salted.cx/privacy-policy).

*Tags: Universal Chat*


---

## Your Logic Implementation Tips

Source: https://help.salted.cx/en/articles/your-logic-implementation-tips


This article focuses on practical tips of implementing Your Logic enabled for Salted CX [Live Conversations](https://help.salted.cx/en/collections/1755577083-live-conversations).

## [](#main-loop-first)Main Loop First

When implementing Your Logic focus on the main conversation events first — opening and closing of the conversations. Open and closing should be present in 100% conversations, plus there is risk of other events happening. Main loop is something that is executed with every customer message.

You should cover these high level parts of the conversation first:

- Opening. Greeting the customer and asking what they want. You need to handle opening for any conversation as you want to make a decision to

- Closing. Opportunity to confirm that the customer request is resolved, collect customer satisfaction and goodbyes. See more in [Collect Customer Feedback](https://help.salted.cx/en/articles/your-logic-implementation-tips) section.

- Escalation detection. Detection that you want to escalate the request to an agent. This can be extremely broad in the first iterations (ask for help for all conversations after customer mentions any request) and very narrow at the end (do not even escalate when customer asks for an agent).

- Resolution detection. Detecting when the customer request is resolved and when it is time to wrap-up the conversation is essential to gather customer feedback and get confirmation that your bot and agents have really managed to resolve the conversation. The resolution detection can be very easy basic at the beginning (listening for an event that [agent engagement is completed](https://help.salted.cx/en/articles/your-logic-requests#2185d3a2a8dc80b69a73dd950c80efbd) and marked as resolved when you expect all conversations to be escalated) to a detection based on the provided responses and the customer answers (when the conversation is handled by a bot).

There are additional scenarios you might want to cover when you let bot handle conversations themselves without escalating everything to an agent:

- Abuse detection. Some customers may be bad actors and try to exploit the chatbot by providing its instructions to favor them even when they would be against policy. You should detect those before you let bot perform actions independently.

- Detection of requests unrelated to your business. You do not want your bot to be used for general purpose requests such as comparing you with your competition, writing long homework assignments, etc. You should detect this and politely respond to the customer that you are able to respond only requests related to your company.

- Smalltalk detection. You might want to tolerate certain level of smalltalk unrelated to your business. You should handle smalltalk according to your company preferences and not ask agents for help with it. Smalltalk may help to build a rapport with the customer so unlike requests unrelated to you business you might want to engage in it a little bit. With each response to a smalltalk you should drive the customer back to an actionable request.

- Detection of escalation. You might want to have escalation detection independent on specific scenario to ensure good customer experience. At the beginning it can be fairly simple based on [customers giving thumbs down](https://help.salted.cx/en/articles/your-logic-implementation-tips?v=2535d3a2a8dc8003abad000c1f135783#24f5d3a2a8dc8011b288f135e4d192cb) to the bot reply, customers telling their [request is not resolved](https://help.salted.cx/en/articles/your-logic-implementation-tips?v=2535d3a2a8dc8003abad000c1f135783#24f5d3a2a8dc803299d0d42b0bc4da6c) or giving you [poor satisfaction score](https://help.salted.cx/en/articles/your-logic-implementation-tips?v=2535d3a2a8dc8003abad000c1f135783#24f5d3a2a8dc803299d0d42b0bc4da6c). Later you can use detection of customer explicit request for an agent, detection of poor customer sentiment and other content based detection.

## [](#measure-key-metrics)Measure Key Metrics

Ensure your implementation is successful by measuring important metrics. All conversations that happen in Salted CX live conversations are automatically available for analytics. Ensure you define a healthy targets and keep metrics with those targets.

Example metrics you might want to watch:

- Customer satisfaction. Make sure you collect the customer satisfaction for every conversation in which it is possible and compare it with the conversations handled by people (if available) and watch how is the customer satisfaction trending.

- Escalation rate. Percentage of conversations that required agent help.

- Engagement time. Engagement time of the bot, followup agent engagement and their total for the conversation.

## [](#iterate-on-handled-scenarios)Iterate on Handled Scenarios

When you have the main loop ready and you can confidently ask human agents for help start implementing individual scenarios you want to completely resolve without an agent involvement. Also remember that for any impactful action you can still escalate to an agents to let them perform the action itself.

Pick you scenarios based on complexity to resolve and volume of conversations that will not have to go to agents. There is no exact rule for this. You can use Salted dashboards and visualizations to find what are the most common reasons customers contact you and what are the most common outcomes to understand where to focus your energy.

With every implemented scenario measure how you are doing. You might do it by [collecting customer feedback](https://help.salted.cx/en/articles/your-logic-implementation-tips?v=2535d3a2a8dc8003abad000c1f135783#24f5d3a2a8dc803299d0d42b0bc4da6c), checking feedback on [your replies](https://help.salted.cx/en/articles/your-logic-implementation-tips?v=2535d3a2a8dc8003abad000c1f135783#24f5d3a2a8dc8011b288f135e4d192cb) and measure other metrics. You might want initially to check manually at least sample of the conversations. Start with sample of traffic to decrease the blast radius if something goes wrong and move forward if you are happy with the metrics.

You should be able to split the conversation into these categories and keep the number of conversations in those categories within your targets:

- True resolution. Your Logic resolved the customer request. You have it confirmed from the customer or detected by other means (successful transaction) or reviewed by a person.

- No resolution. Your Logic provided an information to the customer but it is not a working solution. We have no response from the customer that it does not work. You should strive to have this low - eg. 5% of conversations.

- False resolution. Your Logic provided wrong information to the customer. You think the customer request is resolved and customer may think the request is resolved. However the false information may negatively impact you or the customer in the future. It is impossible to be perfect (even human agents will provide false information). However you should strive for very small percentage - eg. below 1% of conversations.

- Customer left. Your Logic needs information from the customer to continue but the customer has not provided this information and is not responding. Thus Your Logic cannot resolve the request but it knows it cannot resolve the request. This may happen when the customer resolved the issue in the meantime, it is a low priority for the customer, or they got frustrated and gave up. These are tricky and may require research into what happened and even reaching back to the customer.

- True escalation. Your Logic escalated a conversation that you intended to be escalated (the scenario is not yet supported, customer asking for escalation, etc.). These represent future scenarios you might consider handling better.

- False escalation. Your Logic escalated a conversation that it should be able to handle. This is not a big issue if you have enough agents to handle these escalations but you should incrementally reduce their number.

Additionally to those, also watch additional metrics such as customer satisfaction, engagement time, volume of refunds in transactions, etc.

## [](#conversation-opening)Conversation Opening

Even when you escalate to resolve all the customer requests use the opening of the conversation to greet the customer and ask them what they want. This saves some time to human agents as they can start responding to the customer right away.

Even simple chatbot not focused on achieving specific tasks can do the following:

- Greet the customer. Be polite and start and fulfill basic customer expectations.

- Manage expectations. Provide information that this is a bot and it may not be able to help with everything and tell customers what might be the expected response times for both the bot and wait time for a free human agent.

- Collect the customer request. Try to shorten the followup human agent engagement by having the customer request in front of their eyes when they open the conversation.

Additionally you can also use buttons to [Give Customer Quick Choices](https://help.salted.cx/en/articles/your-logic-implementation-tips) to resolving the most common issues.

## [](#help-of-human-agents)Help of Human Agents

Your Logic can easily ask human agents to help with the conversation using action [Needs Help](https://help.salted.cx/en/articles/your-logic-actions). It is completely up to Your Logic to decide in which cases it will ask humans for help. In case Your Logic is not available, does not respond in time, or responds in an unsupported format Salted CX will ask agents for help automatically.

Consider these factors when asking for help:

- Be aware of number of available agents. You should rollout Your Logic incrementally to ensure that there is enough human agents as a fallback in case Your Logic does not work as expected, customers ask questions you haven’t though of and similar scenarios. Keep in mind that high percentage of conversations handled automatically with Your Logic naturally leads to fewer agents available over time as they would sit idle most of the time. So the more conversations you handle automatically the more pressure there is not to ask for help as your agents would get overwhelmed.

- Mind the business hours. This is related to the previous point but it deserves a separate point. Some companies may have business hours in which there are less agents or no agents outside of business hours. Using bots that operate 24/7 can increase the customer expectations. So when a human help is needed make sure to manage the customer expectations and tell them they may need to wait.

- Manage handover to agent. Your Logic can perform multiple actions at once. So when you are asking agents for help you can smoothen the transition. You should let the customer know that they may need to wait for a human agent. Optimally you can try to respond to customer request the best you can (even when customer asks for human, or you have lower confidence in your answer) with the disclaimer to the customer. If the conversation is longer you can also give some notes to the agent by creating a note [Save Note](https://help.salted.cx/en/articles/your-logic-actions). The note can summarize the previous conversations, explain the agent why help is needed, etc.

![](https://www.notion.so/icons/chat_purple.svg?mode=light)

I will need help from a human colleague with that. Give me a moment. The agent typically joins within 5 minutes.In the meantime, you can give us additional details about your request. This might help the agent to resolve your request faster.









## [](#let-customers-talk-to-humans)Let Customers Talk to Humans

If possible in you environment allow your customers to talk to people without a hustle if they request it. Focus on making these things right:

- Ensure the customer feels they are not bothering you. Make sure customers feel there are people in your company they care about them.

- Manage expectations. Give the customer an estimate how long they are likely to wait. This can be static value, based on business hours, or smarter dynamic methods based on volume and available agents. Have a buffer so you can over deliver.

- Collect information to speed up resolution. After you did what customer asked for use the time before an agent joins to collect any information that help the agent to resolve the request as fast as possible. This is great for both the customer experience and reducing handling time (costs).

![](https://www.notion.so/icons/chat_purple.svg?mode=light)

Sure. I have asked an actual person to join this conversation. It usually takes about 10 minutes to find somebody available.In the meantime, please tell us how we can help you. This helps our agents have all the necessary information available when they join and resolve your request faster.









Optionally you can try to answer the customer request by the bot before the agent joins. However you have to be extra cautious not to create the impression the agent is not joining and have really high confidence you have a complete answer.

## [](#take-back-control-from-human-agents)Take Back Control from Human Agents

You Logic stays in the conversation even after it asked for help of a human agents. You can take control back if there is an event that enables you to do so — for example customer clarifies their question, the human agent leaves the conversation and tells the bot can finish it.

Taking back control of the conversation helps to decrease the load on the agents. Your Logic can continue or wrap up the conversation without the agent involvement. If Your Logic needs help it can still ask for help again and agents will be asked for help.

## [](#invite-external-agents)Invite External Agents

The cost of resolving the customer requests grows with the time and resources you have to invest into resolving the request. The simplified view looks like this:

Your Logic can use [Invite External Agent](https://help.salted.cx/en/articles/your-logic-actions) to ask people who are not even users in Salted CX to join the conversation and help to resolve the customer requests. When you invite and external agent they will get narrow permission to handle the specific conversation.

Remember that external agents may have different service level policy, may not be that responsive as your agents. It is necessary to set expectations with the external agents so they are aware of the customer expectations. Make sure you also manage customer expectations when involving the external agents.

The following example shows how the Your Logic can respond in case when it is not sure how to answer. In total these are 3 actions. First managing the customer expectations especially due to possible wait time and enable the customer to talk to us in the meantime. Second Your Logic saved a note visible only to agents that sums up the current conversation so was and tells what is expected from the agent. ThirdYour Logic sends the actual invite to the person.

![](https://www.notion.so/icons/chat_purple.svg?mode=light)

I am sorry, I cannot help you with that. Let me ask a person to help you. We will ask somebody from Live the Music to help you out. Please give our partner up to 8 business hours to respond. Let us know if there is something else we can help you with in the meantime.





![](https://www.notion.so/icons/compose_purple.svg?mode=light)

The customer wants a refund of Rock Concert tickets for $400 in Miami, Florida at May 7 due to a storm Catrina. There are no guidelines whether refunds cover these circumstances. Please decide refund the customer if applicable, otherwise explain the customer why the situation is not covered by a refund.





![](https://www.notion.so/icons/user-circle-dashed_purple.svg?mode=light)

Your Logic invited the external agent Live the Music to this conversation





## [](#give-customer-quick-choices)Give Customer Quick Choices

Your Logic can use [Ask Question](https://help.salted.cx/en/articles/your-logic-actions) and [Update Conversation](https://help.salted.cx/en/articles/your-logic-actions) to give the customer a set of possible options to move the conversation forward without having to write. This is a great way to make the customer experience better and more efficient.

Using questions with answers has some advantages:

- Some customers prefer clicking through menus rather than chatting with a bot. Sometimes it is easier and faster for customers to pick one of the offered option than describing the request.

- Easy to process the answer. You do not have to use AI to analyze the customer response. You know exactly what the customers clicked. This enables to respond faster to customer clicks, saves money and avoids level of uncertainty that is always associated with analyzing a free customer answer.

The usefulness of menus in chat depend on their clarity and options available to the customer. You should watch how often customer use the menus and try to increase their usage over time. You can use questions that are managed by users directly in Salted CX or generate custom menus on the fly.

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

When you ask a question from Your Logic the customers can ignore the question and write you a free text response. Your Logic MUST be ready for it. This is to provide the best customer experience and not forcing the customers to use one modality — menus.





## [](#collect-customer-feedback)Collect Customer Feedback

There are at least two essential questions you should always at the end of the conversation:

- Is the customer request resolved? When you have high confidence that you have resolved the customer request try to gather explicit confirmation. Use [Ask Question](https://help.salted.cx/en/articles/your-logic-actions) to get answer to this. If customer answers No you can take is a signal to ask human agents for help.

- How is customer happy with the conversation. After you know that a customer request was resolved ask the customer to give you feedback as soon as possible. Use [Ask Question](https://help.salted.cx/en/articles/your-logic-actions) to collect the customer satisfaction feedback. Make sure you

Gathering customer feedback is a great way for quality assurance that you crowdsource to your customers and thus costs you very little time and money. Customer feedback is also available in analytics to help you track how you are doing and identify problematic conversations.

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

Keep in mind it is fairly common for customers not answering those questions. This happens both when their request is resolved and when it is not. So the silence from the customer side should be interpreted with uncertainty. Try to ask as few questions as possible not to waste the customer time and increase probability they keep answering your questions.





The following flow shows the example of collecting a customer feedback including automatic closing after a human agent answers the core of the question.

![](https://www.notion.so/icons/chat_blue.svg?mode=light)

To add a new traveler you just need to go list of trips in Account ⏵ Trips and click Modify Booking. Then there is Add Traveler on top of the screen, click that and fill the persons detail.





![](https://www.notion.so/icons/checkmark-line_blue.svg?mode=light)

Adam resolved their engagement with the outcome Account Info Provided





![](https://www.notion.so/icons/chat_purple.svg?mode=light)

We want to be sure. Have we solved your request?





![](https://www.notion.so/icons/chat_green.svg?mode=light)

Yes





![](https://www.notion.so/icons/chat_purple.svg?mode=light)

Thank you. How would you rate your experience?`Great` `Good` `Bad`









![](https://www.notion.so/icons/chat_green.svg?mode=light)

Great





![](https://www.notion.so/icons/chat_purple.svg?mode=light)

Thank you for your feedback. Let us know if you need anything else. Have a nice day!









## [](#act-on-live-customer-feedback)Act on Live Customer Feedback

Salted CX enables to give customers Thumbs Up/Thumbs Down to the replies they receive from Your Logic, your agents or external agents. Your Logic receives notification about this feedback and can respond accordingly.

Thumbs Up it is a great signal that should increase your confidence you are addressing the customer request and may be a good indicator to ask whether the [request was resolved](https://help.salted.cx/en/articles/your-logic-implementation-tips#24f5d3a2a8dc803299d0d42b0bc4da6c).

Thumbs Down is a signal that you may need to take action. The exact action depends on who received the negative feedback. If it is bot, you might consider it a signal to escalate to an agent. If an external agent receives the feedback you might want to ask your agents for help.

All the feedback received from the customers is also available in analytics and you can use it to find out problematic conversations.

## [](#reply-structure)Reply Structure

Recommendations on how to formulate replies sent by Your Logic are very similar to recommendations given to human agent. While using AI to answer the customer requests may cause extra caution you should built-in the caution into the replies in a way that does not feel robotic.

When replying to a customer you should always consider the following:

- Start with direct and short answer. Customers should see what they look for first, not dig it out from the middle of a lengthly response.

- Confirm you are answering the actual customer question. The more complex the question is the you should confirm you are answering what the customer is asking for. Ideally merge the confirmation into the explanation of the answer.

- Provide an explanation to the customer. First this helps you to confirm you are actually answering the question. Secondly it helps to manage customer satisfaction in case they might not like the answer. The explanation should always try to communicate you empathize with the customer and try to be fair.

- Answer potential followup questions. If the original request often leads to follow-ups answer them righ with the reply. You can save the customer some time, increase the customer satisfaction and reduce chance of the customer contacting you in the future.

- Highlight important information. If the explanation is longer, use bold to highlight the most important sections for the customer.

- Offer the next best action the customer. If there is a decision you want from a customer or some action they should take, tell the customers. You can give them [menu options](https://help.salted.cx/en/articles/your-logic-implementation-tips?v=2535d3a2a8dc8003abad000c1f135783#24f5d3a2a8dc80caad93c4cca11df75c) to perform these actions or provide useful hyperlinks.

- Educate the customer about self-service. To make customers more independent consider offering them a self-service actions they can take. This decreases their dependency on your customer care and decreases your future load. Make sure you do not sound too pushy and you are acting in the customers’ own interests.

Consider the following exchange example:

![](https://www.notion.so/icons/chat_green.svg?mode=light)

Is my trip to Mt Blanc refundable?





![](https://www.notion.so/icons/chat_purple.svg?mode=light)

I understand that you are asking about whether your trip to Mt. Blanc is refundable.Your trip to Mt. Blanc is refundable, as it is booked for 15 April and is still more than 72 hours away. So, according to our policy, you can have it refunded.









The example reply to a customer request is technically correct (contains the correct information) but does not focus on readability. Rather than starting with the response it starts with lengthy confirmation the bot understands the question. While this statement tries to play it safe in case the AI did not manage to extract the customer request intent correctly it makes the reply hard to read, overly wordy and not authentic.

The actual answer “Yes” is answered using a long phrase from a policy (not customer) perspective. It uses factual data and company policy information instead of communicating the impact on the policy and dates on the customer. We also do not offer any next best action for the customer.

Alternate reply to the same customer question:

![](https://www.notion.so/icons/chat_green.svg?mode=light)

Is my trip to Mt Blanc refundable?





![](https://www.notion.so/icons/chat_purple.svg?mode=light)

Yes. You can refund your trip to Mt Blanc until 12 April. To refund this trip [open the trip page](http://salted.cx/) and click the Refund button or just ask me to refund.

`Refund to Credits`









The example above contains the same information. However it takes into consideration the guidelines. Is starts with direct short answer. It then combines answering potential followup question while confirming it is answering the customer question. It then highlights the information that may be important the customer — the deadline for refunding.

We also use the opportunity to educate the customer how they can refund the trip themselves directly in our application. This is useful to reduce future load on the customer care and also make customers aware of the features of our application. We do not force the user to use the application as they can still ask about the refund in the application. We offer them quick button for the step we would prefer the customer to take.

## [](#unsupported-features)Unsupported Features

Salted CX may send various types of events to Your Logic. In the future, there might be additional events sent to Your Logic. So you should make it ready to handle unknown event types.

It is not necessary to act on every single event by taking an action. Even for those events, you should respond to Salted CX with[No Actions](https://help.salted.cx/en/articles/your-logic-actions). This tells Salted CX that it can continue sending you next events in the conversation.

When you encounter an unknown event, you have two choices:

- Take no action. We recommend to respond with no action by default.

- Ask for help. This increases the load on agents. We do NOT recommend using this for unknown events.

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

Salted CX will announce upcoming events to make sure you have time to get ready. We recommend watching our [releases page](https://help.salted.cx/en/articles/releases).

*Tags: Your Logic*


---

## Zingtree Integration

Source: https://help.salted.cx/en/articles/integration-zingtree


Self-service for customers is the essential way to resolve common and simple customer requests quickly, efficiently, and without human agent engagement. Zingtree enables you to offer customers self-service on your website to help customers resolve some of their requests without the need to talk to an agent.

Visibility into self-service and how it overflows to your contact center enables you to partially or completely automate more customer conversations, or avoid the need for customers to reach you completely. Ultimately leading to more resolved customer requests more efficiently and increasing customer satisfaction.

## [](#supported-features)Supported Features

Zingtree integration enables you to:

- See customers using self-service and their success rate in resolving the issues.

- Segment volume by the path the customers go through in Zingtree.

- Measure the time the customer spends in Zingtree.

- Understand how many customers and in what cases they need to be connected to human agents.

## [](#zingtree-data)Zingtree Data

Zingtree sessions are translated to [Engagements](https://help.salted.cx/en/articles/model-engagement) and [Turns](https://help.salted.cx/en/articles/model-turn) in Salted CX:

- One customer Zingtree session produces one Engagement of type `Menu`

- Each step in the customer session creates a turn of type `Menu Step`

- Each step in the agent session creates a turn of type `Menu Step` associated with the agent engagement

### [](#engagement)Engagement

Properties of the data set and how the individual items are calculated from Zingtree data.

| Property | Type | Calculation |
|---|---|---|
| Engagement | PID | PID based Zingtree `session ID` |
| Engagement Link | Label for Engagement | Link that points to the specific session within Zingtree at `https://zingtree.com/show/<tree id>?session_id=<session id>` |
| Engagement Name | Label for Engagement | Human readable session ID |
| Agent | Reference to Agent | — |
| Contact | Reference to Customer | `session id` |
| Start Time | Date and time | `start_time_utc` |
| End Time | Date and time | `last_click_time_utc` |
| Campaign | Attribute | — |
| Case | Attribute | — |
| Channel | Entity | — |
| Channel Type | Attribute | — |
| Channel Vendor | Attribute | `Zingtree` |
| Company Contact | Entity | — |
| Conversation | Attribute | PID based on `session ID` |
| Direction | Attribute | `Inbound` |
| Engaged Team | Entity | — |
| Language | Attribute | — |
| Location | Attribute | — |
| Menu Path | Entity | PID is calculated based on an array of tree IDs and node numbers `path` ⏵ `index` ⏵ `subtree_id` |
| Outcome | Entity |  |
| Outcome Category | Entity | — |
| Platform | Attribute | `Zingtree` |
| Priority | Attribute | — |
| Queue | Entity | Name of the tree in Zingtree |
| Service Level | Attribute | — |
| Source | Attribute | `Zingtree` |
| Status | Attribute | `Unknown` |
| Terminated By | Attribute | — |
| Type | Attribute | `Menu` |
| Cost | Fact | — |
| Engagement Time | Fact | Session property `duration_seconds` |
| Focus Time | Fact | — |
| Hold Time | Fact | — |
| Invitation Time | Fact | — |
| Preparation Time | Fact | — |
| Time | Fact | Technical timestamp representing Start time. As a fact, this can be used for sorting and arithmetics in reporting. |
| Wait Time | Fact | — |
| Wrap Up Time | Fact | — |



### [](#turn)Turn

Properties of the data set and how the individual items are calculated from Zingtree data

| Property | Type | Description |
|---|---|---|
| Turn | PID | PID dased on `session ID` and `path` ⏵ `seq` |
| Engagement | Reference to Engagement | PID based Zingtree [`session ID`](https://help.salted.cx/en/articles/integration-zingtree) |
| Turn Time | Date and Time | Session `start_time_utc` + durations of steps that led to this step |
| Category | Entity | `page_title` |
| Type | Attribute | `Menu Step` when customer choose a menu item in the menu to move forward in the flow `Menu Restart` when customers return to the beginning of the tree Menu Back |
| Duration | Fact | Session `path` ⏵ `index` ⏵ `seconds` |
| Length | Fact | — |
| Confidence | Fact | — |



### [](#customer-journey)Customer Journey

We also create a content table that contains individual options content and can be used for visualization in the customer journey. Each turn contains a label of the menu button the customer pressed.

## [](#setup-the-integration)Setup the Integration

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

This setup requires that you have the admin role in Zingtree.





To enable integration with Zingtree follow these steps:

- Login into your Zingtree account

- Click My Account in the top right corner

- Click Organizations &amp; Billing in the open menu

- Click Api &amp; Data in the left hand navigation

- Copy the API key from the screen

- Share the API key securely with Salted CX

- Give us a few days to enable the integration for you. We will notify you once it is enabled.

Learn more about [Zingtree](https://zingtree.com/).

*Tags: Integration*


---

## AI-Powered Quality Assurance

Source: https://help.salted.cx/en/articles/1755188089-ai-powered-quality-assurance


You can use AI to review 100% of conversations with the customers automatically. The AI works with different accuracy for different cases and it is not usable in every scenario. You can use AI to provide automatic reviews of individual turns in conversations.

## [](#how-ai-works)How AI Works

In Salted CX, automated quality assurance receives conversation content, including transcripts and individual messages from a customer journey. The workflow applies configured prompts, relevant knowledge, and review criteria to produce automatic reviews. Manual reviews may provide examples for refining and validating those configurations. Customer data is not used to train or fine-tune the underlying AI models.

### [](#prompts-knowledge-and-review-examples)Prompts, knowledge, and review examples

General-purpose AI does not automatically understand your business rules or quality criteria. Automated reviews therefore use configured prompts, relevant knowledge, and representative human-review examples. The number and type of examples needed depend on the criterion being evaluated.

### [](#human-review-examples)Human review examples

People can review conversation content and record examples of expected findings through manual reviews. These examples can help refine prompts, knowledge, and evaluation criteria for the configured automated-review workflow. Customer conversations, reviews, and feedback are not used to train or fine-tune the underlying AI models.

## [](#manual-reviews-for-improving-automated-qa)Manual Reviews for Improving Automated QA

Representative human reviews help define and validate what an automated review should identify. The number of examples depends on the specific criterion, and some observable behaviors are easier to identify consistently than others.

### [](#turn-level-reviews)Turn-Level Reviews

Turn-level reviews provide focused examples tied to the relevant wording in a conversation. This makes it clearer which observable content is significant for the configured review criterion.

Engagement-wide reviews that are common for legacy quality assurance do not point to the exact moment in a conversation which makes it significantly more difficult for AI to understand what content in the conversation is the main contributor to the searched phenomenon. Legacy quality assurance would lead to significantly lower accuracy and the need to provide orders of magnitude more engagements.

![](https://media.notiondesk.so/upload/698d913b10dd9309036081.png)

In the example above you see a comparison of turn-level tags with engagement level quality assurance questions. You can notice that the snippet from a conversation contains examples of both good objection handling and poor objection handling. Turn-level tags provide focused evidence of what reviewers consider a positive or negative example.

With engagement-level questions, the totally opposite behaviors are not distinguishable from each other. Additionally, an engagement-level example can contain unrelated conversation topics that make the intended criterion less clear.

To sum it up engagement-wide questions used in legacy quality assurance processes have these issues:

- Noise from unrelated parts of a conversation. If the behavior appears only in part of the conversation, the remaining content can obscure the intended criterion. This can require more manual-review examples and may still reduce accuracy.

- An engagement can contain both good and bad behavior. In this case, the engagement is not suitable as one undifferentiated example. Using it that way can lead to non-actionable findings and reduced accuracy.

### [](#tags-and-questions)Tags and Questions

Provide relevant manual-review examples for each tag or question used by the automated-review workflow. You can create custom tags and questions for AI-powered auto reviews.

When you create tags and questions for AI-powered quality assurance these tags and questions should be individually actionable:

- Unwanted behavior. The behavior of either an agent or a customer that represents a situation that is not welcome in your business. You might want to address these either by talking to the agent or changing processes and policies.

- Exceptionally good behavior. The behavior that might be used as a good example is when you exceed customer expectations thanks to your products, services, processes, or agents. This should not include a baseline expected performance from the agent. Such behavior should be considered a default and should not require attention.

- Unexpected behavior. The behavior that is new or unexpected and you may want to check how common it is and whether it is necessary to adapt your processes and train agents for it.

Behavior that is not worth noticing and represents an expected customer experience is not worth tagging in most cases. We recommend spending the time as efficiently as possible and focusing on behavior you can act on later on — you can tell that you need to talk to an agent, change something in your business process, or fix something in a product.

Check [built-in tags and questions](https://help.salted.cx/en/articles/questions-built-in).

## [](#how-to-review-conversations)How to Review Conversations

To review a conversation in an AI-friendly manner we strongly encourage you to follow our recommendations in the [Quality Assurance](https://help.salted.cx/en/collections/1755201479-quality-assurance) article. Especially focusing on these:

- Read a conversation in chronological order. This gives you an understanding of the context and helps you to relive the customer experience.

- When you encounter an unwanted behavior, exceptionally good behavior or an unexpected behavior tag it. You can use one of the built-in tags, create your own, or if the behavior is something new use the generic Bookmark tag to return to it later.

- Wrap up your review session by considering whether you want dedicated tags for a new behavior you have encountered. You might also consider adding more granularity to existing tags to distinguish between behaviors you want to report on separately.

## [](#process-improvements)Process Improvements

Companies evolve and externalities change. This leads to discoveries in conversations on an ongoing basis.

- Keep your tags and questions up to date. When you encounter a new behavior that is worth watching create a tag for it. Also, remove tags for behaviors that no longer appear in the conversations.

- Add tags and questions to your forms after review sessions. If you could not tag a behavior from the form you had at hand during the review session consider adding the tag to your form to avoid switching between different forms. This saves you some valuable time. Always try to balance the length of the form with its usefulness for your reviews. Longer forms may be harder to navigate and slow down some reviews.

---

## Export API

Source: https://help.salted.cx/en/articles/1774628621-export-api


Article short description

The export API provides RAW data available in Salted CX so you can import it into your data storage, analytics solution, business intelligence, or AI tools.

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

The API is intended for low-frequency batch use, such as daily exports. We might restrict access to the API or rate-limit its use due to excessive usage. The API limit for an exported date range is 24 hours. You have to export data in 24 hours batches.





# [](#authentication)Authentication

All endpoints require a valid API key in the `Authorization` header:

```javascript
Authorization: Bearer <your-api-key>
```

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

Ask a Salted CX contact person to share the API Key with you in a secure way.





# [](#workflow)Workflow

1. Initiate an export via `POST /api/v1/export` — returns an `exportId` and a `statusUrl`

2. Poll the status via `GET /api/v1/export/{exportId}/status` until `status` is `COMPLETED`

3. Download the CSV files using the `downloadUrls` from the completed status response (URLs are valid for 1 hour)

---

# [](#endpoints)Endpoints

## [](#post-api-v1-export)POST `/api/v1/export`

Initiates an asynchronous export. The export runs in the background; use the status endpoint to track progress.

### [](#query-parameters)Query Parameters

| Parameter | Required | Description |
|---|---|---|
| `from` | Yes | Start of the date range (ISO 8601), e.g. `2024-01-01T00:00:00Z`. See Filtering semantics below. |
| `to` | Yes | End of the date range (ISO 8601), e.g. `2024-01-02T00:00:00Z`. See Filtering semantics below. |
| `include` | No |  |
| `contact` | No | Email or phone number to filter by a specific customer profile |



### [](#filtering-semantics)Filtering semantics

For each dataset, a record is exported if either of the following holds:

- The engagement linked to the record started in the `[from, to)` range (`engagement.start_time`).

- The record itself was updated in the `[from, to)` range (the dataset's own `updated_at` column — e.g. `customer.updated_at`, `turn.updated_at`).

This means the export captures both new activity and changes to previously-existing records (for example, a renamed customer, a re-categorised service, or a reviewed turn whose review was edited) within the window.

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

Note on mass updates: If a bulk operation touches `updated_at` on many rows (for example, during a data migration), the export for that window can be substantially larger than usual. The 24-hour range limit bounds the maximum exposure.





### [](#constraints)Constraints

- The date range (`to` minus `from`) must not exceed 24 hours

- `from` must be before `to`

### [](#response-200)Response (200)

```json
{
  "exportId": 12345,
  "statusUrl": "/api/v1/export/12345/status",
  "createdAt": "2024-01-01T10:00:00Z"
}
```

| Property | Type | Description |
|---|---|---|
| `exportId` | Long | The ID of the export. |
| `statusUrl` | String | The URL to poll for the export result. |
| `createdAt` | Timestamp | When the export was initiated (ISO 8601, UTC). |



### [](#errors-400)Errors (400)

| Code | Description |
|---|---|
| `INVALID_DATE_RANGE` | `from` is not before `to`, or range exceeds 24 hours |
| `INVALID_INCLUDE` | Unknown dataset name in `include` |
| `EMPTY_INCLUDE` | `include` parameter is present but empty |
| `CONTACT_NOT_FOUND` | The `contact` value could not be resolved |
| `NO_CUSTOMERS_FOR_CONTACT` | Contact was found but has no associated customer records |



---

## [](#get-api-v1-export-exportid-status)GET `/api/v1/export/{exportId}/status`

Returns the current status of an export job. Once completed, includes presigned download URLs.

### [](#response-200)Response (200)

```json
{
  "exportId": 12345,
  "status": "COMPLETED",
  "createdAt": "2024-01-01T10:00:00Z",
  "downloadUrls": {
    "engagement": "https://s3.eu-..../engagements.csv?...",
    "customer": "https://s3.eu-..../customers.csv?...",
    "turn": "https://s3.eu-..../turns.csv?...",
    "review": "https://s3.eu-..../reviews.csv?...",
    "agent": "https://s3.eu-..../agents.csv?...",
    "service": "https://s3.eu-..../services.csv?...",
    "activity": "https://s3.eu-..../activities.csv?..."
  },
  "error": null
}
```

### [](#status-values)Status Values

| Status | downloadUrls | Description |
|---|---|---|
| `PROCESSING` | empty `{}` | Export is running |
| `COMPLETED` | populated | Files are ready to download (URLs valid for 1 hour) |
| `FAILED` | empty `{}` | Export failed — see `error` field |



404 — Export not found or does not belong to your account.

---

## [](#get-api-v1-export-history)GET `/api/v1/export/history`

Returns the most recent exports for your account (up to 100, limited to the last 30 days).

Response (200): Array of status objects (same shape as the status endpoint).

# [](#datasets-csv-columns)Datasets &amp; CSV Columns

## [](#engagement-engagements-csv)engagement (engagements.csv)

| Column | Type | Description |
|---|---|---|
| `pid` | uuid | Engagement ID |
| `external_id` | string | External system ID |
| `name` | string | Engagement name |
| `link` | string | Link to the engagement |
| `agent_pid` | uuid | Agent ID |
| `agent_name` | string | Agent name |
| `contact_pid` | uuid | Customer ID |
| `contact_name` | string | Customer name |
| `conversation_start_time` | timestamp | Start of the conversation |
| `start_time` | timestamp | Start of the engagement |
| `end_time` | timestamp | End of the engagement |
| `conversation_id` | uuid | Conversation ID |
| `conversation_external_id` | string | External conversation ID |
| `channel_type` | string | Channel type (CHAT, EMAIL, VOICE...) |
| `direction` | string | Inbound / Outbound |
| `status` | string | Engagement status |
| `type` | string | Engagement type |
| `outcome_type` | string | Outcome type |
| `service_level` | string | Service level |
| `terminated_by` | string | Who terminated the engagement |
| `initiated_by` | string | Who initiated the engagement |
| `resolution` | string | Resolution |
| `channel` | string | Channel name |
| `queue` | string | Queue name |
| `team` | string | Team name |
| `department` | string | Department name |
| `outcome` | string | Outcome name |
| `outcome_category` | string | Outcome category |
| `reason` | string | Reason name |
| `reason_category` | string | Reason category |
| `case_name` | string | Case name |
| `platform` | string | Platform name |
| `source` | string | Source name |
| `language` | string | Language |
| `channel_vendor` | string | Channel vendor |
| `category` | string | Category |
| `campaign` | string | Campaign |
| `priority` | string | Priority |
| `menu_path` | string | Menu path |
| `flow` | string | Flow name |
| `service` | string | Service name |
| `company_contact` | string | Company contact name |
| `brand` | string | Brand |
| `topic_category` | string | Topic category |
| `topic` | string | Topic |
| `attribute_01` — `attribute_04` | string | Custom attributes |
| `agent_location` | string | Agent location |
| `agent_role` | string | Agent role |
| `agent_organization` | string | Agent organization |
| `external_agent_name` | string | External agent name |
| `cost` | decimal | Cost |
| `engagement_time` | integer | Engagement time (ms) |
| `focus_time` | integer | Focus time (ms) |
| `hold_time` | integer | Hold time (ms) |
| `invitation_time` | integer | Invitation time (ms) |
| `menu_time` | integer | Menu time (ms) |
| `preparation_time` | integer | Preparation time (ms) |
| `wait_time` | integer | Wait time (ms) |
| `wrap_up_time` | integer | Wrap-up time (ms) |
| `total_time` | long | Total time (ms) |
| `engagement_fact_01` — `engagement_fact_03` | decimal | Custom facts |
| `wait_for_customer_time` | integer | Wait for customer time (ms) |
| `order_agent_engagements` | integer | Order of agent engagements in conversation |
| `total_conversation_agent_engagements` | integer | Total agent engagements in conversation |
| `adaptability` | decimal | AI-scored adaptability |
| `adherence` | decimal | AI-scored adherence |
| `clarity` | decimal | AI-scored clarity |
| `completeness` | decimal | AI-scored completeness |
| `customer_satisfaction` | decimal | AI-scored customer satisfaction |
| `empathy` | decimal | Legacy API field for transcript-derived empathic communication. It does not use biometric signals or infer internal emotional states. |
| `expressed_satisfaction` | decimal | AI-scored expressed satisfaction |
| `language_skills` | decimal | AI-scored language skills |
| `persuasion` | decimal | AI-scored persuasion |
| `severity` | decimal | AI-scored severity |
| `understanding` | decimal | AI-scored understanding |



## [](#customer-customers-csv)customer (customers.csv)

| Column | Type | Description |
|---|---|---|
| `pid` | uuid | Customer ID |
| `external_id` | string | External system ID |
| `name` | string | Customer name |
| `link` | string | Link to the customer |
| `type` | string | Customer type |
| `category` | string | Category |
| `segment` | string | Segment |
| `organization` | string | Organization |
| `region` | string | Region |
| `country` | string | Country |
| `state` | string | State |



## [](#turn-turns-csv)turn (turns.csv)

| Column | Type | Description |
|---|---|---|
| `pid` | uuid | Turn ID |
| `engagement_pid` | uuid | Parent engagement ID |
| `turn_time` | timestamp | Timestamp of the turn |
| `turn_time_relative_ms` | integer | Time relative to engagement start (ms) |
| `response_to` | uuid | PID of the turn this responds to |
| `participant` | string | AGENT or CUSTOMER |
| `type` | string | Turn type |
| `origin` | string | Origin |
| `category` | string | Turn category |
| `duration` | integer | Duration (ms) |
| `length` | integer | Character length |
| `sentiment` | decimal | Legacy transcript-derived sentiment indicator. It does not use biometric signals or claim to determine a person's internal emotional state. |
| `confidence` | decimal | Confidence score |
| `quality` | decimal | Quality score |
| `external_id` | string | External ID |
| `content` | string | Turn text content |
| `content_agent` | string | Agent-side content |
| `content_customer` | string | Customer-side content |
| `language_agent` | string | Agent language |
| `language_customer` | string | Customer language |
| `language_content` | string | Content language |



## [](#review-reviews-csv)review (reviews.csv)

| Column | Type | Description |
|---|---|---|
| `pid` | uuid | Review ID |
| `engagement_pid` | uuid | Reviewed engagement ID |
| `turn_pid` | uuid | Reviewed turn ID (if applicable) |
| `reviewer_pid` | uuid | Reviewer ID |
| `reviewer_name` | string | Reviewer name |
| `question_pid` | uuid | Question ID |
| `question_name` | string | Question text |
| `question_type` | string | Question type |
| `question_built_in` | boolean | Whether question is built-in |
| `question_description` | string | Question description |
| `question_business_goal` | string | Question business goal |
| `question_category_pid` | uuid | Question category ID |
| `question_category_name` | string | Question category name |
| `review_time` | timestamp | Timestamp |
| `review_session_id` | string | Review session ID |
| `status` | string | Review status |
| `sampling` | string | Sampling method |
| `type` | string | Review type |
| `kind` | string | Review kind |
| `answer_pid` | uuid | Answer ID |
| `answer_name` | string | Answer text |
| `answer_reason_pid` | uuid | Answer reason ID |
| `answer_reason` | string | Answer reason text |
| `confidence` | decimal | Confidence score |
| `score` | decimal | Score |
| `answer_score` | decimal | Answer score |
| `worst_score` | decimal | Worst possible score |
| `best_score` | decimal | Best possible score |
| `comment` | string | Reviewer comment |
| `comment_translated` | string | Translated comment |
| `comment_language` | string | Comment language |
| `comment_translated_language` | string | Translated language |
| `verified` | string | Whether verified |
| `verified_by` | string | Verified by |
| `verification_comment` | string | Verification comment |
| `answer_type` | string | Answer type |
| `version` | string | Version |
| `form_id` | string | Form ID |
| `engagement_start_time` | timestamp | Engagement start time |
| `agent_pid` | uuid | Agent ID |



## [](#agent-agents-csv)agent (agents.csv)

| Column | Type | Description |
|---|---|---|
| `pid` | uuid | Agent ID |
| `external_id` | string | External system ID |
| `name` | string | Agent name |
| `status` | string | Agent status |
| `type` | string | Agent type |
| `hourly_cost` | decimal | Hourly cost |
| `engagement_cost` | decimal | Per-engagement cost |
| `team` | string | Team |
| `department` | string | Department |
| `location` | string | Location |
| `organization` | string | Organization |
| `role` | string | Role |
| `manager` | string | Manager name |



## [](#activity-activities-csv)activity (activities.csv)

One row per activity record (agent availability / scheduled time / capacity events). When the export is filtered by `contact`, only activities linked to engagements of that customer are included.

| Column | Type | Description |
|---|---|---|
| `pid` | uuid | Activity ID |
| `external_id` | string | External system ID |
| `engagement_pid` | uuid | Linked engagement ID (nullable) |
| `interval_date` | date | Date of the activity interval |
| `order` | integer | Order within the interval |
| `type` | string | Activity type |
| `type_description` | string | Activity type description |
| `availability` | string | Availability bucket |
| `availability_description` | string | Availability description |
| `agent_status_pid` | uuid | Agent status ID (nullable) |
| `agent_status` | string | Agent status name |
| `activity_time` | integer | Activity duration (ms) |
| `consumed_capacity` | decimal | Consumed capacity |
| `available_capacity` | decimal | Available capacity |
| `scheduled_time` | integer | Scheduled time (ms) |



## [](#service-services-csv)service (services.csv)

| Column | Type | Description |
|---|---|---|
| `pid` | uuid | Service ID |
| `external_id` | string | External system ID |
| `name` | string | Service name |
| `status` | string | Service status |
| `partner` | string | Partner name |
| `partner_manager` | string | Partner manager name |
| `vertical` | string | Vertical |
| `region` | string | Region |
| `country` | string | Country |
| `tier` | string | Tier |
| `partner_size` | string | Partner size |
| `partner_tier` | string | Partner tier |
| `category` | string | Category |
| `attribute_01` — `attribute_03` | string | Custom attributes |



# [](#example)Example

The example below shows how to run the export from your console or terminal.

```bash
# 1. Start export
curl -X POST "https://api.eu.salted.cx/api/v1/export?from=2024-01-01T00:00:00Z&to=2024-01-02T00:00:00Z&include=engagement,turn" \
  -H "Authorization: Bearer YOUR_API_KEY"

# Response: {"exportId":12345,"statusUrl":"/api/v1/export/12345/status","createdAt":"2024-01-01T10:00:00Z"}

# 2. Poll status
curl "https://api.eu.salted.cx/api/v1/export/12345/status" \
  -H "Authorization: Bearer YOUR_API_KEY"

# 3. When status is COMPLETED, download CSVs from the downloadUrls
curl -o engagements.csv "https://s3.eu-....engagements.csv?X-Amz-..."
curl -o turns.csv "https://s3.eu-....turns.csv?X-Amz-..."
```

---

## Live Conversation Lifecycle

Source: https://help.salted.cx/en/articles/1756766407-live-conversation-lifecycle


Article short description

Conversation can have quite a complex structure in environments bots involvements, external agents, escalations and other processes. Learn more about how customer journey is structured in [Customer Journey Structure](https://help.salted.cx/en/articles/model-customer-journey-structure). Also check [Conversation Examples](https://help.salted.cx/en/articles/model-conversation-examples) to understand how some more complex scenarios look in the data.

## [](#engagements-in-live-conversations)Engagements in Live Conversations

Each participant (agents, external agents and Your Logic) in a life conversation creates a separate [engagement](https://help.salted.cx/en/articles/model-engagement) associated with it. Engagements and their status are critical to know whether there is somebody handling the customer.

## [](#live-conversation-properties)Live Conversation Properties

Live Conversations have the following properties:

| Property | Type | Description |
|---|---|---|
| Status | Enum |  |
| Needs Help | Boolean | `true` — The conversation will appear in [Needs help navigation section](https://help.salted.cx/en/collections/1755577083-live-conversations) in Live Conversations. `false` — The agents are not asked to join the conversation. Agents can still join conversation for example via link to a specific conversation. |
| Your Logic Working | Boolean | `true` — Your Logic is currently working on a response to an event in a live conversation. `false` — Your Logic is NOT currently working on a response to an event in a live conversation. |
| Engage Your Logic | Boolean | `true` — Salted CX will notify Your Logic about every action in the conversation. `false` — Salted CX will NOT notify Your Logic unless this flag changes. |
| Fallback to Agent | Boolean | `true` — Salted CX did not get a response from Your Logic and had to escalate to an agent as a fallback. `false` — Default state, no fallback. |



## [](#custom-conversation-lifecycle)Custom Conversation Lifecycle

Depending on you business process you might keep track of the state of the conversation. The exact states depend on you business processes and desired customer experience. The high level conversation phases may look like this (with notes on what Your Logic does in those phases):

- Greetings and customer request collection. Greeting the customer and asking them what is their issue (if they have not stated it right away). Collect additional details if the customer has not provided complete information.

- Auto responding to customer request. Providing the customer with the an automated (bot) response to their request (if possible). Your Logic should also watch whether the customer requests escalation to a human agent, handle small talk, detect and respond to requests unrelated to your business, etc.

- Agent or external agent engagement (if required). You Logic can monitor the communication and stay silent. Depending on the implementation it can also step in or take the conversation back in some cases. Your Logic should listen for agents leaving the conversation with or without resolving it and take action depending on the outcome.

- Closing conversation. Your Logic can close the conversation even when the agent handled core of the covnersation to save some agent time. You should use the opportunity to [collect customer feedback](https://help.salted.cx/en/articles/your-logic-implementation-tips#24f5d3a2a8dc803299d0d42b0bc4da6c), encourage customers to reach you again if they need something again and saying goodbye.

If Your Logic relies on keeping track of the conversation state or needs to store other data it can update [custom conversation data](https://help.salted.cx/en/articles/your-logic-actions#2575d3a2a8dc809eb20cfe5f7682e387). Salted CX will then send you your data with the following events.

![](https://media.notiondesk.so/upload/68d393c3664e6728906013.png)Example high-level state transitions in a conversation

## [](#message-live-cycle)Message Live Cycle

Each customer message goes thought multiple steps before it reaches the the agent. The same happens for messages sent form the agents.

![](https://media.notiondesk.so/upload/68d393c635e76801031787.png)

*Tags: Live Conversations, Your Logic*


---

## Universal Chat

Source: https://help.salted.cx/en/articles/universal-chat


Universal Chat enables your customers to message you from your website or application. Universal Chat is deeply integrated with Salted CX AI features, [Live Conversations](https://help.salted.cx/en/collections/1755577083-live-conversations), [Your Logic](https://help.salted.cx/en/collections/1755764337-your-logic) and [analytics](https://help.salted.cx/en/collections/1755268670-dashboards). It does its best to simplify collection of customer feedback and important metrics to help get deeper insight into both quality of the conversations and performance.

![](https://pub-6e850a88e7c944bfb05bc715893a058d.r2.dev/Articles/Live%20Conversations/Universal%20Chat/Universal%20Chat%20-%201%20-%20with%20numbers.png)

You can use Universal Chat on multiple websites and have multiple brands that have different look and feel and behavior. Check [Universal Chat Settings](https://help.salted.cx/en/articles/universal-chat-settings) to learn how to customize Universal Chat and include it in your website or application.

To use Universal Chat connected to you Salted CX account follow instructions in [Universal Chat Integration](https://help.salted.cx/en/articles/universal-chat-integration). We also recommend to go through [Your Logic Implementation Tips](https://help.salted.cx/en/articles/your-logic-implementation-tips) when implementing Your Logic to provide the best possible customer experience.

## [](#open-universal-chat)Open Universal Chat

Universal Chat takes very little space by default. It is represented by a floating chat button in the bottom right corner of the website. If users click the chat button Universal Chat automatically opens a new conversation and focus the response field ![:r1:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/cbece7ea-90d1-42be-b944-7d3a40472c0a/Circle_1.png), so the customer can immediately ask for help. If chat is not needed anymore, top right arrow button ![:r2:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/828ec6f6-6da7-41e1-ab7d-81f376318b90/Circle_2.png) collapses it.

![](https://pub-6e850a88e7c944bfb05bc715893a058d.r2.dev/Articles/Live%20Conversations/Universal%20Chat/Universal%20Chat%20-%202.png)

## [](#messages)Messages

Messages are in chat bubbles ![:r3:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/6a0e6eb2-4742-4445-80a6-8be77bab104f/Circle_3.png) with customers bubble ![:r4:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/49964e58-e0e9-40b5-b973-00c416e5d0bc/Circle_4.png) being based on brand settings color selected in [Universal Chat settings](https://help.salted.cx/en/articles/universal-chat-settings?v=24f5d3a2a8dc81f49249000c3e502787). Avatar and name ![:r5:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/a8d7fc85-01c2-4beb-ae57-18073a27a40e/Circle_5.png) (optional — toggle visibility in [Settings](https://help.salted.cx/en/articles/universal-chat-settings)) indicate whether the message was sent by a bot or by a living agent. All messages no matter from which agent or bot are sent have the same color as we do not provide the customer insight into inner workings of you contact center.

## [](#images)Images

Customers can upload images by pressing the paperclip icon ![:r6:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/22961b53-f52d-4017-87e3-e0ab43ddd029/Circle_6.png). They can always choose an image from their computer. In case the customer is using a phone or similar device they can also capture a new photo using their camera. Customers can upload multiple images at once. Limit for individual files is 10MB.

## [](#questions)Questions

Agents or Your Logic can ask the customer questions. In that case a customers receives a question and set of possible answers ![:r7:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/9e5e9e5f-9b80-4656-8d16-a78ef863eb57/Circle_7.png) they can select from.

Universal Chat enables the customer NOT to answer the question and write a free text reply. This is intentional to give the customer maximum freedom in communicating modality they prefer.

Agents can ask questions from Live Conversations. Your Logic can ask questions by using their PID in Salted CX or create ad-hod questions with custom answers that are dynamically generated.

## [](#conversations)Conversations

Universal Chat enables the customer to have multiple conversations opened in their chat session. The list of conversations, accessible from current conversation by clicking the list icon ![:r8:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/bd34cd7e-cbac-4650-9d97-2a4412a47520/Circle_8.png) on the top left, show the last message ![:r9:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/72b59471-92ba-446c-94f7-8d19849cfc6a/Circle_9.png) sent in the chat session either by the customer or by agents. Each conversation is showing how long the conversation took place as a headline ![:r10:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/39cc41d0-405c-4a91-bb9a-f1c584d8fb1a/Circle_10.png). If there is a new message in a conversation, small notification badge ![:r11:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/3ee86a8a-caf2-477b-accb-27c2e2a315ea/Circle_11.png) will show on the right side of the conversation (or in collapsed chat state, badge is shown on the floating chat button). Customers can click the conversations to open them or click Start New Conversation ![:r12:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/b6a745ee-4a40-42ab-b73a-e66d599f7442/Circle_12.png) to open new one.

![](https://pub-6e850a88e7c944bfb05bc715893a058d.r2.dev/Articles/Live%20Conversations/Universal%20Chat/Universal%20Chat%20-%203%20-%20with%20numbers.png)

![](https://www.notion.so/icons/warning_yellow.svg?mode=light)

Customers may continue even in conversation that is already completed. We intentionally offer customers maximum flexibility so they are not forced to start new conversations just to follow-up on an existing topic. Salted CX will send all the previous con

*Tags: Live Conversations, Universal Chat*


---

## Zendesk Integration

Source: https://help.salted.cx/en/articles/integration-zendesk


![](https://www.notion.so/icons/warning_yellow.svg?mode=light)

This feature is in Preview and its behavior is likely to change based on user feedback. The feature also may have lower availability and have more maintenance windows.









You can connect multiple Zendesk instances to a single Salted CX account and mix data in Zendesk with other data sources.

## [](#zendesk-data-in-logical-model)Zendesk Data in Logical Model

We translate data from all platforms into a unified [Logical Model](https://help.salted.cx/en/collections/1755206106-logical-model) that enables you to report on data from multiple platforms in the same way. We use unified concepts with unified naming and the same meaning in every platform.

As each platform has its own vocabulary and concepts we cannot adopt any single platform vocabulary. Platforms have different names for the same concepts (for example ticket, case, issue, or task for a single customer-related request). Or different platforms use the same name for different concepts (for example “Contact” means a single conversation with a customer in one platform, but it means a customer email/phone in another platform).

This article covers how Zendesk concepts translate into Salted CX concepts and vocabulary.

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

To understand Zendesk data in the Logical Model it is recommended to have a basic understanding of our Customer Journey and Logical Model. You can also check our Glossary to understand the naming and meaning of our concepts.





### [](#customers)Customers

Salted CX creates individual customers that correspond to Zendesk users. Zendesk creates users for both agents and actual customers. Every ticket associated with that use becomes part of the given customer’s customer journey. So you see all those tickets chronologically one after another.

### [](#conversations)Conversations

Each Zendesk ticket translates to one conversation.

### [](#engagements)Engagements

Zendesk does not have a built-in concept similar to engagements. We define engagement as the participation of a single agent or a service in a conversation with a customer. We use heuristics to extract a similar concept from Zendesk data.

We create engagements based on actual agent activity on the ticket. A new engagement is started when a new agent responds to a ticket or when a ticket is reopened. The engagement ends when another agent starts to engage with the customer or the ticket is resolved. The start time of an engagement is when an agent sends their first message. The end time of an engagement is when an agent sends their last message.

For example, if an agent Alice replies to a customer at 8:00 AM with one message, then Alice asks Bob for help with the customer. Bob starts to chat with the customer at 8:15 AM until 8:30 AM. Bob returns the ticket to Alice who chats with the customer from 8:45 AM to 9:00 AM and marks the ticket as resolved. Custom reaches back and Alice chats again with the customer from 10:00 AM to 10:30 AM. We create 4 engagements:

- Engagement with Alice with start time and end time 8:00 AM

- Engagement with Bob with start time 8:15 AM and end time 8:30 AM

- Engagement with Alice with start time 8:45 AM and end time 9:00 AM

- Engagement with Alice with start time 10:00 AM and end time 10:30 AM

![](https://www.notion.so/icons/warning_yellow.svg?mode=light)

Depending on your exact process and setup in Zendesk our metric Engagement Time and metrics based on it may not be reliable indicator of an agent performance. Unlike many other contact center platform Zendesk does not have a concept of an agent actively working on a ticket by accepting it which is in common cases the trigger to start counting Engagement Time. You can use metrics such as Engagements per Hour to get glimpse of the agent performance. More engagements per hour typically means agents are faster in handling them.





### [](#turns)Turns

Each individual message or email from an agent or from a customer creates a new turn associated with an engagement of the currently engaged agent.

## [](#data-not-available-from-zendesk)Data not Available from Zendesk

Different platforms provide different granularity of data and have different concepts. These features may prevent us from reporting on certain useful metrics or impose other significant restrictions.

This typically leads to inability to use certain attributes and/or metrics in reporting for the given platform. This section covers the most noticeable limitations. Remember that when one metric is affected also metrics based on that one (using the affected metric as part of their definition) are affected.

### [](#queue-engagements)Queue Engagements

Zendesk does not have a concept of queues similar to many other contact center platforms. Thus we do not create any queue engagements that typically represent waiting customers in a specific queue and enable visibility into customer movement between queues.

Affected attributes: Queue

Affected metrics: Wait Time, Queue Engagements

### [](#invitation-engagements)Invitation Engagements

Zendesk does not have a concept of inviting agents to conversations (showing agents that they can handle the customer) similar to many other contact center platforms. Thus we do not create any invitation engagements in case the agent misses or rejects the invitation to join conversations.

Affected metrics: Invitation Time, Rejected Invitations, Missed Invitations

### [](#wrap-up-time)Wrap Up Time

Zendesk does not have a concept of wrap up that agent has to perform after an engagement with a customer. Although agent can perform additional actions in Zendesk after they resolve the customer ticket this time is not tracked by Zendesk.

Affected metrics: Wrap Up Time

### [](#agent-status)Agent Status

We do not import agent activity (agent status, AUX codes) from Zendesk. This status codes are typically used for routing decisions and WFM purposes. When using Zendesk we expect you have another source for this data such as WFM or a contact center platform.

Affected metrics: Activity Time, Available Time, Unavailable Time

## [](#setup-the-integration)Setup the Integration

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

This setup requires that you have the admin role in Zendesk.





To enable integration with Zingtree follow these steps:

- Login into your Zendesk account

- [Generate](https://support.zendesk.com/hc/en-us/articles/4408889192858-Managing-access-to-the-Zendesk-API#topic_bsw_lfg_mmb) and copy the API key from the screen

- Securely share the API key and the associated username (email) with Salted

- Share base domain of your Zendesk instance → https://\[base\_domain\].zendesk.com

- Give us a few days to enable the integration for you — we will notify you once it is enabled

*Tags: Integration*


---

## Engagements in Customer Journey

Source: https://help.salted.cx/en/articles/customer-journey-engagement


Engagements in [customer journey](https://help.salted.cx/en/collections/1755250527-customer-journey) represent individual agents including bots that engage with the customer to handle their requests. Each conversation in the customer journey can have multiple engagements with different agents when there are transfers or one agent takes over work after another agent.

The engagements can overlap each other, for example when multiple agents talk to a customer during warm transfers or in a group chat scenario.

## [](#engagement-start)Engagement Start

Whenever an agent joins the conversation the customer journey shows the following header.

![](https://media.notiondesk.so/upload/6989ef727cea0374377754.png)

## [](#open-in-original-data-source)Open in Original Data Source

Click the icon in the top right corner to open the engagement in the original platform such as Amazon Connect, Salesforce, Zendesk, etc. Opening in the original data source is useful to get access to all the details and functionality provided.

## [](#engagement-properties)Engagement Properties

You can pick 3 engagement properties you would like to have visible by default at the start of the engagement ![:r1:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/cbece7ea-90d1-42be-b944-7d3a40472c0a/Circle_1.png). You can pick any engagement property available in analytics. The menu also shows values for every property of the current engagement.

![](https://media.notiondesk.so/upload/6989ef7586514300202902.png)

## [](#ask-about-engagement-and-turn)Ask about Engagement and Turn

You can ask AI anything about the engagement by typing your question into the top right corner field. Ask about is useful to understand what happened in a long engagement in a few seconds.

![](https://media.notiondesk.so/upload/6989ef7859868449730332.png)

You can choose between these types of the answer:

- Concise tries to produce as shoer answer as possible.

- Detailed tries to elaborate and provide maximum level of details including examples from the engagement.

You can ask not only about Engagement but also Turn itself. That can be helpful with longer messages.

## [](#reviews)Reviews

The engagement reviews shows whether there are any engagement-wide reviews. If there are no review engagement start bar does not contain any symbol. If the engagement has at least one review of any type then there are four circles of different colors showing what types of reviews are associated with the engagement. Full circle means that there is at least one review of the type. Empty circle means there is no review of that type.

The circles in order represent:

- Purple — Auto reviews that are generated by AI auto reviewers

- Green — Customer reviews provided by customers typically as a responses to a customer satisfaction survey

- Blue — Agent reviews provided by an engaged who handled that engagement.

- Pink — Quality assurance review provided by team leaders, supervisors and other people responsible for quality assurance.

*Tags: Customer Journey*


---

## Live Conversations Toolbar

Source: https://help.salted.cx/en/articles/1759298233-live-conversations-toolbar


Article short description

Live Conversations can contain custom buttons that are defined in the account settings. These buttons are visible in the [Live Conversations](https://help.salted.cx/en/collections/1755577083-live-conversations). Custom buttons enable agents to trigger complex actions using integration with [Your Logic](https://help.salted.cx/en/collections/1755764337-your-logic?v=24f5d3a2a8dc812a8d9a000cf49d4bf9). Agents can execute these actions without leaving Live Conversations.

## [](#customize-buttons)Customize Buttons

You can customize the buttons in Settings → Custom Actions. This screen enables you to edit buttons and change their order. You can also disable buttons without deleting them. This lets you prepare buttons for future use or remove them without deleting them, in case you need to bring them back.

![](https://media.notiondesk.so/upload/69689b898b4f3751819604.png)

When you save changes, the agents see the changes next time when they open a conversation.

## [](#button)Button 

Live Conversations can contain any number of buttons. Salted CX displays the buttons in the order they are set up. The visualization may vary by device and change over time.

| Button Settings | Description |
|---|---|
| Title | The label on the button tín the user interface. Keep it short (especially if you have more buttons) and understandable. |
| Description | Optional. Tooltip that shows to users when moving pointer over the button. You can provide more details describing what the button does. |
| Action ID | Optional. The (technical) name of the action that is triggered in [Your Logic](https://help.salted.cx/en/collections/1755764337-your-logic) when an agent presses the button. |
| Copy text | Optional. The content to copy into the user clipboard after clicking the button. |
| URL | Optional. The URL that is open in a new tab when the agent presses the button. |
| Visible To | Tells who can see the button in the user interface. Enables you to choose between internal and external agents. You can also make them visible to both. |
| Active | Enables you to show and hide the buttons from agents. |



## [](#variables)Variables

Custom buttons support these variables in Title, Description, Copy, and Link settings. The following table shows supported variables that you can use.

| Variable | Description |
|---|---|
| `Agent.FirstName` | The first name of the agent using the Live Conversations. |
| `Agent.LastName` | The last name of the agent using the Live Conversations. |
| `Agent.Name` | The full name of the agent using the Live Conversations. |
| `Conversation.custom.<path>` | Custom conversation variable. This enables you to use custom data in buttons that better integrate it with your other systems. |
| `Customer.DisplayName` | Display name of the customer who you currently have conversation with. This is typically the first name but may be other value if the first name is not known. |
| `Customer.Contacts` | Comma separated contacts associated with the customer including emails, phone and custom customer identifiers. |
| `Customer.Email` | Email associated with the current customer. We try to pick the best representative email (latest used communication channel). |
| `Customer.Emails` | Comma separated emails associated with the current customer. |
| `Customer.ID` | The current customer PID within Salted CX. |
| `Customer.Phone` | Phone number associated with the current customer. We try to pick the best representative phone number (latest used communication channel). |
| `Customer.Phones` | Comma separated phones associated with the current customer. |







## [](#actions)Actions

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

Your Logic implementation SHOULD support the action before you enable the given button, so it can act on it. Otherwise, the button execution can just do nothing or cause an error in Your Logic.





Actions enable the execution of complex operations from within Live Conversations. Salted CX does not know what the action does; it just triggers a [Your Logic event](https://help.salted.cx/en/articles/your-logic-requests#2705d3a2a8dc808ba1b4c2175950f837). What the action actually performs depends on your implementation.

Actions only contain the name of the action. You cannot use variables in the action name. However, as with all Your Logic events, Salted CX sends all context information related to the current conversation. So Your Logic should have all the details necessary to perform the action.

We recommend that Your Logic provide feedback on performing an action, such as sending a message to a customer, saving a note for agents, etc.

## [](#urls)URLs

URL enables opening a new browser tab or window on the provided address. You can use variables to point to the exact item in your systems, such as `https://myoldcrm.com/search?{Customer.Name}` or `https://crm.company.com/customers/{Customer}` .

---

## Quality Assurance Metrics

Source: https://help.salted.cx/en/articles/1755246584-quality-assurance-metrics


The goals of quality assurance and the quality assurance process are different for every company. You might want to search for many different behaviors, issues, and opportunities in conversations depending on your current business goals.

This article focuses on the high-level metrics that are relevant for any quality process in any company. You want to watch those no matter the specific use case to ensure you are using your time and resources efficiently.

## [](#feedback-loop-duration)Feedback Loop Duration

The time it takes from a moment when something actionable happens in a conversation until it can be acted on. For example:

- An agent is providing inaccurate information to the customers. How long does it take from the moment when the agent first provides that information until the agent is made aware that the information they provide is not accurate and starts providing up-to-date information? This example can be used for any behavior that requires talking to an agent.

- The process causes customer frustration because an agent cannot help the customers. How long it takes from the first customers who are frustrated by the process until that process is fixed or at least the company is aware that it needs to be fixed.

The short feedback loop is important for these reasons:

- Minimize blast radius. A shorter time to resolve the issue reduces the number of conversations affected by it. Whether the cause for the issue is an individual agent a process or a structural issue.

- Agents respond better to timely feedback. When agents still remember the specific conversation. Any feedback feels less abstract and they can easily connect it to real-life situations.

Salted CX has data loads in 15-minute time intervals which enable you to do reviews during the day on conversations that happened a few minutes before the review. All review results are visible in dashboards after the next 15-minute load interval. Use these features to focus on the latest conversations and give everybody else in the company feedback during the day.

## [](#review-coverage)Review Coverage

The percentage of engagements is reviewed by a person. It is important to balance the review coverage with invested effort. For detailed reviews, the industry standard is commonly around 1% of conversations that get a review. This percentage may be much higher for a specific subset of conversations — for example when ensuring compliance is critical in those conversations.

Higher review coverage means that you have a higher chance of uncovering a situation you need to act on. Review coverage is simple to calculate but needs to be treated carefully as it might be expensive and inefficient and has diminishing results unless targeted on specific conversations.

There are several ways to increase the review coverage:

- Increase the number of people doing reviews. This is an obvious method to increase the review coverage. We mention it for completeness. Typically you should focus on doing more with fewer people to provide good value for money.

- Involve people from other departments in reviews. This is similar to the previous one with the exception that there might be synergies where people use their time to help both departments. Are other stakeholders interested in how customers, talk about their product? Is the customer experience department interested in why some customer journeys do not end well? Does your AI/ML team need annotated data? Let them collaborate on customer journeys and provide their reviews and tags. These can help you better understand what other departments expect from the customer journeys and decide what to focus on next.

- Read conversations chronologically as they happen. Often legacy quality assurance is driven by the need to answer questions in a form. This leads to revising

- Provide only actionable feedback. In legacy quality assurance you often have to respond to many questions in a form in case nothing exceptional happens. If agents are trained appropriately the number of such cases should be a vast majority.

- Use short and very focused forms. Based on the selection criteria for the conversations above use forms that are designed for the issues that you are most likely to encounter and do not contain unrelated, rarely encountered tags and questions. This makes it easier to navigate the form.

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

The goal should rarely be to review 100% of conversations unless it is a very specific subset of conversations that are critical to review. The ideal aspiration scenario is to review 100% only of conversations that are “worth reviewing” — they contain something that you can act upon. However, this is difficult to measure in most cases.





## [](#actionable-findings-per-effort)Actionable Findings per Effort

The number of actionable things you have uncovered for the effort you have invested. Ideally, you would be also able to express the value of the findings but that might not always be straightforward or possible to do accurately. Effort is typically expressed by the time necessary for doing the manual reviews.

You can recognize actionable findings very easily by the fact that you know where to go and what to do about it — such as going to an agent and telling them to change their behavior, going to the product department and telling them what issues customers recently encountered with their product, etc.

The ways to increase actionable findings per effort:

- Focus on conversations that have a higher probability of having actionable issues or opportunities based on metadata. For example conversations with excessive hold time, poor customer satisfaction, findings by AI in conversation content, etc.

- Use short and very focused forms. Based on the selection criteria for the conversations above use forms that are designed for the issues that you are most likely to encounter and do not contain unrelated, rarely encountered tags and questions. This makes it easier to navigate the form.

## [](#alignment-with-customer-expectations)Alignment with Customer Expectations

In most cases, you want to have at least some quality aspects aligned with the customer’s expectations. So if customers consistently express low customer satisfaction with an agent but your quality process shows that the agent is doing great in customer experience-related questions you need to check the quality process.

Issues with misalignment between customer satisfaction and quality:

- On individual engagement level. The customer provided feedback after an engagement. At the same time, the engagement was reviewed by a person and was reviewed with a different outcome. The best next step is to look into the customer journey to decide whether the quality assurance process worked as expected or not.

- On average for agent, team, queue, or other aggregated level. If you provide quality reviews consistently with customer satisfaction on individual engagement level but you see the difference when looking for an example on agent performance the cause is likely in the sample that you are selecting. The sample may not be large enough or it may not be random — which may be intentional if you are focusing on conversations that are potentially problematic.

Note that customer satisfaction may be influenced by many factors, some are out of your control and there are some you might not be aware of. It would be very rare to be able to understand and address every single misalignment between your customers and your perspective. Always consider the scale on which the misalignment happens for the decision of whether to focus on it.

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

Customer satisfaction might not be aligned with all the quality questions you try to answer. Customers for example might not be necessarily concerned or aware of the regulations you have to follow. So make sure you compare those quality questions that should be related to the customer experience.





## [](#do-not-review-unnecessary)Do Not Review Unnecessary

For every case you use manual reviews for you should always consider these two options:

- Another data source already contains the information. In some instances, you might be reviewing manual reviews to find information that is already available. Or even when it is not available for every conversation it might be available for a large enough sample that manual reviews are unnecessary or their scope can be much smaller.

- AI can do the job with acceptable accuracy. Depending on the use case you can use AI to review 100% of conversations. You need to provide feedback in case the AI is inaccurate which significantly minimizes scope.

---

## Service availability and SLA

Source: https://help.salted.cx/en/articles/1755264459-service-availability-and-sla


Salted CX powers your contact center across voice and digital channels. This page explains our service availability commitments and what to expect when a service interruption occurs.

## [](#our-availability-commitment)Our availability commitment

| Service level | Availability commitment |
|---|---|
| Standard | 99.9% |
| With a support contract | 99.99% |



Availability is measured over each calendar month for the production services covered by your agreement.

Your agreement specifies the applicable service level and any additional terms.

## [](#what-the-sla-covers)What the SLA covers

The SLA covers the Salted production services included in your subscription. Depending on your deployment, these may include:

- Conversation handling: Salted services for receiving, managing, and sending conversations across your configured channels.

- Agent Desktop: the workspace your team uses to access and handle conversations.

- AI Agents: Salted services supporting automated conversations and collaboration between AI and human agents.

- Quality Intelligence and Conversation Intelligence: the services used to review and analyze conversations.

Coverage follows the services you use, whether you run your contact center on Salted or use selected Salted capabilities alongside an existing platform.

## [](#how-availability-is-measured)How availability is measured

Availability is the percentage of time a covered service is operational during the calendar month, after applying the exclusions defined in your agreement.

Monthly availability = (eligible minutes − downtime minutes) ÷ eligible minutes × 100

An interruption counts as downtime when a covered service cannot perform its core function for your production environment. An incident affecting one channel or service is assessed against that affected service; other services remaining operational does not erase the interruption.

Availability, processing speed, and support response time are different measures. Any additional commitments for processing times or support responses are specified separately in your agreement.

## [](#connected-services-and-customer-managed-systems)Connected services and customer-managed systems

Your contact center may also depend on telecommunications carriers, messaging networks, identity providers, business systems, or automation you operate yourself.

An interruption originating in a customer-managed system or an external service outside the agreed Salted service boundary may fall outside this SLA. Any exclusion applies only to the impact caused by that system, as defined in your agreement.

The service boundary is particularly relevant when you bring your own carrier, AI provider, or automation infrastructure.

## [](#maintenance-and-incident-updates)Maintenance and incident updates

We plan maintenance to minimize disruption to your operation. When maintenance is expected to affect availability, we communicate the affected services, expected impact, and planned timing in advance.

Our status page provides updates on service incidents and scheduled maintenance. Your agreement defines how planned maintenance is treated in the availability calculation.

If you experience an issue, contact Salted support through your agreed support channel. Include when the issue started, the affected channel or service, and relevant examples so we can investigate.

## [](#support-and-sla-remedies)Support and SLA remedies

Customers with a support contract receive the 99.99% availability commitment. Support coverage, response times, and escalation procedures are defined in that contract.

If you believe we have missed your availability commitment, contact support to request an SLA review. Any applicable service credits, eligibility requirements, and claim deadlines are governed by your agreement.

---

## Twilio Flex Integration

Source: https://help.salted.cx/en/articles/integration-flex


![](https://www.notion.so/icons/warning_yellow.svg?mode=light)

This feature is in Preview and its behavior is likely to change based on user feedback. The feature also may have lower availability and have more maintenance windows.









You can connect multiple Twilio Flex instances to a single Salted CX account and mix data with other contact center platforms, other data sources and upload additional data using our Ingest API.

## [](#integration-between-twilio-flex-and-salted-cx)Integration between Twilio Flex and Salted CX

![](https://www.notion.so/icons/warning_yellow.svg?mode=light)

Transcripts are available for messaging channels only. Calls are available for playback in the customer journey without transcript.





We combine two data sources from Twilio to reconstruct customer journeys, conversations and turns (messages) in Salted CX:

- Twilio Event Stream

- Programmable Chat (Conversation API)

### [](#configure-event-stream)Configure Event Stream

In the following steps you will ask Twilio to send important events from your contact center to Salted CX:

1. In Twilio Console go to Event Stream ⏵ Manage ⏵ Create Sink

2. Choose sink Type: Amazon Kinesis Data Stream

3. Request from Salted CX team Amazon Resource Name (ARN), External ID and Role ARN

4. Fill those information provided by Salted CX

5. Click Finish setup

6. In Twilio Console go to Event Stream ⏵ Manage ⏵ Create Subscription

7. Select the Sink created in step 5

8. Use description to ensure people know what the subscription is for, for example “Integration with Salted CX”

9. Select all events with the latest schema version from the TaskRouter section EXCEPT RateLimit (all events from reservation, task, task qeuues worker and workflow)

### [](#create-api-key)Create API Key

In this step you will generate token that Salted CX can use to extract data:

1. In the right top corner click on Admin ⏵ Account Management

2. Keys &amp; Credentials ⏵ API keys &amp; Tokens ⏵ Create API Key

### [](#provide-account-information-to-salted-cx)Provide Account Information to Salted CX

Pass the following information securely to Salted CX team:

- Account SID

- API key SID and secret

## [](#twilio-flex-data-in-the-logical-model)Twilio Flex Data in the Logical Model

We translate data from all platforms into our unified Logical Model that enables you to report on data from multiple platforms in the same way. We use unified concepts with unified naming and the same meaning in every platform.

As each platform has its own vocabulary and concepts we cannot adopt any single platform vocabulary. Platforms have different names for the same concepts (for example queues, case, issue, or task for a single customer-related request). Or different platforms use the same name for different concepts (for example “Contact” means a single conversation with a customer in one platform, but it means a customer email/phone in another platform).

This article covers how Twilio Flex concepts translate into Salted CX concepts and vocabulary.

💡

To understand Twilio Flex data in the Logical Model it is recommended to have a basic understanding of our Customer Journey and Logical Model. You can also check our Glossary to understand the naming and meaning of our concepts.





Salted CX uses TaskRouter tasks to read details about agents activities and reservations. We gather information from the tasks attributes and map them into the Salted CX Logical Model

### [](#customers)Customers

Salted CX creates individual customers that correspond to task attributes that are relevant to the customer identification.

| Salted CX | Task Attribute |
|---|---|
| Customer Contact ID | task\_attributes.customers.external\_id task\_attributes.customers.phone task\_attributes.customers.email task\_attributes.from / to (depends on direction) task SID |
| Customer State | task\_attributes.customers.state |
| Customer Country | task\_attributes.customers.country |
| Customer Category | task\_attributes.customers.category |
| Customer Organization | task\_attributes.customers.organization |
| Customer Region | task\_attributes.customers.region |
| Customer Segment | task\_attributes.customers.segment |



Customer ID is taken from the multiple objects based on priority as mentioned in the table above. If no information about the customer is in the task then the customer is created with task SID which keeps the conversation isolated. That’s why it’s recommended always to populate any contact information into the task attributes.

### [](#agents)Agents

Salted CX gather the agents’ information from the worker attributes that are part of the events that are generated when an agent changes the activity (ie. Offline &gt; Available).

| Salted CX | Worker Attribute |
|---|---|
| Agent ID | email |
| Agent Name | full\_name |
| Agent Department | department |
| Agent Location | location |
| Agent Manager | manager |
| Agent Team | team agent\_team |
| Agent Roles | roles |
| Agent Organization | organization |
| Agent Cost per Hour | cost\_per\_hour |
| Agent Cost per Engagement | cost\_per\_engagement |



Agent State is set to ‘Active’ when the worker is created and ‘Inactive’ if deleted.

Agent Role is set to the the highest permission (admin &gt; supervisor &gt; agent).

### [](#agent-status)Agent Status

Activity is a detailed agent status change (AUX codes) during the day including attribution to time. Each item in the Activity data set represents a sum of time spent in a single agent status (AUX code) in a 15-minute interval.

Offline Activity is not being stored in Salted CX.

### [](#conversations)Conversations

Each TaskRouter task translates to one conversation.

### [](#agent-engagement)Agent Engagement

Twilio Flex uses TaskRouter for assigning tasks and reservations to agents. Salted CX translates a reservation into the engagement which means that there can be multiple engagements in one conversation.

Agent engagement starts with the event of reservation accepted and ends with reservation completed.

| Salted CX | Task Attribute |
|---|---|
| Campain | task\_attributes.conversations.campaign |
| Case | task\_attributes.conversations.case |
| Category | task\_attributes.conversations.category |
| Channel | task\_attributes.conversations.channel task\_channel\_unique\_name (name of the channel in Taskrouter) |
| Channel Vendor | “Twilio” |
| Company Contact | task\_attributes.conversations.company\_contact task\_attributes.conversations.external\_contact task\_attributes.from / task\_attributes.to (based on direction) |
| Conversation | task\_attributes.conversations.conversation\_jd task SID |
| Direction | task\_attributes.conversations.direction task\_attributes.direction ’Inbound’ |
| Engaged Department | worker\_attributes.department |
| Engaged Location | worker\_attributes.location |
| Engaged Organization | worker\_attributes.organization |
| Engaged Manager | worker\_attributes.manager |
| Engaged Role | worker\_attributes.role |
| Engaged Team | worker\_attributes.team worker\_attributes.agent\_team |
| Engagement Attribute 1 | task\_attributes.conversations.attribute\_1 task\_attributes.conversations.conversation\_attribute\_1 |
| Engagement Attribute 2 | task\_attributes.conversations.attribute\_2 task\_attributes.conversations.conversation\_attribute\_2 |
| Engagement Attribute 3 | task\_attributes.conversations.attribute\_3 task\_attributes.conversations.conversation\_attribute\_3 |
| Engagement Fact 1 | task\_attributes.conversations.fact\_01 |
| Engagement Fact 2 | task\_attributes.conversations.fact\_02 |
| Engagement Fact 3 | task\_attributes.conversations.fact\_03 |
| Engagement Time | Duration between reservationAccepted and reservationWrapup |
| Engagement Type | “Agent” |
| Focus Time | task\_attributes.conversations.focus\_time |
| Hold Time | task\_attributes.conversations.hold\_time |
| Invitation Time | Duration between reservationCreated &lt;&gt; reservation Rejected/Revoked/Accepted/Missed/Cancelled |
| Language | task\_attributes.conversations.language |
| Outcome | task\_attributes.conversations.outcome |
| Outcome Category | task\_attributes.conversations.outcome\_category |
| Platform | “Flex” |
| Priority | task\_attributes.conversations.priority |
| Queue | task\_attributes.conversations.queue task\_queue\_sid / task\_queue\_name |
| Reason | task\_attributes.conversations.reason |
| Start Time | reservation.accepted timestamp |
| End Time | reservation.completed timestamp |
| Wait Time | Duration between the last queue.entered and reservation.accepted events |
| Wrap Up Time | Duration between reservation.wrapup and reservation.completed |



If the channel unique name is `voice` (default Twilio naming) then we also gather task\_attributes.conversations.sgement\_link with an URL to the recording so the audio file can be re-played in the customer journey.

If there is not wrapup event configured then the wrap up time is not populated.

### [](#queue-engagement)Queue Engagement

The queue segment always starts with TaskRouter event `queue.TaskQueueEntered`.

The queue segments have the same attributes as the Agent Engagements but they have a different outcome type in Salted CX model based on the ending event:

| Ending Event Name | Outcome Type | Usage |
|---|---|---|
| ReservationAccepted | Accepted | For such queue segments we also create agent engagements so all reporting can be done with this engagements where you will have populated waiting time, engagement time, invitation time and wrap up time (if wrap up exists) |
| TaskQueueEntered | Moved | Such queue engagements represent transfers from queue to another queue |
| TaskDeleted | Deleted | Such queue engagements represent deleted task |
| TaskCanceled | Customer Left Canceled | If the ending event is TaskCanceled then it depends on the Taskrouter value for field task\_canceled\_reason that is populated automatically by Twilio Taskrouter. If it’s ‘hangup’ then we populate ‘Customer Left’ and it represents abandoned conversations. If it’s ‘Task canceled on Workflow timeout’ then the task was ended due to timeout configuration in your Taskrouter Workflow settings. |



### [](#invitation-engagement)Invitation Engagement

The invitation engagements represent situations in which agents receive a reservation (invitation to join a conversation) but they miss it or reject it. Salted CX does not create invitations for instances when agent accepts the reservation. The invitation engagement starts with the event `reservation.created`.

The invitation engagements are mapped to the same attributes as the Agent Engagements but they have a different outcome type in Salted CX model based on the ending event:

| Ending Event Name | Outcome Type | Usage |
|---|---|---|
| ReservationAccepted | —- | We do not create invitation engagement because we have already all information in agent engagement. |
| ReservationTimeout ReservationCanceled | Missed | Such invitation engagements can be used to see how many reservations were missed by agent due to timeout configured in the Taskrouter workflow |
| ReservationRejected | Rejected | Such invitation engagements can be used to see how many reservations were actively rejected by the agents. |
| ReservationRescinded | Revoked | Such invitation engagements represent reservations that were closed because another agent already accepted the task’s reservation. Such scenario can happen if multiple reservations are created for one task (can be configured in Twilio Taskrouter queue setting) |



### [](#turns)Turns

Each individual message in the channel from an agent or from a customer creates a new turn associated with an engagement of the currently engaged agent. The current deployment is configured to download chat transcripts via Twilio Conversation API.

*Tags: Integration*


---

## Webex CC Integration

Source: https://help.salted.cx/en/articles/integration-webex


Connect Cisco Webex Contact Center to Salted CX. Covers supported features, how Webex CC Tasks, engagements, and turns map to the Salted customer journey, available metrics, OAuth setup, and limitations.

Webex Contact Center is Cisco's cloud-based omni channel contact center platform. It routes inbound customer interactions — voice calls, chats, emails, and social messages — to agents based on configurable routing strategies. A unit of work routed to an agent is called a Task.

You can connect multiple Webex CC instances to a single Salted CX account and mix data from Webex CC with other data sources.

## [](#supported-features-in-webex-cc)Supported Features in Webex CC

- Reporting on agent session activity — tracking when agents are logged in, their state (Available, Idle, Busy, Wrap Up), and time spent in each state.

- Reporting on contact (Task) handling — including inbound calls, chats, emails, and other channel interactions routed through Webex CC.

- Reporting on queue activity — understanding traffic volumes, wait times, and abandoned contacts.

- Downloading call recordings — storing telephony recordings in Salted storage for post-call analytics and quality management.

## [](#customer-journey)Customer Journey

Salted CX translates the following entities in Webex CC to corresponding items in the customer journey. It is useful to learn about [Customer Journey Structure](https://help.salted.cx/en/articles/model-customer-journey-structure) to better understand how Webex CC objects translate to Salted CX concepts.

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

Salted CX enables merging traffic from multiple vendor platforms into a single storage. Each supported platform has a different vocabulary and concepts. Salted CX introduces its own concepts unified across supported platforms that strive to balance ease of use and flexibility. Check [Logical Model](https://help.salted.cx/en/collections/1755206106-logical-model) and [Customer Journey Structure](https://help.salted.cx/en/articles/model-customer-journey-structure) to understand key concepts in Salted CX. Depending on the quality of data available in individual supported platforms there are platform-specific exceptions and limitations that we cover in articles dedicated to individual platforms





| Concept in Salted | Objects in Webex CC |
|---|---|
| Customer | No customer identification via Webex CC |
| Contact | Contact. Depending on the channel, the customer's email or phone number is used both as the unique contact identifier and as the customer attribute that groups multiple contacts together. |
| Conversation | Not supported in Webex CC. Individual Tasks are not grouped at a higher level. |
| Engagement | A Task in Webex CC. Each Task represents a single customer interaction from arrival to completion. A Task produces multiple Contact Activity Records (CAR) as it moves through the contact center — IVR, queue, connection, and wrap up. Salted maps each CAR to an engagement. |
| Turn | Individual messages are extracted from the complete chat transcript. The transcript is stored as individual JSON objects. |
| Review | Not supported in Webex CC. |



## [](#engagements)Engagements

Engagements represent the individual handling segments of a customer Task. A single Task typically produces multiple Engagements as it moves through the contact center — from entry point through queue to agent handling

| Engagement Type | Description |
|---|---|
| Agent | Created for every Task segment where an agent actively handled the customer. This is the primary engagement type for agent performance reporting. Maps to a Contact Activity Record (CAR) with activity type Connected. |
| Invitation | Created when a Task is offered to an agent but the agent misses or rejects it (RONA — Redirect on No Answer). Enables identification of overloaded agents or routing issues. |
| Menu | Created for the time a Task spends in the Webex CC Flow (IVR) before reaching a queue. Useful for understanding self-service rates and flow drop-off. |
| Queue | Created for the time a Task spends waiting in a queue before being connected to an agent. Used to measure wait times and queue traffic volumes. |



![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

A typical handled Webex Task creates at least three engagements: one with Engagement Type = Menu for the IVR part, a second with Engagement Type = Queue, and a third with Engagement Type = Agent. When you create metrics or count engagements, make sure you focus on the right type so you do not double-count.





## [](#turns)Turns

### [](#voice)Voice

A stereo audio recording file is downloaded via the Captures API. Agent and customer audio are stored as separate channels, enabling accurate voice analytics. The file is stored in Salted secure storage after download.

### [](#chat)Chat

A structured transcript is downloaded via the Captures API. Individual messages between the agent and customer are extracted from the transcript and stored as separate turns.

### [](#email)Email

Individual email messages in the thread are downloaded via the Captures API. Each message, inbound from the customer or outbound from the agent, produces a separate turn.

## [](#metrics-overview)Metrics Overview

This section covers the base metrics available from Webex Contact Center. These metrics are derived from the Contact Session Records (CSR), Contact Activity Records (CAR), and Agent Session Records (ASR), and are used as the basis for further calculations.

| Metric | Description |
|---|---|
| Agent Engagements | Number of Tasks in which an agent was connected and handled the customer. Excludes Tasks abandoned before reaching an agent. |
| Available Time | The total time an agent spent in the Available state — ready to receive interactions. Derived from Agent Session Records. |
| Engagement Time | The time from when an agent accepted a Task (connected) to when the Task was completed or transferred. Equivalent to Handle Time excluding wrap up. |
| Menu Time | The time a Task spends in the Webex CC Flow (IVR) before entering a queue or being abandoned. |
| Invitations | Number of Tasks offered to an agent that were missed or rejected (RONA). A high invitation count relative to agent engagements may indicate routing or staffing issues. |
| Missed Invitations | Number of Tasks not answered by an agent within the configured RONA timeout. |
| Queue Engagements | Total number of Tasks that entered a queue, including those abandoned before being answered. Represents actual traffic into the queue. |
| Wait Time | The time a Task spends in a Queue before being connected to an agent. Also referred to as Queue Time. |
| Wrap Up Time | The time an agent spends in the Wrap Up (After Call Work) state following a Task. The agent is not available for new interactions during this period. |



## [](#historical-data)Historical Data

Webex Contact Center retains historical data for up to 13 months. Data older than 13 months is not available via the Search API and cannot be backfilled.

## [](#customer-survey)Customer Survey

Webex CC has no native concept of customer feedback, CSAT or reviews. The Reviews concept in Salted CX is therefore not supported for this integration. Most organizations using Webex CC collect customer feedback via third-party tools. If customer survey data is required in Salted CX, a separate integration with the survey platform would need to be built.

## [](#setup-the-integration)Setup the Integration

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

This setup requires that you have the admin role in Webex CC.





This guide walks a Webex Contact Center administrator through the steps required to register a third-party application and generate the credentials it needs to access your Webex CC data via the API. All steps are performed by the administrator — the third-party application only needs to provide the list of permissions (scopes) required.

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

Note: This process uses the standard OAuth 2.0 authorization flow. You will register the integration in the Webex Developer Portal, then complete a one-time browser login to generate a refresh token. The third-party application uses this token to access data on an ongoing basis without requiring further involvement from you — unless the token needs to be regenerated.





To enable integration with Webex CC follow these steps:

1. Log in to [https://developer.webex.com](https://developer.webex.com/) using your admin account. Navigate to My Apps → Create a New App → Integration.Fill in the following:
    
    
    - Integration Name — a descriptive name, e.g. "Salted CX Integration"
    
    
    - Redirect URI - use Postman’s standard callback URL `https://oauth.pstmn.io/v1/callback` or localhost
    
    
    - Scope: choose the following
    
    | Permission (Scope) | What It Allows |
    |---|---|
    | `cjp:config_read` | Gives access to read data using many of the Customer Experience APIs |
    | `spark:people_read` | Provides read access to your users' company directory |
    | `cjp:task_read` | Gives read access to contact center task data |
    
    
    
    Once saved, the Developer Portal will generate a Client ID and Client Secret. The Client ID is always visible under the integration. The Client Secret is only shown once — copy and store it securely before leaving the page.

2. Complete the OAuth Flow (i.e. in Postman) using Client ID, Client Secret and Scopes selected before. The video guide provided by Webex CC <https://app.vidcast.io/share/e2fc878b-9294-4830-86a5-38c77fcc5093>. You need to log in using your Webex CC admin account to complete the authentication.

3. Share the credentials with Salted CX. Share the following four items securely with the third-party application:| Item | Where You Got It |
    |---|---|
    | Client ID | Developer Portal → My Apps |
    | Client Secret | Developer Portal → My Apps |
    | Refresh Token | Response from OAuth flow |
    | Data Center | Control Hub → Account → Data Locations |

### [](#token-renewal)Token Renewal

The refresh token is valid for 90 days and automatically resets each time it is used. As long as the integration is actively running, no manual renewal is required.

If the integration is inactive for more than 90 days, the refresh token will expire. To restore access, repeat Step 2 and share the new refresh token with the third-party application.

## [](#limitations)Limitations

Webex CC enforces limits on [API calls](https://developer.webex.com/webex-contact-center/docs/rate-limiting) that influence how much data can be loaded from Webex CC in a given time frame. These limits typically do not affect incremental loads, as these loads pull only a small volume of data.

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

If the contact center experiences an unusually high volume of interactions in a given 15-minute window (e.g., during a major incident or campaign), the load for that period may take longer to complete. Salted CX will process the backlog in subsequent load cycles without data loss.

*Tags: Integration*


---

## Review Metrics

Source: https://help.salted.cx/en/articles/metrics-review


Reporting on reviews give you visibility into feedback that you and your agents receive for conversations they have engaged with. Reviews cover both human and AI feedback.

## [](#before-you-start)Before You Start

This article covers details of creating metrics on top of the [Logical Model](https://help.salted.cx/en/collections/1755206106-logical-model). It is useful to have understanding of these areas:

- Logical Model helps you understand how reviews relate to the rest of the data in Salted CX.

- [Review](https://help.salted.cx/en/articles/model-review) data set provides details what attributes and facts are available fro individual reviews.

- Custom metrics cover basics for how to write a custom metric within Salted CX.

- Metrics reference contains list of built-in metrics that you might consider using without having to write your own, or metric you can reuse in your own metrics.

## [](#review-type-and-status)Review Type and Status

Ensure that you filter metrics to the review type you are interested in. You can combine Auto Reviews with Manual Reviews for example but you should know why you are doing it.

| Type | Description |
|---|---|
| Agent | Review provided by the agent on their engagements. This type of review enables you to gather the agent's perspective. |
| Auto | The review was provided by an automated service. |
| Customer | The review was provided by the customer. This is typical for customer journeys. |
| Reviewer | The review was provided by a person responsible for quality assurance in the company. This person is different from the agent who handled that engagement. |







Review have status in Salted CX to enable reporting for planned reviews, customer surveys without answers, cases in which a reviewer rejected to review, etc. Use statuses in metric definitions to ensure only the expected reviews are counted.

| Status | Description |
|---|---|
| Completed | The review is completed and it can be included in the reports. |
| Deleted | The review was deleted and should not be in the results. |
| Ignore | The review is not relevant. |
| Pending | The review is scheduled but the reviewer has not answered yet. This may happen in case you have planned reviews that reviewers should do and you want to report on those that are yet to be done. |
| Rejected | The reviewer rejected to review the engagement. This may happen in case that the reviewer concludes that the engagement is not a good representative sample to review. |
| Timeout | The review was requested but the reviewer has not provided it. This may happen when reviewers did not have time to review or for customer reviews the customers simply choose not to answer. |







Example of a custom metric that counts number of engagements that have manual or auto reviews that are completed. The reviews have to be to the question “Knowledge Gap” and “Inaccurate Information”.

```plain
SELECT COUNT(Engagement) 
	WHERE Review Type IN ("Auto", "Reviewer") 
		AND Review Status IN ("Completed")
		AND Question Name IN ("Knowledge Gap", "Innacurate Information")
```

## [](#answer-score-versus-score)Answer Score versus Score

Each [Review](https://help.salted.cx/en/articles/model-review) in Salted CX has two scores:

- Answer Score — The score in the original rating scale. Use this only when you know that all questions in a metric use the same rating scale.

- Score — The Answer Score normalized to percentages in the range from 0% to 100%. This enables you to include a score from multiple questions with different rating scales into a single metric.

Examples of Answer Score versus Score for selected question types:

|  | Answer | Answer Score | Score |
|---|---|---|---|
| NPS (0 to 10) | Detractor | 0 | 0% |
| NPS (0 to 10) | Detractor | 1 | 10% |
| NPS (0 to 10) | Passive | 7 | 70% |
| NPS (0 to 10) | Promoter | 10 | 100% |
| Five Stars (1 to 5) | ★☆☆☆☆ | 1 | 0% |
| Five Stars (1 to 5) | ★★★☆☆ | 3 | 50% |
| Five Stars (1 to 5) | ★★★★★ | 5 | 100% |



## [](#engagement-level-review-results)Engagement Level Review Results

In some reports, you might want to show the review score in a table on the same line as the engagement without having each review on a separate line. See the table below as an example:

![](https://media.notiondesk.so/upload/698d916ddb3d8175106781.png)

As there might be multiple reviews on a single engagement (even for the same Question by different reviewers), it is not possible to represent it by a single number without telling Salted CX how to reduce potential multiple reviews into a single number. You need to decide what aggregation function you want to use and either use a built-in metric or create your own.

```plain
SELECT MIN(Score) WHERE 
	Question IN ("How would you rate the agent?") 
	AND Review Status IN ("Completed")
```

Example metric that takes minimum score for the given question which will show the lowest value in the list of engagements|  | Usage |
|---|---|
| Minimum | Use the minimum `MIN` aggregation function to highlight potential issues that need attention. This is typically what you would like to do. |
| Average | Use the average `AVG` aggregation to get a “fair” assessment of an engagement. Always make sure you include only reviews you really want so for example negative feedback from customers is not masked by very positive feedback from agents and reviewers. |
| Median | Median has limited use at the engagement level. The median is typically useful on larger data samples rather than a few reviews associated with a single engagement. |
| Maximum | Use the maximum `MAX` aggregation to highlight exceptional performance. Always make sure you include only reviews you really want so for example negative feedback from customers is not masked by very positive feedback from agents and reviewers. Most dashboards and visualizations are unlikely to use maximum aggregation as it is intended for specific use cases. |



![](https://www.notion.so/icons/warning_yellow.svg?mode=light)

If you do not filter a metric, a visualization or a dashboard to a specific [Question](https://help.salted.cx/en/articles/model-question) that has responses on the same rating scale strongly consider using Score fact. Score fact normalizes different rating scales to range between 0% and 100%. If the questions have different rating scale the average number is not an actionable figure.

---

## Asynchronous Behavior in Your Logic

Source: https://help.salted.cx/en/articles/your-logic-asynchronous


During conversations, participants do not have to always wait for each other. For example, while the agent is typing a message, the customer can provide additional context, ask more questions, encourage the agent to respond faster, etc. The same may happen for Your Logic no matter how fast it is.

Salted CX tries to reduce complexity for Your Logic while giving you control over how you process individual events in the conversations.

## [](#receiving-events-from-salted-cx)Receiving Events from Salted CX

Every action that is worth processing can be intercepted by Your Logic. Because Your Logic may perform time-consuming operations, the participants may send more messages (or perform other actions) before Your Logic manages to respond to the first message.

This asynchronous communication is very similar to how people communicate. When somebody texts you a question, you are composing a message to clarify the question, but just as you send your message, another text arrives. This can make your reply irrelevant. These things happen and are natural. It is important that Your Logic is ready for it.

![](https://media.notiondesk.so/upload/68d247ca837dc495464868.png)

The flow above would produce 2 or 3 requests to Your Logic, depending on how you handle them. Notice that while Your Logic is busy responding to the first message, the customer sends two more messages. The example could be something like this:

> Hello

> I would like to rebook the trip to sometime next week

> I was thinking about Thursday or Friday.

### [](#request-versus-current-state)Request versus Current State

Salted CX sequences the incoming messages (and all other actions) in each conversation, so you receive all individual requests for each event that happens unless you tell Salted CX you do not want to get them.

| Property | Description |
|---|---|
| Request Time | Time when the request is sent to Your Logic. Salted CX sends you complete state of the current conversation as of this time including turns and other changes following the trigger that caused this. Your Logic is free to process these “future” updates as a response to this request or wait for a request in the future. |
| Expiration Time | Time until when Your Logic has time to respond. After this time expires Salted CX behaves as if Your Logic was not available. It also unblocks a next request in the queue. The length of this window is configurable per account (the platform default is 150 seconds); the examples below use a shortened 15-second window for brevity. |
| Trigger Time | Time when the trigger causing this request actually happened. This is either the same time as request time or typically a bit earlier due to delay caused by processing the original event and even waiting for processing of previous events and Your Logic. Trigger time is specifically the end of post processing. |



Importantly Salted CX sends you the current state of the conversation even when it contains messages and other events that happen after this request. You can choose to process them or not.

Salted CX follows these simple rules:

- Sends one request for every message or other event unless you tell us not to do that

- Sends the state of the conversation at the time when the request is sent

### [](#request-1)Request 1

Request 1 is simple. It sends only one message and the conversation contains only one message.

```json
{
	"requestId": "5a1bfe8d-c73f-4af7-80db-3f6400a10f2d",
	"time": "2025-04-13T08:00:01Z",
	"expires": "2025-04-13T08:00:16Z",
	
	"trigger": {
		"time": "2025-04-13T08:00:00Z",
		"type": "MESSAGE",
		"participantType": "CUSTOMER",
		"content": "Message 1 content"
	},
	
	"customer": {
		/* customer attributes */
	},
	
	"conversation": {
		/* convesation attributes */
	},
	
	"engagements": [
		/* list of engagements */
	],
	
	"turns": [
		{
			"pid": "88b4b430-7f0b-4e15-90a5-3d2e287dfa71"
			"time": "2025-04-13T08:00:00Z"
			"type": "MESSAGE",
			"participantType": "CUSTOMER"
			"content": "Message 1 content"
		}
	]
}
```

Request 1 sent by Salted CX to Your Logic### [](#response-1)Response 1

We show an example empty response that tells Salted CX just to cary on and continue sending subsequent requests for that conversation.

```json
{
	"requestId": "5a1bfe8d-c73f-4af7-80db-3f6400a10f2d"
}
```

### [](#request-2)Request 2

Request 2 is interesting because while processing Request 1 in Your Logic the customer sent two more messages. Notice in the subsequent code example that despite the trigger is the Message 2 from he customer the turns array contains also the Message 3.

```json
{
	"requestId": "a3bb189e-8bf9-3888-9912-ace4e6543002",
	"time": "2025-04-13T08:00:16Z",
	"expires": "2025-04-13T08:00:31Z",
	
	"trigger": {
		"time": "2025-04-13T08:00:10Z",
		"type": "MESSAGE",
		"participantType": "CUSTOMER",
		"content": "Message 2 content"
	},
	
	"customer": {
		/* customer attributes */
	},
	
	"conversation": {
		/* convesation attributes */
	},
	
	"engagements": [
		/* list of engagements */
	],
	
	"turns": [
		{
			"pid": "88b4b430-7f0b-4e15-90a5-3d2e287dfa71"
			"time": "2025-04-13T08:00:00Z"
			"type": "MESSAGE",
			"participantType": "CUSTOMER"
			"content": "Message 1 content"
		},
		{
			"pid": "b8d4c4e0-8e3d-4ff6-a3e3-681b4b9d570e"
			"time": "2025-04-13T08:00:10Z"
			"type": "MESSAGE",
			"participantType": "CUSTOMER"
			"content": "Message 2 content"
		},
		{
			"pid": "2d4e36b2-0c4d-4d75-b25f-4b6c56e3c25e"
			"time": "2025-04-13T08:00:15Z"
			"type": "MESSAGE",
			"participantType": "CUSTOMER"
			"content": "Message 3 content"
		}
	]
}
```

### [](#response-2)Response 2

There are two ways how Your Logic can respond. The first option is the same as Response 1. Just returning the request PID. This would lead to Salted CX sending a third request with content of the message 3.

```json
{
	"requestId": "a3bb189e-8bf9-3888-9912-ace4e6543002"
}
```

(Upcoming) The `skipAfter` property is not available yet — today Salted CX sends a request for every event and a `skipAfter` value in the response is ignored. Once available, Your Logic will be able to process all turns including the “future” turns and respond with `skipAfter` so that events up to that time produce no further requests (typically the time of the last turn in the request).

```json
{
	"requestId": "a3bb189e-8bf9-3888-9912-ace4e6543002",
	"skipAfter": "2025-04-13T08:00:15Z" 
}
```

## [](#parallel-events)Parallel Events

In case Your Logic implementation is able to process multiple events in parallel, you can enable this behavior by changing how Your Logic responds to events:

- Return response with no actions immediatelly after receiving the event (this enables Salted CX send you a next event immediatelly)

- Once you have the response to the event update the conversation directly without tying it to a specific event

You can freely combine this with sequencing. For example, if you receive an event you are able to process in parallel with another event, you can handle it differently from an event you do not want to handle in parallel.

---

## Built-in Questions and Forms

Source: https://help.salted.cx/en/articles/questions-built-in


Salted CX provides built-in content to help Quality Assurance, Team Leaders, and other people in the company to perform reviews, provide feedback to agents, and annotate data for training AI.

## [](#built-in-questions)Built-in Questions

Salted CX provides a built-in set of questions and tags that you can use to review turns and engagements. These questions and tags are useful as Salted CX understands their meaning and can provide built-in reporting on top of those. The built-in questions can also be used to create auto reviews.

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

Contact Salted CX to create tags and questions for you. This step cannot currently be done directly in the application.





| Question or Tag | Type of Question | Description and Usage |
|---|---|---|
| Agent Burnout | Tag | The agent's behavior seems to indicate risk of the agent burnout. |
| Bookmark | Tag | General purpose tag that enables to bookmark parts of customer journey for easier access later. |
| Bot Handling Candidate | Tag | The turn is a good candidate for being handled by a bot instead of an live agent. |
| Broken Promise | Tag | The agent broke a promise given to a customer. |
| Compliance Issue | Tag | The turn has a compliance issue in it. |
| Confusing | Tag | The information in turn can be considered correct but the message can be confusing for users. |
| Customer Retention Risk | Tag | The customer behavior indicates that they might stop using your products or services. |
| Customer Rights Issue | Tag | The agent did something in violation of customer rights. |
| Customer’s Objection | Tag | The customer objected to something the agent offered to him. |
| Disclosed Internal Information | Tag | The agent disclosed an information that should not be shared outside of the company. |
| Escalate to Human Agent | Tag | This should have been escalated to a human agent rather than handled by a bot. |
| Escalate to Supervisor | Tag | This should have been escalated to supervisor instead of user or bot. |
| Exceeding Expectations | Tag | The agent goes extra mile and exceeds customers expectations and also minimal company requirements. |
| Excuse for Delay | Tag |  |
| Failed to Resolve | Tag | The agent failed to resolve the issue even when it was possible to do so. |
| Feedback to Agent | Free Text | Freeform feedback to the agent that is neither specifically negative or positive. |
| Financial Impact | Tag | The agent caused a decision that has a negative financial impact on the company. |
| Frustrated Customer | Tag | The customer clearly communicated that they are frustrated. They were name calling the company for example. |
| Good Rapport | Tag | The agent managed to built a rapport between them and the customer. |
| Grammar Issues | Tag | The turn contains grammar errors that worsen readability of the message or look unprofessional. |
| Happy with Agent | Tag | Customers expressed that their happy with an agent. |
| Happy with Company | Tag | Customers expressed that they're happy with your company. |
| Happy with Process | Tag | Customers expressed that they're happy with a process they are going through. |
| Happy with Product | Tag | Customers expressed that they're happy with your product or services they are going through. |
| Happy with Vendor | Tag | Customers expressed that they are happy with your vendor, partner, supplier, etc. |
| Ignored Request | Tag | Turn of the customer that agent have not responded to. |
| Improve Canned Answer | Tag | Indicator that a canned answer should be improved to cover additional, cases, improve clarity |
| Incomplete Information | Tag | The agent provided incomplete information to the customer. |
| Incorrect Information | Tag | The agent provided the customer incorrect information. |
| Inflating Performance | Tag | The agent made illicit actions that were not according to the process and were clearly intended to increase the agent performance metrics. |
| Introduction | Yes/No/Not Applicable | Did the introduction follow the company guidelines? |
| Knowledge Gap | Tag | The agent has a knowledge gap that causes handling |
| Late Response | Tag | The agent responded later than expected by the customer based on the previous communication. |
| Legal Issue | Tag | The turn is a potential legal issue. |
| Menu Candidate | Tag | The turn is a good candidate of being to handled by self service such as menu on the web or in the IVR. |
| Missed Sale Opportunity | Tag | The agent missed an opportunity to sell something to the customer. |
| Missed Upsell Opportunity | Tag | The agent had opportunity to offer the customer additional products and services but they have missed the window of oppotunity. |
| Missing Apology | Tag | The agent should have apologized to the customer at this point but didn’t do it. |
| Missing Approval | Tag | The agent haven’t gone through an approval steps for sending a message that requires an approval. |
| Missing Follow Up | Tag | The agent did not create a followup for the customer request when necessary. |
| Missing Next Steps | Tag | The agent should have provided the next steps but failed to do so. |
| Missing Verification | Tag | The agent has not verified customer according to the required process. |
| Misunderstood Customer | Tag | The agent misunderstood the customer. For example they repeated the customer request inaccurately. |
| Next Steps | Tag | The agent provided next steps for the customer issue even when a customer has not asked about them, but there is a reasonable chance that the customer would encounter them once they resolve their current issue. |
| Not Authentic | Tag | The agent responses in a way that feels robotic and scripted. |
| Not Helpful | Tag | The agent responded in the way that was objectively not helpful. |
| NPS | Number | Industry standard NPS. |
| Off Script | Tag | The agent went off script. |
| Offensive | Tag | The turn contains content that the customer is likely find offensive. |
| Opportunities | Free Text | Free description what the agent is doing right. Use this to encourage agents and reinforce a good behavior. |
| Outdated Information | Tag | The agent provided information that is no longer current and considered outdated. |
| Poor Empathy | Tag | The agent should have expressed empathy with the customer but they did not. |
| Poor Followup | Tag | The agent created a poor followup that is missing important information. |
| Poor Objection Handling | Tag | The agent did not handle the customer objection well. The agent has not used the expected response for a given customer objection. |
| Poor Translation | Tag | The turn was not well translated by the tools used in the contact center. |
| Privacy Issue | Tag | Private information was shared in a way that is not aligned with the process and may cause compliance issue. |
| Process Issue | Tag | The turn hit an issue with business processes. |
| Process Not Followed | Tag | The agent has not followed a given process. |
| Proposed Wording | Free Text | Exact wording that the agent should have used when answering to a customer. Use this to teach agents what to answer to customers in different situations. This can be just a fine polishing their response or giving them totally different direction on how to respond. |
| Punctuation Issues | Tag | The turn contains punctuation errors that worsen readability of the message or look unprofessional. |
| Reach to Customer | Tag | Mark that you should reach back to the customer regarding this issue. |
| Repeating Customer Words | Tag | The agent just repeated what customer exactly said without adding any additional information or confirming unknowns. |
| Reviewed | Tag | Marks the engagement as reviewed. |
| Rude | Tag | The message of the agent might be perceived rude by the customer. |
| Sentiment | Single Choice | Customer sentiment based on the turn expresses how how customers likely feel based on how they express themselves in the conversation. |
| Slow Tools | Tag | Agent is using tool that is not efficient when handling the customer. This can be performance issue, need for an agent to make unnecessary steps in an application, etc. |
| Strengths | Free Text | Free description what the agent should do better the next time. Use this to drive agent behavior change. |
| Stressed Agent | Tag | The agent is noticeably stressed. |
| Structure Issues | Tag | The communication was not well structured to be easy to understand by the customers. |
| Successful De-Escalation | Tag | The agent successfully de-escalated the situation with a customer. |
| Suggestion for Salted CX | Free Text | Free text that our users can use to report suggestions for Salted CX that are attached to turns and engagements. For example on how to better visualize a selected item in the customer journey. |
| Summary | Free Text | Condensed information about the most important points in the turn or an entire engagement. |
| Technical Issue | Tag | The agent encountered a technical issue that affected the conversation. |
| Too Pushy | Tag | The agent was pushing a product, service at the level that was not comfortable to customers. |
| Too Wordy | Tag | The response to customer is wordy. |
| Unanswered Questions | Tag | The agent has not answered all customer questions. |
| Unhappy with Agent | Tag | Customers expressed that their unhappy with an agent. |
| Unhappy with Company | Tag | Customers expressed that they're unhappy with your company. |
| Unhappy with Process | Tag | Customers expressed that they're unhappy with a process they are going through. |
| Unhappy with Product | Tag | Customers expressed that they're unhappy with your product or services they are going through. |
| Unhappy with Vendor | Tag | Customers expressed that they are unhappy with your vendor, partner, supplier, etc. |
| Unnecessary | Tag | This turn is not necessary. Agent should have just omitted this message would save some time. |
| Unnecessary Apology | Tag | The agent apologized even when the apology was not necessary. |
| Unnecessary Escalation | Tag | The agent decided to escalate the conversation even when the escalation was not necessary from the company policy perspective. |
| Unnecessary Follow Up | Tag | The agent created initiated a follow-up (such as case creation or scheduling another call) when it was not necessary. |
| Unnecessary Transfer | Tag | The agent decided to transfer the conversation even when they should be able to handle the customer. |
| Unprofessional | Tag | The communication with customer did not meet the level required by the company. |
| Unrealistic Promise | Tag | The agent promised or build an expectation at the the customer side to do something that is not realistic. |
| Unredacted Information | Tag | The turn exposes an information that should have been redacted by Salted CX. |
| Unsuitable Product Offer | Tag | The agent offered a product that was not suitable for the customer based on the information the agent had available. |
| Urgent | Tag | Customers` request is urgent and requires immediate resolution. |
| Use for 1 on 1 | Tag | Marks the turn for a discussion during on on one meeting. |
| Use for Calibration | Tag | The turn is a good candidate for calibration reviews. |
| Use for Training | Tag | The turn is a good candidate for training sessions. |



## [](#built-in-forms)Built-in Forms

Built-in forms are general-purpose forms suitable for basic needs across verticals. Salted CX provides them as a starting point so you can start doing reviews and providing feedback from day one.

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

Contact Salted CX to create new forms for you. This step cannot currently be done directly in the application.





| Form | Description |
|---|---|
| Agent Well-Being | Form focused on keeping agents happy and engaged when working. |
| Automation Opportunities | Form focused on pin pointing areas that can be handled with automated tools such is self-service, IVRs or bots. |
| Bot | Form focused on providing feedback on bot performance. This feedback can be used to improve the bot to handle better various scenarios or identify scenarios in which the customer should rather be talking to a person. |
| Communication Style | Form focused on how the agent communicates with the customer and issues that are in the message. |
| Compliance | Form focused on potential compliance issues that happen in the conversations. |
| Customer Experience | Form focused on how the customer feels specifically when the customers themselves express their experience. |
| Customer Retention | Form focused on identifying risk of losing the customer. |
| Customer Trust | Form focused on providing customers’ with accurate information and building their trust. |
| Customer Understanding | Form focused on whether the agent is good at understanding the customer. Whether the agents can tell how customers’ feel and what they are asking for. |
| Feedback to Agent | Form focused on providing feedback to an agent. |
| Inefficiency | Form focused on areas where agents or processes led to additional unnecessary work by either doing actions that take their time or the time of other people in the company. |
| Process Adherence | Form focused on how the agents follow company processes and whether the processes themself are suited to cover customer needs. |
| Process Improvement | Form focused on improving the process agents follow during conversations and the tools they have available. |
| Sales Skills | Form focused on sales performance. |

---

## Customer Profile

Source: https://help.salted.cx/en/articles/customer-profile


Article short description

Customer Profile links multiple contact information into a single customer so you can then see all conversation across channels in our [customer journey](https://help.salted.cx/en/collections/1755250527-customer-journey). Customer Profile stores contact information such as emails, phone numbers, usernames, IDs from various platforms, and similar.

## [](#linking-contacts)Linking Contacts

You can associate multiple contacts with a single customer. Each customer is associated with a single [customer journey](https://help.salted.cx/en/collections/1755250527-customer-journey). That enables you to see all the conversations between you and the customer in a single place as a complete customer experience.

![](https://media.notiondesk.so/upload/689de8461cc4e210489161.png)A single customer with contacts scattered across different systems

In the example above when you integrate Salted CX with the three example systems Salted CX will automatically build the relationships based on multiple records associated with the same customers in the individual systems. Now when the customer uses their phone number `+1 (555) 123-4567` and their email `carmen.menzel@company.com` the conversations over these two channels are visible in the same [customer journey](https://help.salted.cx/en/collections/1755250527-customer-journey) even when they do not appear in a single system next to each other.

We automatically extract relationships between contacts from all supported platforms. When you use our Ingest API you can also provide alternative contact information about customers that helps to build relationships between contacts of the individual customers.

## [](#privacy)Privacy

Customer Profile is designed with privacy protection in mind while providing features that help you to understand complete customer journeys. The customer and their contact information are represent by PIDs. PID is an UUID from which you cannot determine the original value.



## [](#contact-format)Contact Format

We perform simple clean up of the contact information to connect conversations that would otherwise be attributed to a different physical person just because a difference in formatting.



![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

Clean up is based on contact type you provide. So the clean up for phone number happens only in case you explicitly tell via Ingest API that the contact is a phone number (Phone). If you provide different contact type only the basic clean up will happen — removing white spaces at the beginning and at the end of the contact.





![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

 If you use our Ingest API to load the customer contacts we strongly recommend you validate you have the contact information in the format you expect. If you load phone numbers always try to include the country code in the phone number even if you have phone calls only from one country.





Unified phone number format enables to easily link the same person in multiple systems and prevent different people from being linked if they by chance have the same phone numbers, just in different countries. Phone number `+1 (555) 123-4567` is considered different from phone number without country code `(555) 123-4567` as we are unable to reliably attribute country to that phone number.

We do not use contacts that do not pass basic validation to link with other contacts into the customer journey.

## [](#do-not-link-contact)Do Not Link Contact

You can prevent a selected contact from lining to other contacts from the [customer journey](https://help.salted.cx/en/collections/1755250527-customer-journey). This enables you to isolate a contact that does not represent well a physical person from merging unrelated conversations into a single customer journey.

An example of contacts you do not want to use for building customer journeys are group email addresses or phone numbers that are used by a company gateway and there are multiple people using them.

## [](#large-contact-clusters)Large Contact Clusters

We limit the number of contacts associated with one customer to 100. This cap prevents accidentally loading data to Salted CX that would cause linking unexpected contacts together. When this cap is reached we attempt to identify a contact caused the large clusters to appear and isolate the contact from creating the customers. The contact has to have at least 20 connections to become isolated. Example when this happens is when source systems contain unclean data such as `no@email.com` for customers who have not provided emails. In case the system also contains customers such email can link those phone numbers to a single customer. This detection mechanism helps to automatically resolve these issues if they link too many contacts together.

*Tags: Customer Journey*


---

## Metrics Best Practices

Source: https://help.salted.cx/en/articles/metrics-best-practices


Management of anything requires visibility. Metrics (or KPIs) are the key method how to measure performance and report on trends.

Salted CX has a rich set of industry-standard metrics that work across different platforms and provide visibility into many aspects of different types of contact centers.

## [](#actionable-metrics)Actionable Metrics

Foster a culture of making the metrics actionable. We recommend having a smaller set of metrics with clearly defined processes when they change. For each metric you plan to introduce you should ask these two questions:

- If the metric is higher than X who will do what?

- If the metric is lower than Y who will do what?

You should have an answer to at least one of these questions before you invest effort into introducing any metric. The “who” part helps you to understand who is the audience for the metric and can act on it. The “what” part helps you to understand whether the metric is actually actionable. You can enhance the “what” with “why” to justify the metric existence

There are a few examples:

- If the customer satisfaction is lower than 85% the customer experience team will walk through conversations in the last ten days and provide a list of corrective actions for individual teams. Because our company relies on loyal customers who buy more services over time and higher customer satisfaction increases the chance of future purchases.

- If the response rate to customer surveys in a channel is lower than 10% the customer experience team will create a new survey workflow for that channel and/or modify the questions asked to increase the response rate. Because we want to ensure that we receive as much customer feedback as possible.

- If the percentage of escalations from self-service to a life agent in a web menu is higher than 5% in a given branch the analytics team will check all conversations that were escalated to identify improvements in the menu. Because escalated requests are 50 times more expensive to handle we need to keep the number of agents at the current levels.

- If the number of negative auto reviews per agent exceeds 10 in a single day the agent’s team lead will prepare a coaching session for the agent based on the conversations that received the negative auto reviews. Because auto reviews cover all conversations and are an early warning that agents may not follow our customer satisfaction and quality assurance requirements.

- If the agent has schedule adherence lower than 95% the team lead will issue a warning to the agent or begin a disciplinary process if this repeats for the 3rd time. Because we have found that if we do not enforce this level of adherence we have issues with handling the inbound traffic during peak hours.

## [](#features-of-a-good-metric)Features of a Good Metric

We recommend each metric to have at least these attributes defined:

- Owner. Somebody who understands the metric definition and what it should represent. Ideally this person would be able to answer questions how the metric should be calculated for different edge cases. This person should also be able to define the rest of the points in this list.

- Business reason. Why the metric is important for the company.

- Action is taken when lower and/or higher than a threshold. For each metric you should have a clear action that somebody takes when it crosses a defined threshold. This action should be in your operating procedures. Good place where to describe the next steps is the dashboard itself.

- Audience. Who is consuming the metric. These should be the same people who should take action if the metric crosses a threshold. It is also good to have a wide audience for transparency.

- Descriptive name. Use a name that is aligned with the company vocabulary and ideally aligned with the naming convention of Salted CX

- Detailed description. Imagine that you are explaining what the metric means and how it is used to a new person in your company. Include in the description why the metric is important, how to use it, how exactly is calculated, and if there are any particular cases in which it works well and in which it does not.

---

## Performance Tips

Source: https://help.salted.cx/en/articles/1755219765-performance-tips


Salted CX is designed to provide a good performance on top of large volume of conversations including their content. We target to have render times most of the time within a few seconds. However there are still technological limits and complex visualizations may take longer to render. This article covers best practices to minimize those instances.

The performance of the rendering depends on many factors, including but not limited to:

- Metric complexity. We give users extreme flexibility to create metrics that match their business needs. This may opens possibility to create metrics that use excessive resources even when run on top high-performance storage.

- Size of the data used for metric calculation. Larger volume of data for calculation means more data needs to be processed. There are technological limits to how fast data can be moved in ant system. This is mostly influenced by filters, eventually by metrics in case they ignore filters by definition.

- Total size of data in your Salted CX account. Depending on metrics definition and filtering criteria it might be impossible to take advantage of certain performance optimization and processing all data might be needed.

## [](#metric-complexity)Metric Complexity

Metric complexity is a key factor driving performance.

- Prefer metrics that do not require traversing multiple data sets. For example metric that uses Review data set and Customer data set needs to traverse 3 large dat sets.

- Restrict metric to filter for relevant items. It is good practice to filter by (Engagement, Review) Type and Status not just for performance reasons but to focus metric on data that are really actionable and avoid mixing unrelated data.

## [](#filters)Filters

Filters reduce the volume of data that we need to process. When creating a new visualization or a new dashboard we use 30 days filter by default.

- Avoid working without date filters. This generally leads to processing all data. Which means the more conversations you have collected so far the slower the computation runs.

- Prefer 30 days or shorter time filters in visualizations and dashboards. The most valuable information is typically in the most recent conversations anyway.

- Using hierarchical filtering criteria where values available in one filter depends on another filter ❶. This often requires exploring all data in your account. If you need to use these dependency filters consider adding filter based on date that narrows the search for available attribute values ❷.

![](https://media.notiondesk.so/upload/689de24a2f420633513702.png)

## [](#dashboards)Dashboards

Dashboards contain a collection of visualizations. All visualizations in a dashboard start rendering in the same time and run in parallel. If the dashboard contains a lot of visualizations.

- Prefer dashboards that fit on a screen. When you have a long scrollable pane with many visualizations the visualizations that are not visible to users delay for visualizations that are visible to user. It is good practice to have all data that users need to fit the screen and use drill downs and filtering to provide additional perspective.

---

## ServiceNow Integration

Source: https://help.salted.cx/en/articles/integration-servicenow


![](https://www.notion.so/icons/warning_yellow.svg?mode=light)

This feature is in Preview and its behavior is likely to change based on user feedback. The feature also may have lower availability and have more maintenance windows.





You can connect multiple ServiceNow instances to a single Salted CX account and mix data in Salted CX with other data sources.

## [](#integration-between-servicenow-and-salted-cx)Integration between ServiceNow and Salted CX

There are only two required items to connect to Salted CX:

1. [ServiceNow API credentials](https://docs.servicenow.com/bundle/utah-platform-security/page/integrate/inbound-rest/concept/c_OAuthAPI.html) (username and password)

2. ServiceNow instance URL — for example <https://yourcompany.service-now.com/>

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

Salted CX currently supports ServiceNow Incidents only. We will add other types of activity such as requests, problems, changes, etc. based on demand. However incidents are the only





## [](#servicenow-data-in-logical-model)ServiceNow Data in Logical Model

We translate data from all platforms into our unified Logical Model that enables you to report on data from multiple platforms in the same way. We use unified concepts with unified naming and the same meaning in every platform.

As each platform has its own vocabulary and concepts we cannot adopt any single platform vocabulary. Platforms have different names for the same concepts (for example ticket, case, issue, or task for a single customer-related request). Or different platforms use the same name for different concepts (for example "Contact" means a single conversation with a customer in one platform, but it means a customer email/phone in another platform).

This article covers how ServiceNow concepts translate into Salted CX concepts and vocabulary.

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

To understand ServiceNow data in the Logical Model it is recommended to have a basic understanding of our Customer Journey and Logical Model. You can also check our Glossary to understand the naming and meaning of our concepts.





### [](#customers)Customers

Salted CX creates individual customers that correspond to ServiceNow users. ServiceNow creates users for both agents and the customers contacting the company. Every incident or request associated with a user representing a customer becomes part of the given customer's customer journey. So you see all those tickets chronologically one after another in our customer journey.

The customer email becomes the contact identifier in Salted CX, with fallback to phone number or ServiceNow sys\_id if email is not available. The customer name from ServiceNow is stored as the customer name in Salted CX.

### [](#conversations)Conversations

Each ServiceNow incident or request translates to one conversation in Salted CX.

### [](#engagements)Engagements

ServiceNow does not have a built-in concept similar to engagements in Salted CX. We define engagement as the participation of a single agent or a service in a conversation with a customer. We use heuristics to extract a similar concept from ServiceNow data.

We create engagements based on actual agent activity on the incident or request. An engagement starts when an agent responds to a ticket for the first time or when a ticket is reopened. The engagement ends when another agent starts to engage with the customer or the ticket is resolved. The start time of an engagement is when an agent sends their first message. The end time of an engagement is when an agent sends their last message. This heuristic tries to best approximate the engagement time.

For example, if an agent Alice replies to a customer at 8:00 AM with one message, then Alice asks Bob for help with the customer. Bob starts to chat with the customer at 8:15 AM until 8:30 AM. Bob returns the ticket to Alice who chats with the customer from 8:45 AM to 9:00 AM and marks the ticket as resolved. Customer reaches back and Alice chats again with the customer from 10:00 AM to 10:30 AM. We create 4 engagements:

- Engagement with Alice with start time and end time 8:00 AM

- Engagement with Bob with start time 8:15 AM and end time 8:30 AM

- Engagement with Alice with start time 8:45 AM and end time 9:00 AM

- Engagement with Alice with start time 10:00 AM and end time 10:30 AM

![](https://www.notion.so/icons/warning_yellow.svg?mode=light)

Depending on your exact process and setup in ServiceNow our metric Engagement Time and metrics based on it may not be reliable indicator of an agent performance. Unlike many other contact center platforms, ServiceNow does not have a concept of an agent actively working on a ticket by accepting it. This means the agent can spend some time by looking at the ticket before engagement start time starts. You can use metrics such as Engagements per Hour to get glimpse of the agent performance. More engagements per hour typically means agents are faster in handling them.





We map the following attributes from ServiceNow tickets to the Salted CX model:

| Salted CX | ServiceNow Attribute |
|---|---|
| Case | Problem number |
| Channel Vendor | "ServiceNow" |
| Channel Type | Mapped from contact\_type: empty → "Email", "self-service" → "Web", "phone" → "Voice" |
| Conversation | Ticket number |
| Conversation Start Time | Ticket created timestamp (sys\_created\_on) |
| Direction | 'Inbound' |
| Engagement Type | "Agent" |
| Engagement Link | Link to the ticket in ServiceNow |
| Engagement Priority | Ticket priority |
| Engagement State | "Completed" if state is 6 or 7, else "In Progress" |
| Start Time | Engagement start time (first comment timestamp) |
| End Time | Engagement end time (last comment timestamp) |



### [](#turns)Turns

Each individual comment or message from an agent or from a customer creates a new message turn associated with an engagement of the currently engaged agent.

## [](#data-not-available-from-servicenow)Data not Available from ServiceNow

Different customer care platforms provide different granularity of data and have different concepts. These features may prevent us from reporting on certain metrics or impose other restrictions.

This typically prevents use of certain attributes and/or metrics in reporting for the given platform. This section covers the key limitations based on ServiceNow data. Remember that when one metric is affected also metrics based on that one are affected (such as average of the missing metric).

### [](#queue-engagements)Queue Engagements

ServiceNow does not have a concept of queues similar to many other contact center platforms. Thus we do not create any queue engagements that typically represent waiting customers in a specific queue and enable visibility into customer movement between queues.

Affected attributes: Queue

Affected metrics: Wait Time, Queue Engagements

### [](#invitation-engagements)Invitation Engagements

ServiceNow does not have a concept of inviting agents to conversations (showing agents that they can engage with the customer by joining conversation) similar to many other contact center platforms. Thus we do not create any invitation engagements in case the agent misses or rejects the invitation to join conversations.

Affected metrics: Invitation Time, Rejected Invitations, Missed Invitations

### [](#wrap-up-time)Wrap Up Time

ServiceNow does not have a concept of wrap up that agent has to perform after an engagement with a customer. Although agent can perform additional actions in ServiceNow after they resolve the customer ticket this time is not tracked by ServiceNow.

Affected metrics: Wrap Up Time

### [](#agent-status)Agent Status

We do not import agent activity (agent status, AUX code) from ServiceNow. These status codes are typically used for routing decisions and WFM purposes. When using ServiceNow we recommend you have another source for this data such as WFM or a contact center platform that you connect with Salted CX.

Affected metrics: Activity Time, Available Time, Unavailable Time

*Tags: Integration*


---

## Filtering

Source: https://help.salted.cx/en/articles/1755272271-filtering


Filtering choses which data make it into the metric calculation. Filtering is applied before any calculation happens on the individual items (Engagements, Agents, etc.) level.

## [](#basic-filtering)Basic Filtering

In this example we will simply add a simple condition on top of a built-in metric. The example below takes the built-in metric Agent Engagements that counts all engagements of every agent ever made. We can just add one condition that makes the metric count only engagements that have Outcome value Resolved.

```sql
SELECT <span class="fw-bold nd-color--green">Agent Engagements</span> 
	WHERE <span class="fw-bold nd-color--orange">Outcome</span> = <span class="nd-color--red">"Resolved"</span>
```

Now suppose we want to filter the Resolved Engagements only to a specific Queue. We have have several options to define it. One option is to define it based on the same built-in metric.

```sql
SELECT <span class="fw-bold nd-color--green">Agent Engagements</span> 
	WHERE <span class="fw-bold nd-color--orange">Outcome</span> = <span class="nd-color--red">"Resolved"</span> AND <span class="fw-bold nd-color--orange">Queue</span> = <span class="nd-color--red">"Level 1 Support"</span>
```

Another option is to reuse the metric Resolved Engagement we have defined earlier. This reuse has the advantage that whenever our definition what being resolved means (for example Outcome can be also “Solved”) you have fewer metrics to update. Reusing existing metrics also makes many metrics shorter and easier to read and understand.

```docker
SELECT <span class="fw-bold nd-color--orange">Resolved Engagements</span> 
	WHERE <span class="fw-bold nd-color--orange">Queue</span> = <span class="nd-color--red">"Level 1 Support"</span>
```

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

When building insights and dashboards you apply filters there so you often do not need include filters directly in metrics. You can create a generic metric and then use different filtering in different reports and dashboards depending on your business needs. However filtering on metric level is still useful for more complex conditions or just to make building reports more convenient.





## [](#logical-expressions)Logical Expressions

You can use the following logical expressions to filter exactly the items from data sets that you need:

- `NOT` — Inverts the condition. So only items that do not match the following statement are used in the metric calculation.

```sql
SELECT <span class="fw-bold nd-color--green">Completed Agent Engagements</span> 
	WHERE <span class="fw-bold">NOT</span> <span class="fw-bold nd-color--orange">Queue</span> = <span class="nd-color--red">"Test"</span>
```

- `AND` — Both conditions have to be true for an item to be included in the metric calculation.

```sql
SELECT <span class="fw-bold nd-color--green">Completed Agent Engagements</span> 
	WHERE <span class="fw-bold nd-color--orange">Queue</span> = <span class="nd-color--red">"VIP"</span> <span class="fw-bold">AND</span> <span class="fw-bold nd-color--orange">Outcome</span> = <span class="nd-color--red">"Resolved"</span>
```

- `OR` — At least one of the conditions have to be true for an item to be included in the metric calculation.

```sql
SELECT <span class="fw-bold nd-color--green">Completed Queue Engagements</span> 
	WHERE <span class="fw-bold nd-color--orange">Outcome</span> = <span class="nd-color--red">"Callback"</span> <span class="fw-bold">OR</span> <span class="fw-bold nd-color--orange">Outcome</span> = <span class="nd-color--red">"Voicemail"</span>
```

## [](#parent-filters)Parent Filters

You can define metrics that ignore parent filters. Parent filters are filters that users choose on insights or dashboards level.

- `WITH PARENT FILTER` — All parent filters affect this metric. This is the default behavior and you do not have to include it in the metric.

- `WITH PARENT FILTER EXCEPT <span class="fw-bold nd-color--orange">Attribute 1</span> , <span class="fw-bold nd-color--orange">Attribute 2</span>, …` — All parent filters affect this metric except for filters of Attribute 1, Attribute 2 and other listed attributes. You can use this statement to choose attributes.

- `WITHOUT PARENT FILTER` — No parent filters affect this metric. Whatever filters the users apply in insights or dashboards do not affect this metric.

- `WITHOUT PARENT FILTER EXCEPT <span class="fw-bold nd-color--orange">Attribute 1</span> , <span class="fw-bold nd-color--orange">Attribute 2</span>, …` — No parent filters affect this metric, except for filters of Attribute 1, Attribute 2 and other listed attributes. This statement enables you choose attributes that affect the metric.

---

## Historical Changes in Data

Source: https://help.salted.cx/en/articles/1755188319-historical-changes-in-data


Data gets updated over time — queues get renamed, organization hierarchy changes, people move from team to team, etc. Salted CX tries to best represent history in a way that is accurate and provides expected data. However, data sources may impact our ability to do so. This article covers technical details of how historical data look in Salted CX.

## [](#entities)Entities

Salted CX uses [entities to represent important objects](https://help.salted.cx/en/collections/1755206106-logical-model) in a contact center world. These entities represent many different concepts such as teams, queues, agent statuses, etc. These entities have a permanent identifier (PID), an external identifier (ID they have in the data source), and a human-readable name.

Salted CX uses permanent immutable identifiers (PIDs) to reference entities from data sets. These PIDs are not updated after an entity is created and ensure the integrity of the data. Entity names are used for visualization in our application including customer journey, reporting, etc.

There are two ways how PIDs are generated:

- Based on immutable external ID. Preferred method if the stable ID is available in the given platform. This enables renaming entities without breaking references.

- Based on name or mutable ID. This is a fallback method if the platform does not have immutable IDs for the given entity type.

The below table shows the comparison of these representations and how they

| Property | Past | Present |
|---|---|---|
| Entity with Data Source ID |  |  |
| PID | `3b7b04f3-aee1-44e1-96a9-3b85604c770e` | `3b7b04f3-aee1-44e1-96a9-3b85604c770e` |
| External ID | `data-source-immutable-id` | `data-source-immutable-id` |
| Name | Original Name | New Name |
| Entity without Data Source ID |  |  |
| PID | `6bfda030-ad65-478a-ac9f-bde605a13776` | `4f6ac436-80b8-46a7-9244-7994a00fd455` |
| External ID | Original Name | New Name |
| Name | Original Name | New Name |



### [](#pids-based-on-entity-external-id)PIDs Based on Entity External ID

Salted CX uses data source IDs by default to have stable references even when the entity gets renamed in the original data source. This enables maintaining referential integrity even when the entity gets renamed.

Salted CX always shows the latest name for the entity. For example, if a team gets renamed even past engagements will show the latest name of the team. If you want to break this relationship you have to create a new team in the data source and associate agents with that team. This applies to every entity including but not limited.

![](https://www.notion.so/icons/warning_yellow.svg?mode=light)

Be careful when working with these entities. Renaming the entity does not change its purpose historically. Do not repurpose these entities for different use cases that you do not want to see in reporting together. Always delete or deactivate the old entities and create new ones.





### [](#pids-based-on-entity-name)PIDs Based on Entity Name

In case the data source does not have IDs for the given entity name Salted CX generates PIDs based on the entity name. This is a fallback scenario and Salted CX uses it only if there is no support for stable ID for the given entity.

Before creating a name-based PID for an entity, Salted CX does the following operations:

- Trims leading and trailing spaces

- Converts the name to the lower case

The below example demonstrates the issue on a chart that shows volume of engagements in two queues. In the scenario the blue Queue was renamed to the green Queue - Renamed in the middle of the month. This leads to a major issue when calculating some metrics as part of the engagements is attributed to one queue and the rest to the other queue. Which leads to misleading numbers in charts and tables.

![](https://media.notiondesk.so/upload/689de24c6b65f832052745.png)Example chart that shows manifestation of a renamed queue that is identified by its name.

| Engagements Count | April | May | June | July | August | September |
|---|---|---|---|---|---|---|
| Queue | 17 | 26 | 31 | 15 | — | — |
| Queue - Renamed | — | — | — | 20 | 37 | 36 |
| Another Queue | 20 | 24 | 26 | 27 | 28 | 28 |



![](https://www.notion.so/icons/warning_yellow.svg?mode=light)

Be careful when renaming entities in the original platform that do not have stable IDs. Renaming entities that do not have stable ID in the original platform will lead to breaking the continuity of data and potentially lead to misleading metric numbers — especially when reporting on volumes segmented by the entity type that got renamed.





### [](#deleted-objects)Deleted Objects

In many platforms you can delete objects that Salted CX imports. How deleted objects look like in Salted CX depends on the circumstances of the delete:

- The object is “soft-deleted” in the source platform — Salted CX imports the object including all its available attributes. If the object is translated to a data set stat has `Status` attribute, the Status attribute is set to value `Deleted`.

- The object is deleted but Salted CX imported it in the past — Salted CX keeps all references to the object and its attributes. If the object is translated to a data set stat has `Status` attribute, the Status attribute is set to value `Deleted`.

- The object is deleted before it was imported into Salted CX but other objects still reference it by its original ID — Salted CX created a placeholder for the object that does not have any other attribute than its ID in the source platform. Salted CX then uses name `∅ <platform ID>` to indicate that the object was deleted and also keep distinguishable names for the deleted objects.

- The object is deleted and references to it are removed — Salted CX is not aware of what objects are originally referenced and uses reference to empty entity.

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

We strongly recommend to perform so-called “soft delete” if your platform supports it. Soft delete does not delete the entity but marks it as deleted. This enables to preserve the historical data and excludes the entity from usage in your platform. For example a soft deleted queue no longer accepts any conversations from customers but the group name is still available in historical reporting so you see how many conversations the queue received in the past.





## [](#before-and-after-salted-cx)Before and After Salted CX

Salted CX data may provide a different level of detail depending on when a data source was connected to Salted CX.

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

Our recommendation is to connect the data source to Salted CX as soon as possible even when users do not have yet access to Salted CX. This approach enables to gathering deeper history time history with full set of supported features.





![](https://www.notion.so/icons/warning_yellow.svg?mode=light)

Always exercise additional caution when acting on data before Salted CX was connected. We recommend to review our documentation for the given data source in case the metrics before connecting Salted CX significantly differs from metrics after connecting Salted CX. 





### [](#after-salted-cx)After Salted CX

Salted CX primary focus is to provide the most value from the moment you connect the data source. Because of this Salted CX tries to use the most granular method for retrieving the data even when it is not available for conversations that happened in the past. This may lead to some differences between data discussed in the next section.

### [](#before-salted-cx)Before Salted CX

Depending on the data source availability of data may be limited due to the connected data source features, architecture, limitations, and configuration. The exact impact on data depends on the mentioned factors.

The focus when loading the historical data is:

- Have the same way of calculating metrics and attributes. Salted CX tries to have no or minimal differences in how data are represented in both time frames.

- Provide as much facts and attributes as possible. Historical data may not contain the same level of granularity.

There are certain issues we have identified in different data sources in the table below.

| Issue | Description and Mitigation |
|---|---|
| No data available | Some data sources may keep data only for a limited time. After that time they provide no data or the data are not granular enough to convert them to the Salted CX [Logical Model](https://help.salted.cx/en/collections/1755206106-logical-model). This might be for example when the data are available only in an aggregated form via a historical API. There is typically no workaround unless the customer has backup data. In such cases, they can use Ingest API to load the historical data. |
| Less attributes | Some data sources may contain less information in permanent storage than they produce on the fly. Some data sources enable to consumption stream of very granular events that provide very detailed information about any update in the data source. However, these events are stored only for a limited time and after that, they are deleted from the data source. Only less detailed data are available permanently in the data source. |
| State transitions are not available | Conversations may go through state transitions during multiple engagements in the conversation. This would typically be reflected in engagement attributes such as Reason, Outcome, etc. Some data sources only contain information about the last state of the conversation (or a corresponding entity in the source system). This may manifest itself by having less granularity in the past data and missing visibility into how agents progressed when working on conversation especially if there were more agents involved. This may also lead to missing queue engagements, invitation engagements, and other transitions in the customer journey. |
| Engagement and other activity attribution issues | Most data sources contain only information on who is the agent that handled an engagement but do not contain details about the organization hierarchy (team in which the agent was) when the agent handed that engagement. They only contain information about the current organization structure. When agents are moving in the company organization hierarchy or the structure itself changes the teams, departments, locations, and other organization units in which agents are now may be different from the organization units in which agents were when the engagement happened. This leads to potentially skewing metrics based on engagements and activities before connecting to Salted CX. When working with trends and other metrics over a longer time scale make sure then when interpreting metrics you consider the possibility of agents moving around. |

---

## Live Conversations Setup

Source: https://help.salted.cx/en/articles/live-conversations-settings


Article short description

To stat using Live Conversations in Your Salted CX account follow these steps:

- [Create Salted CX account](https://help.salted.cx/en/articles/live-conversations-settings?v=24f5d3a2a8dc81f49249000c3e502787#25a5d3a2a8dc80ec92ecdff06dbca803). We recommend to create a testing account even when you already have a Salted CX account.

- [Enable Live Conversations](https://help.salted.cx/en/articles/live-conversations-settings?v=24f5d3a2a8dc81f49249000c3e502787#25a5d3a2a8dc8082a128c07ae2d72c82). Live Conversions are disabled by default for new accounts.

- [Give agents permissions to use Live Conversations](https://help.salted.cx/en/articles/live-conversations-settings?v=24f5d3a2a8dc81f49249000c3e502787#25a5d3a2a8dc80658230e415a62fd08d). Setup your identity provider so it gives users (agents) who handle the customers permissions to access Live Conversations.

- [Integrate with Your Logic](https://help.salted.cx/en/articles/live-conversations-settings?v=24f5d3a2a8dc81f49249000c3e502787#25a5d3a2a8dc8001b814f3993fc2a842). Optional. Integration with Your Logic enables you to implement a custom behavior based on rules, workflows or using large language models to resolve the customer requests.

- [Integrate Universal Chat into your web app](https://help.salted.cx/en/articles/live-conversations-settings?v=24f5d3a2a8dc81f49249000c3e502787#25a5d3a2a8dc806e9d70e09cec819738). Optional. Enables agents and Your Logic to handle conversations from your website.

- [Connect to WhatsApp numbers](https://help.salted.cx/en/articles/live-conversations-settings?v=24f5d3a2a8dc81f49249000c3e502787#25a5d3a2a8dc808f93b1d491502494f1). Optional. Enables agents and Your Logic to handle conversations from WhatsApp.

## [](#create-salted-cx-account)Create Salted CX Account

Live Conversations can be used in any Salted CX account. Conversations that happen in Salted CX are visible with conversations from other [connected platforms](https://help.salted.cx/en/collections/1755256026-integrations).

Learn how to [create a Salted CX account](https://help.salted.cx/en/articles/account).

![](https://www.notion.so/icons/warning_yellow.svg?mode=light)

We strongly recommend to use a separate Salted CX account for testing Your Logic and training agents. This prevents the testing conversations to be mixed in analytics with the production traffic.





## [](#enable-live-conversations)Enable Live Conversations

Enabling Live Conversations requires to contact Salted CX. Please reach to us at <help@salted.cx> to enable Live Conversations for you. Once enabled users who have the appropriate permissions will see [Live](https://help.salted.cx/en/collections/1755577083-live-conversations) tab on top of the application.

## [](#give-permissions-to-agents)Give Permissions to Agents

You need to give users [permissions](https://help.salted.cx/en/articles/permissions) to access live conversations. This is done in your identify provider such as [Google](https://help.salted.cx/en/articles/identity-provider-google) or [Okta](https://help.salted.cx/en/articles/identity-provider-okta).

## [](#integrate-with-your-logic)Integrate with Your Logic

Integrating Live Conversations with [Your Logic](https://help.salted.cx/en/collections/1755764337-your-logic) enables you to handle the customer requests automatically or to respond to different events.

Learn more about [Your Logic](https://help.salted.cx/en/collections/1755764337-your-logic) and [Your Logic Implementation Tips](https://help.salted.cx/en/articles/your-logic-implementation-tips?v=24f5d3a2a8dc81f49249000c3e502787).

## [](#integrate-universal-chat-to-your-web-app)Integrate Universal Chat to Your Web App

If you want agents or Your Logic to handle the customer conversations from your web site you need to use Salted CX the customer facing web widget.

Learn more about [Universal Chat Integration](https://help.salted.cx/en/articles/universal-chat-integration?v=24f5d3a2a8dc81f49249000c3e502787).

## [](#connect-to-your-whatsapp-numbers)Connect to your WhatsApp numbers

If you want agents or Your Logic to handle conversations that originate from your WhatsApp customers. You manage your WhatsApp phone numbers directly in your Mete account. You only need to provide credentials for Salted CX to access the WhatsApp API.

Contact Salted CX at <help@slted.cx> to help you with the WhatsApp setup.

*Tags: Live Conversations*


---

## Okta as Identity Provider

Source: https://help.salted.cx/en/articles/identity-provider-okta


In Okta you can choose to authenticate using [SAML](https://help.salted.cx/en/articles/identity-provider-okta#bca9b963f15e47b28920b6eeccd8e400) or [OIDC](https://help.salted.cx/en/articles/identity-provider-okta#f1fa1b6081a74a60b293a61da77b7799). There is no difference between those options in Salted CX. You can choose the one that you prefer.

After you setup the application you have to assign it to users and choose permissions for them. See [Assign Salted CX app to a user or a group](https://help.salted.cx/en/articles/identity-provider-okta) for details.

## [](#authentication-via-saml)Authentication via SAML

### [](#add-salted-cx-as-a-saml-application-to-okta)Add Salted CX as a SAML application to Okta

1. In Salted CX Settings, go to Single Sign On → SAML page and copy the SSO URL and the Audience URI.

2. In you Okta instance go to Okta Admin console → Applications → Applications → Create App Integration.

3. Select SAML 2.0.

4. Fill in the app name and check Do not display application icon to users.

5. Fill the Single sign-on URL and Audience URI fields with the values from step one.

6. Set up the following required Attribute Statements:| Name | Name format | Value |
    |---|---|---|
    | email | Basic | `user.email` |
    | given\_name | Basic | `user.firstName` |
    | family\_name | Basic | `user.lastName` |
    | cxsaltedpermissions | Basic | Value depending on what permissions you want to give the users by default. |
    
    
    
    ![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)
    
    To learn more about how permissions work, read the [Permissions](https://help.salted.cx/en/articles/permissions) docs.

7. Click Next and Finish to create the application.

8. Copy the Metadata URL found in the Sign On tab of the Okta application you just created.

9. Go back to Single Sign On page in Salted CX settings and paste in the Metadata URL.

## [](#create-a-bookmark-app-to-show-salted-cx-in-okta-dashboard)Create a Bookmark App to show Salted CX in Okta Dashboard

Currently, we do not support identity provider initiated authentication flow. If you want to display a Salted CX app tile to your users in Okta dashboard or in the Okta Browser Plugin, you can create a Bookmark App.

1. Go to Okta Admin console → Applications → Applications → Browse App Catalog.

2. Search for Bookmark App.

3. Fill the application label and the URL of your Salted CX instance, for example `https://company.us.salted.cx`.

## [](#authentication-via-openid-connect-oidc)Authentication via OpenID Connect — OIDC

### [](#add-salted-cx-as-an-oidc-application-to-okta)Add Salted CX as an OIDC application to OKTA

1. In Salted CX Settings, go to the Single Sign On → OIDC page and copy the Redirect URI.

2. Go to Okta Admin console → Applications → Applications → Create App Integration.

3. Select OIDC - OpenID Connect → Web Application.

4. Pick and fill in the app name (e.g Salted CX, but you can choose whatever name you like) and check the Authorization Code and Refresh Token grant type.

5. Add the URL from step one to Sign-in redirect URIs. Leave Sign-out redirect URIs empty.

6. Select Skip group assignment for now and Save.

7. After the app is created, copy the Client ID and Client secret and paste them into the Salted CX OIDC settings page.

### [](#add-cxsaltedpermissions-attribute-to-salted-cx-oidc-app)Add cxsaltedpermissions attribute to Salted CX OIDC app

1. In Okta Admin console, go to Directory → Profile Editor and find the Salted CX OIDC app you created in the previous section.

2. Click on the app to open its Profile Editor and click on the Add attribute button.

3. Fill in the following values and save:
    - Data type: string
    
    
    - Display name: Salted CX Permissions
    
    
    - Variable name: cxsaltedpermissions
    
    
    - Attribute required: yes
    
    
    - User permissions: Read Only

## [](#assign-salted-cx-app-to-a-user-or-a-group)Assign Salted CX app to a user or a group

1. In Okta Admin console, go to Applications → Applications

2. Click on the Salted CX app to open its details page.

3. Select the Assignments tab.

4. Click on the Assign button and select the user or group you want to assign the app to.

5. Click Assign

6. Fill in the `cxsaltedpermissions` attribute based on the permissions you want to grant the user or the group.

*Tags: Users*


---

## Protected Information

Source: https://help.salted.cx/en/articles/protected-information


![](https://www.notion.so/icons/warning_yellow.svg?mode=light)

Salted CX reduces the exposure of protected information to users but does not eliminate it. The accuracy of detection depends on many factors. Salted CX may also redact information that is does not need to be protected. You can still view this redacted information if needed.





We automatically detect potentially personally identifiable and other sensitive information in conversation content. By design, we do not show such data in reporting and other areas of our application.

We show placeholders instead of potentially protected information in the conversation content. You can still understand the conversation even with the redacted information. You have to explicitly ask for access to the protected information. We log access to individual pieces of information.

| Information Type | Display Pattern | Example |
|---|---|---|
| Card Number | `●●● <last four digits>` | `●●● 1234` |
| Email | `<first letter>●●●@<domain>` | `v●●●@gmail.com` |
| Phone | `<national prefix if any> ●●● <last two digits>``●●● <last two digits>` | `+420 ●●● 12``●●● 12` |



[https://app.notion.com/p/saltedcx/Redact-Protected-Information-in-Live-30c5d3a2a8dc80cf9a9ec9b0151b8ac1?source=copy\_link#30c5d3a2a8dc8013871ad03e27d6add0](/30c5d3a2a8dc80cf9a9ec9b0151b8ac1)

![](https://media.notiondesk.so/upload/69b9586460479443610506.png)

## [](#detected-information)Detected Information

The following table lists all pieces of information that we detect. If the information is protected, we replace it with a placeholder in the customer journey. If the information can be used as a contact in the customer journey, you can use it to connect conversations across channels.

|  | Protected | Contact In Customer Journey | Description |
|---|---|---|---|
| Phone Number | Yes | Yes | Phone number. |
| Email | Yes | Yes | Email addresses. |
| Credit Card Number | Yes | No | Credit card numbers of part of them. |



## [](#reveal-protected-information)Reveal Protected Information

You can reveal any protected information if you have permission to view person information you can click on the redacted piece of conversation to reveal it. You need to provide a reason why you need to view the protected information.

![](https://media.notiondesk.so/upload/69b958666adfb954494709.png)

![](https://media.notiondesk.so/upload/69b95867b20ed110612755.png)

The following reveal options are available:

- Reach the customer — you need the information to contact the customer.

- Verification or process review — you need to see the information in order to check that the transaction was correctly handled.

- Unreasonable redaction — you suspect that the redacted information is should not be redacted.

- Other — None of the available options apply.

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

All access to personal information is logged including time, user, piece of information that the user accessed and the reason provided by the user to access the protected information.

*Tags: Customer Journey*


---

## Questions

Source: https://help.salted.cx/en/articles/questions


Questions enable you to manage questions that reviewers answer when reviewing customer journeys or that Salted CX AI answers using auto reviewers.

![](https://media.notiondesk.so/upload/698d912bcdb31339165927.png)

## [](#navigation)Navigation

The navigation contains questions organized into categories. You can search in questions, use filters and sorting to show those questions that are relevant for you.

Each question has an icon that corresponds to the question type. There are also icons that indicate the following features:

- Built-in question with a lock icon. You cannot delete these questions. They are provided out of the box and they have a known meaning in Salted CX.

- Auto reviewed questions with spark icons. These questions have an auto reviewer associated with them. This means that Salted CX analyzes 100% of conversations to answer these questions for them.

## [](#question-category)Question Category

You can organize questions into categories. Categories help to keep questions organized in the navigation. Question Category is also an attribute in reporting that you can filter by an segment by in metrics, visualizations and dashboards.

![](https://media.notiondesk.so/upload/698d912ec143d329691934.png)

To change the question category:

- Click the existing category ![:r1:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/cbece7ea-90d1-42be-b944-7d3a40472c0a/Circle_1.png)

- Search ![:r2:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/828ec6f6-6da7-41e1-ab7d-81f376318b90/Circle_2.png) for the category you want to put the question into

- If the category does not yet exist press Create New Category ![:r3:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/6a0e6eb2-4742-4445-80a6-8be77bab104f/Circle_3.png)

- Or press an existing category

## [](#question-name)Question Name

You can change the question name by clicking on it and typing a new name.

![](https://www.notion.so/icons/warning_yellow.svg?mode=light)

Do not rename questions that are currently in use to have a different meaning. This would lead to missleading reporting. Salted CX uses the question PID (not the name) for identifying the question. Changing the question name meaning would make the past reviews seem to be answers to a different question. Rename questions to make the clearer and easie to undertand.





You can also modify other question properties:

- Description. Use the description to clarify to reviewers what exactly you are asking them to focus on and provide additional details on criteria for different answers.

- Business Goal. Use the business goal to clarify why answering the question and finding reviewed conversations with these questions is important for your business.

## [](#new-questions)New Questions

To create a new question:

- Press New Question in the bottom left corner.

![](https://media.notiondesk.so/upload/698d91314081c683209144.png)

- Choose the question type you want to create.

Each question has a specific options you can edit. Some questions also enable you to create auto reviewers. Auto reviewers just like humans look at the conversations and answer the questions. The advantage of auto reviewers is that they review 100% of conversations.

---

## Salesforce Integration

Source: https://help.salted.cx/en/articles/integration-salesforce


You can connect multiple Salesforce instances to a single Salted CX account and mix data in Salesforce with other data sources.

## [](#supported-features-in-salesforce)Supported Features in Salesforce

Salted CX relies on [Salesforce Omni-Channel](https://help.salesforce.com/s/articleView?id=sf.omnichannel_intro.htm&type=5) to be enabled. Salesforce Omni-Channel manages work assignments to agents including handling of customers. This makes it easier to understand agent performance in a contact center.

Salted CX supports the following features in Salesforce:

- Reporting on Salesforce AgentWork that tracks what time agents spent handling customers and working on other tasks that are distributed using Salesforce Omni-Channel.

- Reporting on Salesforce Service Presence agent statuses to understand when the agents are ready to handle customer conversations and whether they adhere to their schedule.

- Reporting on responded customer surveys.

- Turns in the customer journey for individual engagements.

## [](#salesforce-omni-channel-overview)Salesforce Omni-Channel Overview

Salesforce Omni-Channel is a feature that enables agents to fork on pieces of work called AgentWork. Salesforce Omni-Channel routes individual AgentWork items to agents based on settings that can customized directly in Salesforce.

AgentWork carries any kind of work an agent can accept and spend time on. Commonly this is a communication with a customer but it can also be an administration task.

## [](#customer-journey)Customer Journey

Salted CX roughly translated the following entities in Salesforce to corresponding items in the customer journey. It is useful to learn about [Customer Journey Structure](https://help.salted.cx/en/articles/model-customer-journey-structure) to better understand how Salesforce objects translate to Salted CX concepts.

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

Salted CX enables merging traffic from multiple platforms into a single storage. Each supported platform has a different vocabulary and concepts. Salted CX introduces its own concepts unified across supported platforms that strive to balance ease of use and flexibility. Check [Logical Model](https://help.salted.cx/en/collections/1755206106-logical-model) and [Customer Journey Structure](https://help.salted.cx/en/articles/model-customer-journey-structure) to understand key concepts in Salted CX. Depending on the quality of data available in individual supported platforms there are platform-specific exceptions and limitations that we cover in articles dedicated to individual platforms| Concept in Salted | Objects in Salesforce |
|---|---|
| Customer | [Contact](https://developer.salesforce.com/docs/atlas.en-us.object_reference.meta/object_reference/sforce_api_objects_contact.htm). Currently Salted CX treats a single Salesforce Contact as a customer. |
| Contact | [Contact](https://developer.salesforce.com/docs/atlas.en-us.object_reference.meta/object_reference/sforce_api_objects_contact.htm). Salesforce Contact is used for both unique contact and the customer attribute that groups multiple contacts together. |
| Conversation | [Case](https://help.salesforce.com/s/articleView?id=sf.cases_def.htm&type=5). Other objects in Salesforce point towards which cases they are related to. If this relationship can be traced back to the case the engagements are |
| Engagement |  |
| Turn | Chat EngagementsContent from Salesforce LiveChatTranscript objects for chat conversations. Individual messages are extracted from the complete chat transcript. Email EngagementsContent from individual Salesforce EmailMessage objects. Call EngagementCall engagements from Salesforce do not have turns. |
| Review | Individual Salesforce SurveyResponseResult items. |











## [](#engagements)Engagements

Engagements represent customers’ engagements with individual agents and other services (like a queue). If an agent is handled by multiple agents an engagement is created for every single engagement.

| Engagement Type | Description |
|---|---|
| Agent | Created for every Salesforce AgentWork that an agent accepted to work on. It can be a conversation on any channel that uses [Salesforce Omni-Channel](https://help.salesforce.com/s/articleView?id=sf.omnichannel_intro.htm&type=5). These types of engagements are those you will typically be reporting for agent performance. |
| Invitation | Created for situations when an agent is asked to join a conversation by accepting Salesforce AgentWork. Invitation engagements are created only for situations when an agent misses or rejects the Salesforce AgentWork. This type of engagement enables you to find situations when agents are overloaded, conversations are offered to them even when they are supposed to work on something else, or they can point to a behavior issue. |
| Queue | Created for every Salesforce AgentWork that is in the Queue regardless of whether an agent accepts it or not. This represents a customer (or a task) waiting for an agent to be handled. |
|  |  |



![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

Typical handled Salesforce AgentWork creates at least 2 engagements. One engagement has Engagement Type = Queue and the other has Engagement Type = Agent. When you create metrics or just count engagements make sure you focus on the right type and do not double count in some cases. The general rule of thumb for creating metrics on top of the Engagement data set is that unless you have a specific use case you should filter for engagement type specific for your use case.





## [](#turns)Turns

Salesforce has multiple ways how agents can communicate with customers. Depending on the method the turns are created differently.

### [](#emails)Emails

Individual email messages associated with a case, lead, or opportunity create individual turns. If the message is not part of an Omni-Channel AgentWork each outgoing message also produces a separate agent engagement.

### [](#live-chats)Live Chats

Salesforce Live Chat content is stored as pure text without internal structure. Salted CX analyzes the text content of live chats to create individual turns and associate them with the corresponding agents.

## [](#customer-surveys)Customer Surveys

Individual responses to Salesforce Customer Surveys are represented as individual [Reviews](https://help.salted.cx/en/articles/model-review) in Salted CX. Each customer survey may contain multiple questions. Responses to these individual questions produce multiple Reviews.

Customer Surveys in Salesforce are by default associated with the Salesforce Contact object which is equivalent to a [Customer](https://help.salted.cx/en/articles/model-customer) in Salted CX. Salted CX requires items in the Review data set to be linked to a specific [Engagement](https://help.salted.cx/en/articles/model-engagement). Salted CX uses heuristics to determine to which engagement the review is linked.

Salted CX uses heuristics to attribute the customer surveys to the engagement that immediately precedes the invitation to customer journey (based on Salesforce Survey Invitation creation time). If there is no engagement with the customer the survey results are not stored in the current implementation.

If a customer changes their answer in a customer survey only the most recent response will be stored in reviews.

![](https://www.notion.so/icons/warning_yellow.svg?mode=light)

Be mindful when acting on customer surveys. The survey results are attributed to engagements immediately preceding the invitations to customers to provide feedback. However, customer perception might be influenced by events that happened in previous engagements and even events that happened after the engagement it is attributed to. Drill down to the customer journey to better understand the complete customer experience. We recommend using surveys as a discovery tool for potential issues rather than using the review score average for decision-making without reviewing the customer journey first.





## [](#metrics-overview)Metrics Overview

This section covers base metrics. These metrics are further used in calculations.

| Metric | Description |
|---|---|
| Agent Engagements | Counts the number of Salesforce AgentWork in which the agent talked with a customer. Any Salesforce AgentWork that was canceled before an agent accepted the work is NOT listed in this. Counts the number of tasks that are associated with the agent. |
| Available Time | The time an agent spent in Salesforce UserServicePresence status that has Salesforce attribute `IsAway` set to `false`. |
| Engagement Time | Salesforce Omni-Channel The time between the moment when an agent accepts a Salesforce AgentWork and the moment the agent switches to wrap up (AfterConversation phase) or completes the AgentWork (when the status is closed in Salesforce). In case the Salesforce AgentWork is completed but not accepted by the agent we fallback for the start of the engagement to the time when the Salesforce AgentWork was offered to the agent. This is the closest approximation we get and may lead to inflated Engagement Time depending on your environment. |
| Engagements within Service Level | Number of engagements that have attribute `Service Level` set to value `Within SLA`. This attribute is now set based on the time between the time when the Salesforce AgentWork is created and the time when the AgentWork is accepted by an agent. Currently, the threshold is set to constant 60 seconds for any agent work. Can be changed on request. |
| Focus Time | The time agent actively worked on the Salesforce AgentWork. Tracks when the AgentWork item is opened by an agent and in focus in Salesforce. If the Wrap Up phase is enabled in Salesforce it also counts the Wrap Up Time. Focus Time is available only for Salesforce AgentWork that is routed using the tab-based capacity model in Salesforce. |
| Invitation Time | Time it took the agent to accept, decline or miss the request to handle the AgentWork item. |
| Invitations | Counts Salesforce AgentWork that was either missed or declined by an agent. Invitations are NOT created for Salesforce AgentWork that is accepted by an agent. |
| Missed Invitations | Number of Salesforce AgentWork records missed by agents. |
| Rejected Invitations | Number of Salesforce AgentWork records rejected by agents. |
| Queue Engagements | All Salesforce AgentWork that was placed in a queue including Salesforce AgentWork. This includes Salesforce AgentWork which no agent worked on. This metric is useful to understand actual traffic in the contact center. |
| Wrap Up Time | The total time an agent spends in the phase called After Conversation Time in Salesforce is associated with AgentWork. This is the total time including all extensions. Wrap Up Time is not available for engagements that are not handled via Salesforce Omni-Channel. |



There are a lot of other metrics built on top of the metrics above. See [Metrics Reference](https://help.salted.cx/en/articles/1755225286-metrics-reference) for more information.

## [](#metric-calculation-formulas)Metric Calculation Formulas

Calculation of basic metrics using objects and fields in Salesforce.

| Metric | Engagements Matching Conditions | Value from Salesforce |
|---|---|---|
| Activity Time | Engagement  ⏵  Type = `Agent Status` |  |
| Engagement Time | Engagement  ⏵  Type = `Agent` |  |
| Focus Time | Engagement  ⏵  Type = `Agent` | = AgentWork  ⏵  ActivityTime Focus Time is available only for Salesforce AgentWork that is routed using the tab-based capacity model in Salesforce. |
| Invitation Time | Engagement  ⏵  Type = `Agent` | = AgentWork  ⏵  SpeedToAnswer |
| Invitation Time |  | = (AgentWork ⏵  DeclineDateTime) - (AgentWork ⏵  CreatedDate) |
| Wait Time | Engagement  ⏵  Type = `Agent` |  |
| Wait Time | Engagement  ⏵  Type = `Queue` |  |
| Wrap Up Time | Engagement  ⏵  Type = `Agent` | = AgentWork ⏵ AfterConversationActualTime |



## [](#historical-data)Historical Data

Before Salted CX is enabled the data in Salesforce might not provide the same level of granularity and accuracy as after Salted CX is enabled. Salesforce does not store all the details that are necessary to restore data to the same detail as with the regular 15-minute loads.

The following data may be inaccurate for the time before using Salted CX:

- Engagement attribution to organization hierarchy including teams, departments, and locations. Salesforce stores the latest association between the user and their teams, departments, and other organization units. Salesforce does not provide past assignments to organization units so Salted CX attributes all engagements before the time it is enabled to the organization units the agent was assigned at the moment when Salted CX got enabled.

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

We recommend connecting Salesforce to Salted CX as soon as possible. This enables Salted CX to retrieve data granularity that would get lost as data gets updated.





## [](#data-quality-issues)Data Quality Issues

This section highlights cases in which the Salesforce data may not be accurate and Salted CX uses heuristics and other methods to process them to the best possible result.

### [](#live-chat-transcripts)Live Chat Transcripts

Salesforce Live Chat transcripts are a single unstructured text field. Salted CX makes the best effort to parse the transcript and attribute individual messages to agents and customers. Some scenarios are impossible to interpret accurately.

Known scenarios when the attribution of turns is not accurate:

- A participant copies and pastes the history of the chat to the conversation. Because the past conversation has the same pattern it is hard to identify whether the pasted content is regular turns or they are part of another turn. In this case, the pasted text content produces new turns and Salted CX does not recognize they are pasted content.

### [](#overlapping-agent-statuses)Overlapping Agent Statuses

Due to rounding and race conditions in Salesforce, the agent activity statuses reported from Salesforce sometimes overlap by a few seconds. This may lead to misleading metrics that could show that an agent spent in an agent status more time than possible.

Salted CX expects that the agent statuses do not overlap so during the data transformation it cuts the agent status activity if there is a new activity that starts while the previous one is not yet finished. This may lead to a few-second differences in reported activity time.

## [](#limitations)Limitations

Salesforce enforces limits on API calls that influence how much data can be loaded from Salesforce in a given time frame. These limits typically to not affect incremental loads as these loads pull only small volume of data.

![](https://www.notion.so/icons/warning_yellow.svg?mode=light)

When you perform mass updates in Salesforce such as updating one field in large volume of objects this causes large scale updates. When Salted CX detects large volume of objects were updated in a given time window it skips those updated objects to prevent hitting Salesforce limits and thus disabling subsequent incremental loads. Depending on what objects have been mass updated the data may be incomplete for the time affected time period. When updating objects historically consider whether the update is necessary for older data and if so whether the update can be done incrementally (updating batches of objects distributed over longer time period).





## [](#additional-resources)Additional Resources

The following articles cover Salesforce integration in additional detail:

- [Setup Salesforce Integration](https://help.salted.cx/en/articles/1769877319-setup-salesforce-integration)

*Tags: Integration*


---

## Segmentation

Source: https://help.salted.cx/en/articles/visualization-segmentation


Segmentation enables you to [aggregate](https://help.salted.cx/en/articles/1755250946-aggregations) metrics by an attribute of choice. In Salted CX you can use any attribute in the [Logical Model](https://help.salted.cx/en/collections/1755206106-logical-model) for segmentation of metrics.

## [](#visualizations)Visualizations

The easiest way to segment a metric is to use any Attribute in a visualization. Metrics are very generic and can be easily segmented by any attribute that makes sense based on Logical Model structure. Visualization editor hides attributes that you cannot use because the metric cannot be segmented by them.

![](https://media.notiondesk.so/upload/698b116da8008508275299.png)Drag and drop Agent to view the metric segmented by an agent

![](https://media.notiondesk.so/upload/698b1170e1726910663068.png)Drag and drop Queue to view the metric segmented by an Agent an a Date

![](https://media.notiondesk.so/upload/698b11749fc85753695491.png)Visualization segmented by Agent and Month

## [](#dates-and-time)Dates and Time

There are multiple dates and times options that enable you to segment by when an enagegement started, engagement ended, review was created, etc. Additionally date and times have a structure. So you can choose the granularity that you use for segmentation by any date and time.

![](https://media.notiondesk.so/upload/698b1177468fa284870445.png)

To choose the granularity in visualizations:

- Press group by under the date and time

- Choose the granularity in the menu

- Press More options for additional ways to segment the metrics

*Tags: Visualizations*


---

## Your Logic Response Examples

Source: https://help.salted.cx/en/articles/your-logic-response-examples


Your Logic enables you to tell Salted CX what to do during the conversation. Your Logic enables you to execute a sequence of multiple actions. This article lists some useful examples that handle certain scenarios in a way that attempt to focus on quality of the conversations.

## [](#escalation-to-human-agents)Escalation to Human Agents

This is the scenario when Your Logic cannot resolve the customer request and needs a human assistance. Asking agents for help asks agents to join the conversation. When the agents join the conversation Your Logic still receives requests and can continue to engage in the conversation.

In this scenario we do three steps:

- Send message to the customer to manage their expectations and let them know they may wait a little longer for an answer.

- Save a note with a summary for the human agent what they should focus on.

- Tell Salted CX that an agent is needed to help with the conversation.

```json
{
	"requestId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",

	"actions": [
		{
			"type": "MESSAGE",
			"content": "Sorry, I do not know about that. Give me a moment to connect you with a human colleague."
		},
		{
			"type": "NOTE",
			"content": "The customer is asking about a product not mentioned in our knowledge base - Star Plan."
		},
		{
			"type": "NEEDS_HELP",
			"needsHelp": true
		}
	]
}
```

## [](#invite-external-agent-and-manage-customer-expectations)Invite External Agent and Manage Customer Expectations

Inviting external agents with creating a note for the external agent and letting the customer know the response may take a while.

```json
{
	"requestId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",

	"actions": [
		{
			"type": "MESSAGE",
			"content": "We have invited our partner to help you with these questions. Note that it make take a few hours for them to respond as they may be on the trip and not attending their computer. Let us know if there is somehting else we can help with in the meantime."
		},
		{
			"type": "NOTE",
			"content": "The customer is asking about a product not mentioned in our knowledge base - Star Plan."
		},
		{
			"type": "INVITE_EXTERNAL_AGENT",
			"email": "email-of-the-external-agent@partner.com",
			"name": "Partner Support",
			"subject": "Help with a customer conversation",
			"message": "Hello, please join this conversation to help the customer with their questions about Star Plan.",
			"expires": "2026-12-31T10:30:00Z"
		}
	]
}
```

*Tags: Your Logic*


---

## Agent Guide to Live Conversations

Source: https://help.salted.cx/en/articles/1758108157-agent-guide-to-live-conversations


Article short description

Live conversations enable you to have conversations with customers from one screen.

![](https://media.notiondesk.so/upload/68d644c8a3005825070264.png)

## [](#how-to-navigate)How to Navigate

On the left, there is navigation that enables you to jump between conversations and thus customers.

My Conversations ![:r1:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/cbece7ea-90d1-42be-b944-7d3a40472c0a/Circle_1.png) are conversations that you currently participate in. Keep their number ![:r2:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/828ec6f6-6da7-41e1-ab7d-81f376318b90/Circle_2.png) reasonable so you do not have to multitask too much, and do not let customers wait for your responses. Agree with your team leader on what the best limit is for you. Industry standard is around 4 parallel conversations per agent.

Help Needed ![:r3:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/6a0e6eb2-4742-4445-80a6-8be77bab104f/Circle_3.png) lists conversations that you should join if you have capacity. You have to click the Join button ![:r4:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/49964e58-e0e9-40b5-b973-00c416e5d0bc/Circle_4.png) in a conversation to view its content.

Recently Left ![:r5:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/a8d7fc85-01c2-4beb-ae57-18073a27a40e/Circle_5.png) contains conversations in which you participated, but you have already left them. You can open it when you need to return to a conversation that you have left prematurely.

## [](#understand-the-conversation)Understand the Conversation

When you open a conversation, ensure you understand what the customer is asking you to do and what has already occurred. In some conversations, there might be a previous conversation with a bot. Ensure that you naturally follow up on what has already happened.

![](https://media.notiondesk.so/upload/68d642d5b5ce4316216585.png)

- If the customer name is known we can see it on top ![:r6:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/22961b53-f52d-4017-87e3-e0ab43ddd029/Circle_6.png). If the customer name is not known you will see the channel name with an ID number.

- Scroll up in the page with messages, to see more from the history with the customer. You can view the previous conversations even those happened in a different platform.

- Messages from you and other agents are blue ![:r7:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/9e5e9e5f-9b80-4656-8d16-a78ef863eb57/Circle_7.png).

- Messages from the customer are green ![:r8:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/bd34cd7e-cbac-4650-9d97-2a4412a47520/Circle_8.png).

- Messages from bot (AI) are purple ![:r9:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/72b59471-92ba-446c-94f7-8d19849cfc6a/Circle_9.png). Often a bot can start the conversation

- Messages from external agents are yellow. External agents are agents that are not users in Salted CX but were invited to help with specific conversations.

- There might be special kind of content such as questions ![:r10:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/39cc41d0-405c-4a91-bb9a-f1c584d8fb1a/Circle_10.png). These turns enable more complex integrations for both customers and agents.

## [](#resolve-the-conversations)Resolve the Conversations

You have a text field to provide the customer with the answer. You can utilize additional tools to enhance your productivity.

- Ask question ![:r12:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/b6a745ee-4a40-42ab-b73a-e66d599f7442/Circle_12.png). You can ask customers quickly a predefined question that gives them multiple options

- Working on it button ![:r13:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/ecf5bec7-0640-4f5a-928c-0f89d29f37ba/Circle_13.png). Press this button to send a canned message to the customer what assures the customer you are working on their issue.

- Prepared replies ![:r14:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/6ffa2e34-8d07-42f5-a33e-f3cdb7891ba5/Circle_14.png). Press this button to open a searchable menu containing prepared replies that can be sent to the customer. You can search for replies using their shortcut (shown in grey text in the menu) or by their content (shown in black).

![](https://media.notiondesk.so/upload/68d642d84df5a641549030.png)





- Improve reply. Just write a gist of the message and then type two dots `..` at the end of your reply to let Salted CX propose improved reply based on the previous conversation.





Once you believe you have completely resolved the customer request, click the Resolve ![:r18:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/270ca6e0-b4f0-427a-8f54-947da50b9aa4/Circle_18.png) button. This removes the conversation from My Conversations ![:r1:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/cbece7ea-90d1-42be-b944-7d3a40472c0a/Circle_1.png) and moves it to Recently Left ![:r5:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/a8d7fc85-01c2-4beb-ae57-18073a27a40e/Circle_5.png). If the customer writes back with a request, the conversation may appear in Help Needed ![:r3:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/6a0e6eb2-4742-4445-80a6-8be77bab104f/Circle_3.png) again.

## [](#escalations)Escalations

In case you do not know how to help the customer, you have these options:

- Request help ![:r17:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/3d7458c0-edc3-4769-b896-602c6c05e235/Circle_17.png). This will make the conversation appear in Help Needed ![:r3:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/6a0e6eb2-4742-4445-80a6-8be77bab104f/Circle_3.png) section of your colleagues. Customer is not aware of this action. You remain in the conversation and can still communicate with the customer. Any number of colleagues can be engaged in a single conversation.

- Share link with a specific person or a group. At any time you can copy the link to the conversation from a browser and share it with specific colleagues. If your colleagues are users in Salted CX they can sign in and join the conversation. You can share the link with one person or in a group communication channel (such as Google Chat group or Slack channel if you want to ask someone from a group of people).

Remember, multiple people may be speaking with the same customer simultaneously.

## [](#leave-conversations)Leave Conversations

You can leave conversations by pressing the Leave button ![:r19:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/d860a19a-3c86-4a84-b3cf-4055447d4e41/Circle_19.png) without marking them as resolved. Use this when you need to wrap up your work or when there is no way you can help, but someone else can assist with the conversation.

![](https://media.notiondesk.so/upload/68c91d81b4d88940307096.png)

Choose the correct reason why you are leaving the conversation. The reason is visible in the reporting, so choose the one that is true.

## [](#custom-buttons)Custom Buttons

You can have a set of buttons ![:r16:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/3eed8247-03a6-4994-b439-04ab2d7f10b4/Circle_16.png) that enable you to trigger actions without leaving the user interface. This set of buttons is unique for your company. Buttons can either trigger an action in the background or open windows in your browser.

## [](#other-participants)Other Participants

There might be multiple participants in a conversation. Live Conversations show you list of other people involved in a conversation. So you can see whether somebody else is also involved.

![](https://media.notiondesk.so/upload/68df92d865e22461756027.png)





## [](#performance-monitoring)Performance Monitoring

Salted CX tracks all activity in live conversations to ensure high-quality conversations and optimal performance. This is information available to you and your team leaders. You can access it in your dashboard and push to improve those metrics.

Major data points we track:

- Engagements volume. The number of your engagements or the number of engagements you have participated in. Handling conversations as fast as possible helps you to handle more conversations.

- Engagement time. How long you have participated in the conversation from the moment you clicked the Join button until you either mark conversation as resolved or leave it. Use [our tips](https://help.salted.cx/en/articles/1758108157-agent-guide-to-live-conversations#26f5d3a2a8dc8048938bcdd6f584ab4b) to resolve the conversations as wast as possible.

- Outcome monitoring. We monitor which reasons you use to leave conversations and whether they correspond with reality. Make sure when you mark conversations as resolved customers would consider them resolved. When leaving conversations ensure you chose the actual reason. All choices will be visible in dashboards.

- Customer request resolution. Depending on you company setup Salted CX can ask the customer whether the request was resolved after you mark the conversation is resolved and reopen it if they say that it is not resolved.

- Customer satisfaction. Depending on your company setup Salted CX can collect customer satisfaction and other feedback.

- Automatic Quality Assurance. Salted CX has a configurable AI that processes the content of the conversations and checks for grammar.

Salted CX enables importing various data points to monitor multiple metrics and determine whether you are meeting your targets.

## [](#text-reply-guidelines)Text Reply Guidelines

Always strive to respond to previous customer messages in a single message. Do not provide the responses in parts unless there is information the customer can already use to perform an action.

Let’s consider the following customer request:

![](https://www.notion.so/icons/chat_green.svg?mode=light)

Is my trip to Mt Blanc refundable?





Possible reply could be:

![](https://www.notion.so/icons/chat_blue.svg?mode=light)

Thank you for reaching out to us with your request. My name is John, and I will do my best to resolve your issue. I understand that you are asking about whether your trip to Mt. Blanc is refundable. Your trip to Mt. Blanc is refundable, as the trip is booked for 15 April and is still more than 72 hours away. According to our policy, you are eligible for a refund.





Check an alternative way to reply:

![](https://www.notion.so/icons/chat_blue.svg?mode=light)

Yes. You can refund your trip to Mt Blanc until 12 April. To refund this trip, [g](http://salted.cx/)o to your account and click the Refund button, or just ask me to refund.









There are several things done differently in the second reply:

- Start with direct and short answer. Customers should see what they look for first, not dig it out from the middle of a lengthly response.

- Do not tell customers you are there to resolve their requests. Customers expect this. Only tell them that you are working on the request when you expect to reply to take longer than they might expect and you need to tell them it may take a while.

- Confirm you are answering the actual customer question. The more complex the question is the you should confirm you are answering what the customer is asking for. Ideally merge the confirmation into the explanation of the answer.

- Provide an explanation to the customer. First this helps you to confirm you are actually answering the question. Secondly it helps to manage customer satisfaction in case they might not like the answer. The explanation should always try to communicate you empathize with the customer and try to be fair.

- Answer potential followup questions. If the original request often leads to follow-ups answer them righ with the reply. You can save the customer some time, increase the customer satisfaction and reduce chance of the customer contacting you in the future.

- Offer the next best action the customer. If there is a decision you want from a customer or some action they should take, tell the customers.

- Educate the customer about self-service. To make customers more independent consider offering them a self-service actions they can take. This decreases their dependency on your customer care and decreases your future load. Make sure you do not sound too pushy and you are acting in the customers’ own interests.

## [](#tips-for-good-performance)Tips for Good Performance

Push your performance.

- Find the number of conversations you can handle in parallel. Start with 2 so you can use the time when the customer is replying to you to help the other customer. Try to move to number around 4 to 5 over a few days. Switching between customers consumes time, so finding balance is necessary. Ensure your overall performance in your agent dashboard does not suffer by handling more customers.

- Use two dots at the end of the message to improve your reply. Need to reject the customer request? Try typing `no..` and depending on the context we will try to improve your answer so something like `I'm sorry, you cannot get refund in this case.` You will have the opportunity to review and modify the reply before sending.

- Use “Working on it” button ![:r13:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/ecf5bec7-0640-4f5a-928c-0f89d29f37ba/Circle_13.png). The button automatically sends the customer a short message that you are working on their request.

## [](#your-feedback)Your Feedback

Salted CX Live Conversations is a tool that is great but not perfect. If you think there is something in the tool that slows you down or makes your work more difficult than necessary, talk to your supervisors so they can pass your feedback further and improve your experience in the long run.

---

## Aggregations

Source: https://help.salted.cx/en/articles/1755250946-aggregations


Aggregations use individual facts to calculate higher level value that combines all individual values into one overall value.

In the simplest form aggregations calculate one value for all data in the contact center. Aggregations are typically combined with filtering and segmentation. [Filtering](https://help.salted.cx/en/articles/1755272271-filtering) enables to focus on data of interest and remove noise (extremely low and high values). [Segmentation](https://help.salted.cx/en/articles/visualization-segmentation) enables to calculate values for individual segments of data with different value of an attribute.

You can filter and segment directly in the metrics definition or when building the insights based on the metric. Filtering (not segmentation) can also be added when building dashboards.

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

Do not add unnecessary filtering and segmentation directly in the metric. Metrics can be fairly simple and generic so they can be used for building many different insights.





## [](#count)COUNT

Counts all distinct values of the attributes of the given attribute matching the criteria.

Syntax

```sql
SELECT COUNT(<span class="fw-bold nd-color--orange">attribute</span>)
```

Example

```sql
SELECT COUNT(<span class="fw-bold nd-color--orange">Engagement</span>) 
	WHERE <span class="fw-bold nd-color--orange">Type</span> = <span class="nd-color--red">"Agent"</span> AND <span class="fw-bold nd-color--orange">Outcome</span> = <span class="nd-color--red">"Sale"</span>
```

Number of engagements that were handled by an agent and ended with a sale## [](#sum)SUM

Shows total value of all individual values matching the condition.

Syntax

```sql
SELECT SUM (<span class="fw-bold nd-color--green">fact or metric</span>)
```

Example

```sql
SELECT SUM(<span class="fw-bold nd-color--blue">Wrap Up Time</span>) 
	WHERE <span class="fw-bold nd-color--blue">Wrap Up Time</span> > 3
```

Total time spent in wrap ups ignoring wrap ups that are 3 seconds and shorter## [](#avg)AVG

Shows an average value of a fact or a metric. Facts that are empty and metric that are empty do not influence the average. Averages are bread and butter for every contact center.

Syntax

```sql
SELECT AVG(<span class="fw-bold nd-color--green">fact or metric</span>)
```

Example

```sql
SELECT AVG(<span class="fw-bold nd-color--green">Wait Time</span>)
	WHERE <span class="fw-bold nd-color--orange">Type</span> = <span class="nd-color--red">"Queue"</span>
```

Average time the customer waited in the queue. Engagements that are not related to a queue are not counted in the average.## [](#max)MAX

Maximum value of a fact or a metric.

Syntax

```sql
SELECT MAX(<span class="fw-bold nd-color--green">fact of metric</span>)
```

Example

```sql
SELECT MAX(<span class="fw-bold nd-color--green">Wait Time</span>) 
	WHERE <span class="fw-bold nd-color--orange">Queue</span> = <span class="nd-color--red">"VIP"</span>
```

Maximum wait time of any customer in the queue VIP## [](#min)MIN

Minimum value of a fact or a metric.

Syntax

```sql
SELECT MIN(<span class="fw-bold nd-color--green">fact of metric</span>)
```

Example

```sql
SELECT MIN(<span class="fw-bold nd-color--green">Handling Time</span>) 
	WHERE <span class="fw-bold nd-color--orange">Outcome</span> = <span class="nd-color--red">"Success"</span>
```

Minimum handling time time that was required to successfully handle the customer## [](#median)MEDIAN

Median value of a fact or a metric. This means that half of the values are lower that the median and half of the values is higher than the median.

Syntax

```sql
SELECT MEDIAN(<span class="fw-bold nd-color--green">fact of metric</span>)
```

Example

```sql
SELECT MEDIAN(<span class="fw-bold nd-color--blue">Wait Time</span>) 
	WHERE <span class="fw-bold nd-color--orange">Queue</span> = <span class="nd-color--red">"L1 Support"</span>
```

That half of the customer waited less than the median in queue L1 Support![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

You can consider using MEDIAN as alternative to AVG for your overall metrics. Median is not so easily skewed by extremely high values used to calculate the average.





## [](#greatest)GREATEST

`GREATEST` chooses the highest value from those provided to it as parameters. It accepts both facts and metrics as its attributes.

Syntax

```sql
SELECT GREATEST(<span class="fw-bold nd-color--green">fact or metric</span>, <span class="fw-bold nd-color--green">fact or metric</span>, ...)
```

Examples

```sql
SELECT GREATEST(
	<span class="fw-bold nd-color--green">Average Customer Score</span>, <span class="fw-bold nd-color--green">Average Agent Score</span>, <span class="fw-bold nd-color--green">Average Quality Score</span>)
```

Picks the highest average score for the agent from different sources## [](#least)LEAST

`LOWEST` chooses the lowest value from those provided to it as parameters. It accepts both facts and metrics as its attributes.

Syntax

```sql
SELECT LEAST(<span class="fw-bold nd-color--green">fact or metric</span>, <span class="fw-bold nd-color--green">fact or metric</span>, ...)
```

Examples

```sql
SELECT LOWEST(
	<span class="fw-bold nd-color--green">Average Customer Score</span>, <span class="fw-bold nd-color--green">Average Agent Score</span>, <span class="fw-bold nd-color--green">Average Quality Score</span>)
```

Picks the lowest average score for the agent from different sources

---

## Conversation Examples

Source: https://help.salted.cx/en/articles/model-conversation-examples


A single Conversation with a customer can be a complex structure where multiple agents, bots and other actors are engaging with the customer. The real-world complexity of Conversations makes them difficult to analyze as they may have many attributes that change over time. To reduce this complexity Salted CX decomposes Conversations into units called Engagements.

Engagement are intended to be easier to use for analytics as they do not have a [complex inner structure](https://help.salted.cx/en/articles/model-customer-journey-structure). Use the following example to deeper understand metrics for complex conversations.

When using Salted CX Ingest API for loading engagements make sure you follow the structure of conversations outlined in this article and document differences from it in case the data source does not provide data that are granular enough.

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

The following sections only show attributes and facts of the Engagements that are the most relevant for the given example. In practice the [Engagements](https://help.salted.cx/en/articles/model-engagement) have more attributes and facts associated with them.





## [](#voice)Voice

Examples focused purely on voice channel without any self-service. All involved agents use voice.

### [](#inbound-voice)Inbound Voice

In typical Inbound voice call the customer typically waits in the queue. And agent is asked to picked up (or the call is directly assigned to them and started automatically) and the agent starts speaking.

![](https://media.notiondesk.so/upload/689dde4fa412c828629625.png)

Engagement Data Set

| Conversation | Engagement | Type | Agent | Conversation Start Time | Start Time | End Time | Queue Time | Invitation Time | Engagement Time | Wrap Up Time |
|---|---|---|---|---|---|---|---|---|---|---|
| Conversation A | Engagement Queue A | Queue | — | 8:00 | 8:00 | 8:15 | 0:15 | — | — | — |
| Conversation A | Engagement Agent A | Agent | Agent A | 8:00 | 8:15 | 8:40 | — | 0:05 | 0:15 | 0:10 |



Notes on the data:

- Engagement Queue A does not have an agent associated with it because the customer is not a responsibility of the agent.

- No Invitation Engagement is created as these engagements are created only in case an agent is asked to handle the customer but they miss or reject to join the conversation.

- End Time of Engagement Agent A is the end of the wrap up phase as it should indicate the end of any agent work related to the engagement.



Turn Data Set

During a phone conversation each turn will represent a continuous talk either by agent or a customer (or mixed channel if the channels are not separated).

| Engagement | Turn | Type | Participant | Turn Time |
|---|---|---|---|---|
| Engagement Agent A | Turn A | Talk | Agent | 8:15 |
| Engagement Agent A | Turn B | Talk | Customer | 8:20 |
| Engagement Agent A | Turn C | Talk | Agent | 8:25 |



Notes on the data:

- Typical call contains much more turns as the conversation can switch between participants quite quickly.

- Turns of the type Talk are available only in if transcripts are available for the call.



### [](#manual-preview-and-progressive-dialer-outbound-call)Manual, Preview and Progressive Dialer Outbound Call

Manual outbound calls are initiated by agents based on a list they have available (in their agent desktop) or some request to contact specific customer. The same conversation structure have outbound calls started by Preview Dialers.

![](https://media.notiondesk.so/upload/689dde559d328362742045.png)

Engagement Data Set

| Conversation | Engagement | Type | Agent | Conversation Start Time | Start Time | End Time | Queue Time | Invitation Time | Engagement Time | Wrap Up Time |
|---|---|---|---|---|---|---|---|---|---|---|
| Conversation A | Engagement Agent A | Agent | Agent A | 8:00 | 8:15 | 8:40 | — | 0:05 | 0:15 | 0:10 |



Notes on the data:

- There is no queue engagement as the customer does not wait in any queue.

- The ringing of the phone is represented by Invitation Time and it is part of Engagement Time because the agent is busy when trying to reach the customer.



Turn Data Set

During a phone conversation each turn will represent a continuous talk either by agent or a customer (or mixed channel if the channels are not separated).

| Engagement | Turn | Type | Participant | Turn Time |
|---|---|---|---|---|
| Engagement Agent A | Turn A | Talk | Agent | 8:05 |
| Engagement Agent A | Turn B | Talk | Customer | 8:10 |



Notes on the data:

- Typical call contains much more turns as the conversation can switch between participants quite quickly.

- Turns of the type Talk are available only in if transcripts are available for the call.



### [](#abandoned-inbound-call)Abandoned Inbound Call

Inbound calls that do not reach agents are represented in Salted CX. In some cases abandoned calls can have only a queue engagement. In other cases.

![](https://media.notiondesk.so/upload/689dde5a6beaa821720575.png)

Engagement Data Set

| Conversation | Engagement | Type | Agent | Conversation Start Time | Start Time | End Time | Queue Time | Invitation Time | Engagement Time | Wrap Up Time |
|---|---|---|---|---|---|---|---|---|---|---|
| Conversation A | Engagement Queue A | Queue | — | 8:00 | 8:00 | 8:40 | 0:40 | — | — | — |
| Conversation A | Invitation A | Invitation | Agent A | 8:00 | 8:10 | 8:20 | — | 0:10 | — | — |
| Conversation A | Invitation B | Invitation | Agent B | 8:00 | 8:20 | 8:30 | — | 0:10 | — | — |



Notes on the data:

- Because the agents refused and missed invitations a special type of engagements are created.

- There may be multiple invitations for the same customer waiting in the queue. Every time an agent is invited and agent does not start talking to a customer an invitation engagement is created.

- The queue can span longer than when the last invitation ends if there are for example no agents left to notify.

- Invitations may not be available for all platforms and some platforms might provide only data on the last agent asked to handle the conversation.



No turns are created for this scenario

### [](#inbound-call-with-cold-transfer)Inbound Call with Cold Transfer

Cold transfer is a situation in which the agent moves a customer to another queue served by different agents. Typical use of a warm transfer is when the agent is not the one who can help the customer but depending on the customer request the agent can identify the right destination.

![](https://media.notiondesk.so/upload/689dde5d7cb53254482079.png)

Engagement Data Set

| Conversation | Engagement | Type | Agent | Conversation Start Time | Start Time | End Time | Queue Time | Invitation Time | Engagement Time | Wrap Up Time |
|---|---|---|---|---|---|---|---|---|---|---|
| Conversation A | Engagement Queue A | Queue | — | 8:00 | 8:00 | 8:15 | 0:15 | — | — | — |
| Conversation A | Engagement Agent A | Agent | Agent A | 8:00 | 8:15 | 8:35 | — | 0:05 | 0:10 | 0:10 |
| Conversation A | Engagement Queue B | Queue | — | 8:00 | 8:25 | 8:40 | 0:15 | — | — | — |
| Conversation A | Engagement Agent B | Agent | Agent B | 8:00 | 8:40 | 8:50 | — | 0:05 | 0:10 | — |



Notes on the data:

- Engagement Queue A does not have an agent associated with it because the customer is not a responsibility of the agent.

- No Invitation Engagement is created as these engagements are created only in case an agent is asked to handle the customer but they miss or reject to join the conversation.

- End Time of Engagement Agent A is the end of the wrap up phase as it should indicate the end of any agent work related to the engagement.

- While Engagement Agent A is in wrap up there is parallel Engagement Queue B representing the customer waiting in a queue for the new agent

- In case there is no wrap up the Wrap Up time is empty as shown in the Engagement Agent B



Turn Data Set

During a phone conversation each turn will represent a continuous talk either by agent or a customer (or mixed channel if the channels are not separated).

| Engagement | Turn | Type | Participant | Turn Time |
|---|---|---|---|---|
| Engagement Agent A | Turn A | Talk | Agent | 8:15 |
| Engagement Agent A | Turn B | Talk | Customer | 8:20 |
| Engagement Agent A | Turn C | Talk | Agent | 8:25 |
| Engagement Agent B | Turn D | Talk | Agent | 8:40 |
| Engagement Agent B | Turn E | Talk | Customer | 8:45 |
| Engagement Agent B | Turn F | Talk | Agent | 8:50 |



Notes on the data:

- Typical call contains much more turns as the conversation can switch between participants quite quickly.

- Turns of the type Talk are available only in if transcripts are available for the call.

- Turns are associated with the engagement in which happened.



### [](#inbound-call-with-warm-transfer)Inbound Call with Warm Transfer

Warm transfer is a transfer that involves the transferring agent to connect with the target agent before handling over the customer who is typically put on hold. Typically the transferring agent has to wait in the queue as a regular customer (although transfers can be prioritized to shorten hold times). Once connected the two agents can talk together before unmuting the customer. After unmuting the customer the transferring agent typically gives a short intro to the customer and leaves the conversation.

![](https://media.notiondesk.so/upload/689dde6419364779757299.png)

Engagement Data Set

| Conversation | Engagement | Type | Agent | Conversation Start Time | Start Time | End Time | Queue Time | Invitation Time | Engagement Time | Wrap Up Time |
|---|---|---|---|---|---|---|---|---|---|---|
| Conversation A | Engagement Queue A | Queue | — | 8:00 | 8:00 | 8:15 | 0:15 | — | — | — |
| Conversation A | Engagement Agent A | Agent | Agent A | 8:00 | 8:15 | 8:55 | — | 0:05 | 0:35 | 0:05 |
| Conversation A | Engagement Queue B | Queue | — | 8:00 | 8:25 | 8:40 | 0:15 | — | — | — |
| Conversation A | Engagement Agent B | Agent | Agent B | 8:00 | 8:40 | 9:05 | — | 0:05 | 0:25 | — |



Notes on the data:

- The customer is typically put on hold when warm transfer is initiated, however the Engagement Time A is still counted because the Agent A is still busy with the handling the customer even when it means not talking to the customer

- The person who waits in the Engagement Queue B is the Agent A for a chance to talk to Agent B

- The engagements can overlap — at 8:40 the agents talk to each other and this adds to Engagement Time of the both agents’ engagements.

- Agent A can be in wrap up while the Agent B talks to the customer.



Turn Data Set

During a phone conversation each turn will represent a continuous talk either by agent or a customer (or mixed channel if the channels are not separated).

| Engagement | Turn | Type | Participant | Turn Time |
|---|---|---|---|---|
| Engagement Agent A | Turn A | Talk | Agent | 8:15 |
| Engagement Agent A | Turn B | Talk | Customer | 8:20 |
| Engagement Agent A | Turn C | Talk | Agent | 8:25 |
| Engagement Agent A | Turn D | Talk | Agent | 8:40 |
| Engagement Agent B | Turn E | Talk | Agent | 8:45 |
| Engagement Agent A | Turn F | Talk | Agent | 8:50 |
| Engagement Agent B | Turn G | Talk | Customer | 8:55 |
| Engagement Agent B | Turn H | Talk | Agent | 9:00 |



Notes on the data:

- The assignment of turns when the engagements overlap is determined by who is talking, however this may not be available at all platforms and the turns can be assigned to either engagement



### [](#outbound-call-with-dialer)Outbound Call with Dialer

Dialer calls to customers automatically based on a list of customers to reach to.

## [](#conference-call)Conference Call

Conference call is a call where more agents are brought into the conversation at once collaboratively working on the customer request.

![](https://media.notiondesk.so/upload/689dde68d54de177583379.png)

Engagement Data Set

| Conversation | Engagement | Type | Agent | Conversation Start Time | Start Time | End Time | Queue Time | Invitation Time | Engagement Time | Wrap Up Time |
|---|---|---|---|---|---|---|---|---|---|---|
| Conversation A | Engagement Queue A | Queue | — | 8:00 | 8:00 | 8:15 | 0:15 | — | — | — |
| Conversation A | Engagement Agent A | Agent | Agent A | 8:00 | 8:15 | 8:55 | — | 0:05 | 0:35 | 0:05 |
| Conversation A | Engagement Agent B | Agent | Agent B | 8:00 | 8:25 | 8:40 | 0:15 | — | — | — |
| Conversation A | Engagement Agent C | Agent | Agent C | 8:00 | 8:40 | 9:05 | — | 0:05 | 0:25 | — |
| Conversation A | Invitation D | Invitation | Agent D | 8:00 | 8:25 | 8:30 | — | 0:05 | — | — |
| Conversation A | Invitation E | Invitation | Agent E | 8:00 | 8:25 | 8:35 | — | 0:10 | — | — |



Notes on the data:

- The engagements of individual agents joining the call overlap each other.

- Each agent engagement can have a separate wrap up.

- There is no queue for invites to the other agents because the customer nor Agent A do not really wait.

- If agents miss or reject the invitation to join the conference an invitation engagement is created.



Turn Data Set

During a phone conversation each turn will represent a continuous talk either by agent or a customer (or mixed channel if the channels are not separated).

| Engagement | Turn | Type | Participant | Turn Time |
|---|---|---|---|---|
| Engagement Agent A | Turn A | Talk | Agent | 8:15 |
| Engagement Agent A | Turn B | Talk | Customer | 8:20 |
| Engagement Agent A | Turn C | Talk | Agent | 8:25 |
| Engagement Agent A | Turn D | Talk | Agent | 8:40 |
| Engagement Agent B | Turn E | Talk | Agent | 8:45 |
| Engagement Agent A | Turn F | Talk | Agent | 8:50 |



Notes on the data:

- The assignment of turns when the engagements overlap is determined by who is talking, however this may not be available at all platforms and the turns can be assigned to either engagement



## [](#email)Email

### [](#inbound-email)Inbound Email

Inbound emails typically lead to inviting an agent to respond to the customer message.

![](https://media.notiondesk.so/upload/689dde6db9028535489121.png)

Engagement Data Set

Invitation engagement is not created in case the

| Conversation | Engagement | Type | Conversation Start Time | Start Time | End Time | Queue Time | Invitation Time | Engagement Time | Wrap Up Time |
|---|---|---|---|---|---|---|---|---|---|
| Conversation A | Engagement Queue A | Queue | 8:00 | 8:00 | 8:15 | 0:15 | — | — | — |
| Conversation A | Engagement Agent A | Agent | 8:00 | 8:15 | 8:25 | — | 0:05 | 0:10 | — |
| Conversation A | Engagement Queue B | Queue | 8:00 | 8:35 | 8:50 | 0:15 | — | — | — |
| Conversation A | Engagement Agent B | Agent | 8:00 | 8:50 | 9:00 | — | 0:05 | 9:00 | — |



Notes on the data:

- When handling emails a new queue and agent engagement typically exists for every response and reply. Because there are expected longer response times in most contact centers once the agent sends an email they are immediatelly free to handle another conversation.



Turns Data Set

| Engagement | Turn | Type | Participant | Turn Time |
|---|---|---|---|---|
| Engagement Queue A | Turn A | Message | Customer | 8:00 |
| Engagement Agent A | Turn B | Message | Agent | 8:25 |
| Engagement Queue B | Turn C | Message | Customer | 8:35 |
| Engagement Agent B | Turn D | Message | Agent | 9:00 |



Notes on the data:

- The turns for emails are essentially the same as for chat channels.

*Tags: Logical Model*


---

## Custom Visualizations

Source: https://help.salted.cx/en/articles/visualizations-custom


Visualization is an individual number, table or chart that shows one or more metrics. Optionally you can segment the metrics by one or more attributes. You can also filter the metrics by one or more attributes. You can use multiple visualizations in a dashboard to look on a data from several different perspective at once.

To start building a visualization click the New Visualisation button in left bottom corner. You can build new visualizations with drag and drop without the need to have deep technical skills. You can use many of the metrics and attributes included out of the box or any metrics that you or your colleagues created in your account.

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

Do not be afraid to experiment when building a new visualization. You can easily use redo and undo to go many steps back and forward. You do not lose your work when going in a wrong direction for a while.





![](https://media.notiondesk.so/upload/698b116d2bc7d540789304.png)

## [](#data-items)Data Items

On the right side you have building blocks available for your visualization. You can drag and drop data items from here into

### [](#search)Search

You can use Search data… ![:r1:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/cbece7ea-90d1-42be-b944-7d3a40472c0a/Circle_1.png) field to filter available metrics, facts and attributes. Search matches any word in the metric, fact or attribute title.

### [](#categories)Categories

You can use the button bar with metrics, attributes and facts ![:r2:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/828ec6f6-6da7-41e1-ab7d-81f376318b90/Circle_2.png) to show only them. If you are searching for one of those it helps you to narrow the options.

### [](#data-items-list)Data Items List

Drag and drop items from Data Items list ![:r3:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/6a0e6eb2-4742-4445-80a6-8be77bab104f/Circle_3.png) to the canvas to include them in your visualization. Depending on the Data Item type different areas are highlighted to indicate where you can use the given item.

Hover over any of the data items. Question mark will appear. Hover over the question mark icon to see more details about any data item.

### [](#create-metric)Create metric

Press Create metric button ![:r4:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/49964e58-e0e9-40b5-b973-00c416e5d0bc/Circle_4.png) if there is no metric that provides the values you would like to see in your insight.

## [](#tool-bar)Tool Bar

### [](#insight-name)Insight Name

Click the insight name ![:r5:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/a8d7fc85-01c2-4beb-ae57-18073a27a40e/Circle_5.png) to rename it.

### [](#undo-redo-clear)Undo / Redo / Clear

Undo ![:r6:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/22961b53-f52d-4017-87e3-e0ab43ddd029/Circle_6.png) returns the insight one step back. Click undo when you went into a direction that you wanted. You can undo multiple steps so you do not have to be afraid to experiment and try every avenue when exploring your data.

Redo repeats the step you have previously stepped back by using undo.

Cancel removes all currently added metrics, attributes and filters from the insight. Use it to revert changes you are not satisfied with.

### [](#save)Save

Save button ![:r7:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/9e5e9e5f-9b80-4656-8d16-a78ef863eb57/Circle_7.png)  saves the insight in the current state. If you have edited an existing insight the insight gets updated and the previous version is overwritten. The insight is updated in all dashboards that include it.

### [](#more)More

Use the More button![:r8:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/bd34cd7e-cbac-4650-9d97-2a4412a47520/Circle_8.png) to export the current insight into one of the formats:

- XLXS for working with the file in Excel.

- CVS for machine processing the data.

## [](#insight-options)Insight Options

The pane next to the building blocks contains the definition of you insight.

### [](#insight-visualization)Insight Visualization

![](https://media.notiondesk.so/upload/698b11702642e592978463.png)

You can switch visualization type ![:r8:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/bd34cd7e-cbac-4650-9d97-2a4412a47520/Circle_8.png) while keeping metrics, attributes and filters you have used in a different visualization. So you can experiment which visualization is the best to highlight metrics that are important for you.

- Table. Universal starting point for showing a lot of data segmented by many dimensions. Table can be more difficult for people to find outliers and other items should stand out. Consider using different visualization, sorting the table or using conditional highlighting to make interesting number stand out.

- Column Chart. Good for representing volume (number of engagements) in distinct categories such as date.

- Bar Chart. Great for creating visual leaderboards that highlight differences between volume (number of something) in different categories. You can use top/bottom filters and sort the chart to have a great leaderboard.

- Line Chart. Line chart is great for showing a metric (average times, scores, etc.) how they changed over time.

- Area Chart. Alternative to column chart.

- Combo chart. Enables to combine metrics shown in columns, line and area to easily distinguish them. You can use multiple axis to show metrics that use different units or have order of magnitude different values.

- Headline. Single large number good for communicating the most important metrics on top of a dashboard.

- Scatter Chart. Great for comparing 2 different metrics and understanding relationship (correlation) between them.

- Bubble Chart. Great for comparing 2 different metrics and understanding relationship (correlation) between them. Compared to scatter chart you can also use bubble size to indicate a third metric. The size of the bubble is great to indicate whether the item is wort your attention.

- Pie Chart. Good for communicating a ratio in volume by a different category in a way that is similar to headline and communicates overall performance.

- Donut Chart. Good for communicating a ratio in volume by a different category in a way that is similar to headline and communicates overall performance.

- Bullet Chart. Great for showing the current metrics and comparing them to targets you want to reach.

### [](#visualization-metrics-and-attributes)Visualization Metrics and Attributes

Into metrics and attributes area ![:r9:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/72b59471-92ba-446c-94f7-8d19849cfc6a/Circle_9.png) you can drag and drop data items for the Data Items list ![:r3:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/6a0e6eb2-4742-4445-80a6-8be77bab104f/Circle_3.png) to build your insight. The number of slots and what they represent differs by visualization type ![:r8:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/bd34cd7e-cbac-4650-9d97-2a4412a47520/Circle_8.png).

### [](#visual-configuration)Visual Configuration

Visual options ![:r10:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/39cc41d0-405c-4a91-bb9a-f1c584d8fb1a/Circle_10.png) do not have direct impact what data the visualization shows but enables you to configure how the data are presented including colors, axis and canvas settings. The options differ by visualization type ![:r8:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/bd34cd7e-cbac-4650-9d97-2a4412a47520/Circle_8.png).

### [](#filters-bar)Filters Bar

Into filter bar ![:r11:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/3ee86a8a-caf2-477b-accb-27c2e2a315ea/Circle_11.png) you can drag and drop attributes from the Data Items list ![:r3:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/6a0e6eb2-4742-4445-80a6-8be77bab104f/Circle_3.png) to narrow down the visible data. Note that any filtering criteria added to the filter bar are overridden by dashboard filters. So you can create an unfiltered insight or filter it to same values that is easier to work. Users can then choose different filters in a dashboard that override those in the insight.

### [](#add-filter)Add Filter

Add filter button ![:r12:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/b6a745ee-4a40-42ab-b73a-e66d599f7442/Circle_12.png) enables you to add more complex filtering options. You can filter by metric used in the insight or use top/bottom filtering to show only a few first items that have highest or lowest value.

*Tags: Visualizations*


---

## Data Loads

Source: https://help.salted.cx/en/articles/1755219286-data-loads


Salted CX loads data from multiple data sources, transforms them, and unifies them into the [Logical Model](https://help.salted.cx/en/collections/1755206106-logical-model). Data from all the data sources are visible in one account. Conversations from all the data sources are visible side-by-side. It is still possible to filter.

## [](#regular-data-loads)Regular Data Loads

Salted CX makes its best effort to load data every 15 minutes. The below diagram shows the timeline of the data loads.

![](https://media.notiondesk.so/upload/689de24a7db8e305240364.png)Timeline of data loads

In the example above the data load for the time period 8:00 to 8:15 sometime in the following 15-minute time period between 8:15 to 8:30. Salted CX does not have the exact timeframe for the data load in the load interval. This means that data can be up to 30 minutes old. This happens for engagements that happen around 8:00 when the data load ends at 8:30.

Loading process has the following phases:

- Wait. Salted CX waits between End of Loaded Period and Load Start for several minutes to give the data sources some time to have all the data for the loaded time period available. Data sources may often have delayed data as data export is often a secondary feature. The delay may be different depending on the customer and the data source.

- Extraction. Salted CX extracts data that had any updates in the previous time period and stores them on Salted CX side in their original raw format. The time spent in this phase heavily depends on the data source and the amount of updated data.

- Transformation. Once data are stored in Salted CX in its original form Salted CX transforms them into our unified Logical Model and makes them available for reporting.

### [](#data-sources-with-lower-load-frequency)Data Sources with Lower Load Frequency

Some data sources may not have the data available in 15-minute intervals. In such case Salted CX loads data for those data sources with lower frequency while loading other data sources with 15-minute frequency.

If your account integrates data sources with lower load frequency you may need to pay extra attention when drawing conclusions from the data. Especially when combined with data from data sources loaded in 15-minute intervals.

![](https://media.notiondesk.so/upload/689de24ce31d2852014043.png)Example of a report that combines data from data source with 15-minute and daily loads

In the example above if you have a report where data source are not distinguished (grey chart) you might think at the end of the day Jan 5th that there was a significant drop in your daily traffic. However that is only caused by the fact that the data for Jan 5th was not yet loaded from one of the data sources. The chart that distinguishes the individual data sources (blue and green) highlights this.

## [](#delayed-loads)Delayed Loads

There are several situations in which the data may not be loaded within the regular loads time window.

### [](#data-source-is-not-available-or-degraded)Data Source is Not Available or Degraded

There might be issues with data sources that are outside of Salted CX control. Individual data sources may not be available or they may have degraded performance. Salted CX does not block the entire load if data from some data sources are not yet available. This may influence metrics that are based on data from multiple data sources such as sudden drop in traffic, skewed averages, etc.

### [](#bulk-updates-in-the-data-sources)Bulk Updates in the Data Sources

Bulk updates and deletes in the data sources may lead to delayed loads into Salted CX. Example a bulk update in the data source is for example changing one property of millions of conversations in a few minutes time window.

The typical reasons for delay in :

- Data sources primarily processes the bulk update requests and (often secondary) data export features are not prioritized. Primary features of our data sources is typically facilitate communication between your company and your customers which understandably takes precedence.

- The data extraction can take longer due to limits or fair user policy of the data source. Limits and fair use are typically reasonable for regular loads but may not cover peaks caused by bulk updates.

- The processing of bulk data can take longer on Salted CX side. The exact delay depends on the data source and what data points are affected.

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

Bulk updates are typically driven by our customers when they implement changes in their systems. It is good to coordinate with people using Salted CX that they may be impacted by delayed data load. We recommend to do such updates outside of business hours. The stress on data sources is lower and users may have less need for the latest data.





## [](#initial-data-load)Initial Data Load

When Salted CX is enabled for any data source we load the historical data to give users insight into longer term trends from the beginning. The initial load may take significant time depending on how much into the past Salted CX loads the data, what is the volume of conversations and other data you have produced so far, and depending on the current load of the system. Due to these factors we cannot provide general guidelines on how long the initial data load takes.

Data related to conversations that happened before Salted CX was connected to the data source may be less detailed than the data imported by Salted CX incrementally. See [Historical Changes in Data](https://help.salted.cx/en/articles/1755188319-historical-changes-in-data) for more details.

---

## Forms

Source: https://help.salted.cx/en/articles/forms


Forms are a way of collecting people’s feedback for conversations and their parts. Users can use forms in [customer journey](https://help.salted.cx/en/collections/1755250527-customer-journey) to provide quantitative and qualitative feedback that is easy to report and act on. All feedback collected using forms is stored for reporting as [Reviews](https://help.salted.cx/en/articles/model-review).

![](https://media.notiondesk.so/upload/698d916493f1a072218972.png)

Forms are a list of blocks that enable reviewers to provide feedback for engagements and turns. You can combine any number of blocks. However we recommend to use the forms that are short and targeted to resolving specific use cases.

## [](#enable-use-of-the-form)Enable Use of the Form

You can decide in which context the form will be available:

- Engagement — The form is available for reviews when the engagement is selected.

- Agent Turn — The form is available for reviews when agent turn is selected.

- Customer Turn — The form is available for reviews when customer turn is selected.

- Bot Turn — The form is available for reviews when bot turn is selected.

- Coaching — The form is available to log coaching sessions in agent profile.

## [](#blocks)Blocks

There are multiple types of blocks that you can combine in the form. There are different types of blocks serving different purposes.

![](https://media.notiondesk.so/upload/698d916836caa131256201.png)

To add a block to a form:

- Press the Add New Block button at the bottom of the form

- Choose the type of the block you want to insert

To change order of blocks:

- Press menu ![:r1:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/cbece7ea-90d1-42be-b944-7d3a40472c0a/Circle_1.png) in the top right corner

![](https://media.notiondesk.so/upload/698d916aa18ea896518021.png)

- Press Edit Layout ![:r2:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/828ec6f6-6da7-41e1-ab7d-81f376318b90/Circle_2.png) in the menu

![](https://media.notiondesk.so/upload/698d916d2de67115748977.png)

- Use handles ![:r3:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/6a0e6eb2-4742-4445-80a6-8be77bab104f/Circle_3.png) on the right side of the blocks to change order of blocks

- Press Done Editing ![:r4:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/49964e58-e0e9-40b5-b973-00c416e5d0bc/Circle_4.png) once the order is set

### [](#tag-questions-block)Tag Questions Block

Tag Questions Block contains a set of tags that are related to each other and enable a reviewer to quickly tag enaggements and turns if they have a given behavior.

![](https://media.notiondesk.so/upload/698d916feb520488082871.png)

Add a tag to the block:

- Press Add Tag Question ![:r1:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/cbece7ea-90d1-42be-b944-7d3a40472c0a/Circle_1.png)

- Use search ![:r2:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/828ec6f6-6da7-41e1-ab7d-81f376318b90/Circle_2.png) to find the question

- Salted CX offers you to create a question if the tag you need does not exist

- Press Create New Tag Question ![:r3:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/6a0e6eb2-4742-4445-80a6-8be77bab104f/Circle_3.png) if you want to create a new tag

- Or choose one of the offered questions

### [](#freetext-question-block)Freetext Question Block

Freetext question collects text feedback from a reviewer. Freetext questions are great to collect open-ended qualitative feedback that is not (yet) covered with tags and single choice questions.

![](https://media.notiondesk.so/upload/698d917270a82117463355.png)

### [](#single-choice-question-block)Single Choice Question Block

Single choice block enables reviewers to pick one answer for the question.

![](https://media.notiondesk.so/upload/698d9174cd891503279425.png)

To change the question, description and available answers you have to edit the question directly in questions. Keep in mind that a question can be used in multiple forms and editing the question will influence them as well.

To edit the question:

- Press the menu ![:r1:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/cbece7ea-90d1-42be-b944-7d3a40472c0a/Circle_1.png) in the top right corner of the block

- Press View Question ![:r2:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/828ec6f6-6da7-41e1-ab7d-81f376318b90/Circle_2.png) in the menu

### [](#text-block)Text Block

Text block is plain text that is useful for providing information to a person that does the reivew. You can use it to provide detailed instructions to reviewers.

![](https://media.notiondesk.so/upload/698d917720f55721557301.png)

---

## Freshdesk Integration

Source: https://help.salted.cx/en/articles/integration-freshdesk


![](https://www.notion.so/icons/warning_yellow.svg?mode=light)

This feature is in Preview and its behavior is likely to change based on user feedback. The feature also may have lower availability and have more maintenance windows.









You can connect multiple Freshdesk instances to a single Salted CX account and mix data in Slated CX with other data sources.

## [](#integration-between-freshdesk-and-salted-cx)Integration between Freshdesk and Salted CX

There are only two required items to connect to Salted CX:

1. [Freshdesk API key](https://support.freshdesk.com/support/solutions/articles/215517-how-to-find-your-api-key)

2. Root domain — for example [https://saltedcx.freshdesk.com/](https://saltedcx.freshdesk.com/a/tickets/4)

💡

Salted CX currently supports Freshdesk only. Freshchat and Freshcaller can be created on demand.





## [](#freshdesk-data-in-logical-model)Freshdesk Data in Logical Model

We translate data from all platforms into our unified Logical Model that enables you to report on data from multiple platforms in the same way. We use unified concepts with unified naming and the same meaning in every platform.

As each platform has its own vocabulary and concepts we cannot adopt any single platform vocabulary. Platforms have different names for the same concepts (for example ticket, case, issue, or task for a single customer-related request). Or different platforms use the same name for different concepts (for example “Contact” means a single conversation with a customer in one platform, but it means a customer email/phone in another platform).

This article covers how Freshdesk concepts translate into Salted CX concepts and vocabulary.

💡

To understand Freshdesk data in the Logical Model it is recommended to have a basic understanding of our Customer Journey and Logical Model. You can also check our Glossary to understand the naming and meaning of our concepts.





### [](#customers)Customers

Salted CX creates individual customers that correspond to Freshdesk users. Freshdesk creates users for both agents and the customers calling the company. Every ticket associated with a user representing a customer becomes part of the given customer’s customer journey. So you see all those tickets chronologically one after another in our customer journey.

The ticket requester email becomes contact identifier in Salted CX and the ticket requester name from Freshdesk is stored into the customer name.

### [](#conversations)Conversations

Each Freshdesk ticket translates to one conversation.

### [](#engagements)Engagements

Freshdesk does not have a built-in concept similar to engagements in Salted CX. We define engagement as the participation of a single agent or a service in a conversation with a customer. We use heuristics to extract a similar concept from Freshdesk data.

We create engagements based on actual agent activity on the ticket. An engagement start when an agent responds to a ticket for the first time or when a ticket is reopened. The engagement ends when another agent starts to engage with the customer or the ticket is resolved. The start time of an engagement is when an agent sends their first message. The end time of an engagement is when an agent sends their last message. This heuristic tries to best approximate the engagement time.

For example, if an agent Alice replies to a customer at 8:00 AM with one message, then Alice asks Bob for help with the customer. Bob starts to chat with the customer at 8:15 AM until 8:30 AM. Bob returns the ticket to Alice who chats with the customer from 8:45 AM to 9:00 AM and marks the ticket as resolved. Custom reaches back and Alice chats again with the customer from 10:00 AM to 10:30 AM. We create 4 engagements:

- Engagement with Alice with start time and end time 8:00 AM

- Engagement with Bob with start time 8:15 AM and end time 8:30 AM

- Engagement with Alice with start time 8:45 AM and end time 9:00 AM

- Engagement with Alice with start time 10:00 AM and end time 10:30 AM

💡

Depending on your exact process and setup in Freshdesk our metric Engagement Time and metrics based on it may not be reliable indicator of an agent performance. Unlike many other contact center platforms, Freshdesk does not have a concept of an agent actively working on a ticket by accepting it. This means the agent can spend some time by looking at the ticket before engagement start time starts. You can use metrics such as Engagements per Hour to get glimpse of the agent performance. More engagements per hour typically means agents are faster in handling them.





We map the following attributes from Freshdesk tickets to the Salted CX model:

| Salted CX | Freshdeck Ticket Attribute |
|---|---|
| Case | Ticket number |
| Channel Vendor | “FreshWorks” |
| Conversation | Ticket number |
| Conversation Start Time | Ticket created timestamp |
| Direction | ’Inbound’ |
| Engagement Type | “Agent” |
| Engagement Link | Link to the ticket |
| Engagement Priority | Ticket priority |
| Engagement State | "Completed" if ticket\_status == "4" or ticket\_status == "5" else "In Progress” |
| Start Time | Engagement start time |
| End Time | Engagement end time |



### [](#turns)Turns

Each individual message or email message from an agent or from a customer creates a new message turn associated with an engagement of the currently engaged agent.

## [](#data-not-available-from-freshdesk)Data not Available from Freshdesk

Different customer care platforms provide different granularity of data and have different concepts. These features may prevent us from reporting on certain metrics or impose other restrictions.

This typically prevents use of certain attributes and/or metrics in reporting for the given platform. This section covers the key limitations based on Freshdesk data. Remember that when one metric is affected also metrics based on that one are affected (such as average of the missing metric).

### [](#queue-engagements)Queue Engagements

Freshdesk does not have a concept of queues similar to many other contact center platforms. Thus we do not create any queue engagements that typically represent waiting customers in a specific queue and enable visibility into customer movement between queues.

Affected attributes: Queue

Affected metrics: Wait Time, Queue Engagements

### [](#invitation-engagements)Invitation Engagements

Freshdesk does not have a concept of inviting agents to conversations (showing agents that they can engage with the customer by joining conversation) similar to many other contact center platforms. Thus we do not create any invitation engagements in case the agent misses or rejects the invitation to join conversations.

Affected metrics: Invitation Time, Rejected Invitations, Missed Invitations

### [](#wrap-up-time)Wrap Up Time

Freshdesk does not have a concept of wrap up that agent has to perform after an engagement with a customer. Although agent can perform additional actions in Freshdesk after they resolve the customer ticket this time is not tracked by Freshdesk.

Affected metrics: Wrap Up Time

### [](#agent-status)Agent Status

We do not import agent activity (agent status, AUX code) from Freshdesk. This status codes are typically used for routing decisions and WFM purposes. When using Freshdesk we recommend you have another source for this data such as WFM or a contact center platform that you connect with Salted CX.

Affected metrics: Activity Time, Available Time, Unavailable Time

*Tags: Integration*


---

## Google as Identity Provider

Source: https://help.salted.cx/en/articles/identity-provider-google


To login using your Google credentials you need to do setup in Google Workspace. You need to be admin of Google Workspace to perform this setup. This setup will let Google know it should enable access to Salted CX and will enable you to assign permissions to individual users.

The setup has the following parts:

- [Add Permissions User Attribute](https://help.salted.cx/en/articles/identity-provider-google#99f77aa308aa449f8848e558a95086a0). This is done only once per account and adds an attribute that you can use to store [permissions](https://help.salted.cx/en/articles/permissions) that are passed to Salted CX during sign on.

- [Create SAML Application](https://help.salted.cx/en/articles/identity-provider-google#99f77aa308aa449f8848e558a95086a0). This makes Google Workspace aware your Salted CX account exists and that it should enable sign in to it using Google credentials.

- [Set Permissions per User](https://help.salted.cx/en/articles/identity-provider-google#3590e77aa0434622836ed833c5df4680) — These steps give individual users [permissions](https://help.salted.cx/en/articles/permissions) to access selected Salted CX features and you need to give these permissions to every user who should have access to Salted CX.

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

Until you give individual users permissions they cannot access Salted CX. So you can do all the setup without concern that users would get unexpected access to any features or data.





## [](#add-permissions-attribute)Add Permissions Attribute

You need to add attribute that you can use for storing the permissions the user has within Salted CX. This is done only once per account. You need to to be [super admin](https://support.google.com/a/answer/2405986#super_admin) in your Google organization:

1. [Sign in](https://admin.google.com/) to your [Google Admin console](https://support.google.com/a/answer/182076)

2. Go to Menu, then Directory, then Users![](https://media.notiondesk.so/upload/689de24f0da6e697937858.png)

3. Press More Options

4. Press Manage Custom Attributes

5. Press Add Custom Attribute![](https://media.notiondesk.so/upload/689de25181a76496374049.png)

6. Into Category field fill value Salted CX![](https://media.notiondesk.so/upload/689de253ea059846860139.png)

7. Into Description field fill Permissions in Salted CX, or any other value that describes well for you the use of the attribute

8. Into Name field fill `permissions` value.![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)
    
    The Name is not required to be `permissions` . We use it for simplicity of this tutorial. You can name the attribute any way you want. For example if you have multiple Salted CX accounts you can have multiple different different attributes with different sets of permissions. Then you can use the name to clearly show to what account the permissions apply. You setup later which permissions are used for the which Salted CX account.

9. In Info type leave the option set to Text

10. In Visibility leave the option set to Visible to user and admin

11. In Number of values leave the option set to Single value

12. Click Add

Now you an attribute that can contain user’s permissions for Salted CX. You will need this attribute to add Salted CX as an application to Google Workspace.

[More information on custom attributes in Google](https://support.google.com/a/answer/6208725?hl=en#zippy=%2Cadd-a-new-custom-attribute%2Crequirements-for-custom-attributes-for-the-secure-ldap-service)

## [](#create-a-saml-application)Create a SAML Application

You need to be logged as an admin in Google Workspace:

1. In the left navigation press Apps, then [Web and mobile apps](https://admin.google.com/ac/apps/unified)![](https://media.notiondesk.so/upload/689de256e9532152088460.png)

2. Press Add app

3. Press App custom SAML app

4. Type in App name. You can name the app any way you want, for example Salted CX![](https://media.notiondesk.so/upload/689de259ef539959541075.png)

5. Press Continue

6. Press Download Metadata and store the file at your computer![](https://media.notiondesk.so/upload/689de26341cf4701770960.png)

7. Press Continue

8. Paste SSO URL from Salted CX to ACS URL field (you can find this value in Salted CX Settings → Single Sign On)![](https://media.notiondesk.so/upload/689de2661d634679331914.png)

9. Paste Audience URI to Entity ID field (you can find this value in Salted CX Settings → Single Sign On)

10. Press Continue, leave other options as they are

11. Choose First name in Google Directory attributes and type `given_name` to App attributes![](https://media.notiondesk.so/upload/689de26811c02785453218.png)

12. Choose Last name in Google Directory attributes and type `family_name` to App attributes

13. Choose Primary email in Google Directory attributes and type `email` to App attributes

14. Choose permissions (or other attribute that you have created) in Google Directory attributes and type `cxsaltedpermissions` to App attributes

15. Press Finish

16. Go back to Single Sign On page in Salted CX settings and paste in the Metadata URL

## [](#enable-salted-cx-application-for-all-users)Enable Salted CX Application for All Users

1. Press User access pane in the application![](https://media.notiondesk.so/upload/68a2e3e9850dc490357216.png)

2. Choose ON for everyone![](https://media.notiondesk.so/upload/68a2e3ec014bf144935464.png)

3. Press Save

![](https://www.notion.so/icons/warning_yellow.svg?mode=light)

Currently users cannot open Salted CX from within the Google Workspace app menu. Your users have to go to the Salted CX domain and will be redirected to Google for sign in. This is a current limitation of our single sign on implementation.





## [](#set-permissions-per-user)Set Permissions per User

You need [Update user privilege](https://support.google.com/a/answer/1219251#users&zippy=%2Cusers) in Google to set user permissions. This actions are necessary for every user you want to access Salted CX:

1. [Sign in](https://admin.google.com/) to your [Google Admin console](https://support.google.com/a/answer/182076)

2. Go to Menu, then Directory, then Users

3. Find the user you want to set permissions for

4. Click the user’s name

5. Click User information

6. Click the attribute named `permissions` or [other name you have used during setup](https://help.salted.cx/en/articles/identity-provider-google#1382aedc2f924489acf7f66cabdd089e)

7. Set the value of the attribute to the permissions JSON object

8. Click Save

[More information on setting custom attributes in Google](https://support.google.com/a/answer/6208725?hl=en#zippy=%2Cadd-a-new-custom-attribute%2Crequirements-for-custom-attributes-for-the-secure-ldap-service)

## [](#next-steps)Next Steps

You might consider making the [Setting Permissions per User](https://help.salted.cx/en/articles/identity-provider-google#3590e77aa0434622836ed833c5df4680) part of an on-boarding process for new people in your contact center organization. You can use [Google API to automate the process](https://developers.google.com/admin-sdk/directory/v1/guides/manage-schemas).

*Tags: Users*


---

## Ingest Data Format

Source: https://help.salted.cx/en/articles/1755247563-ingest-data-format


## [](#file-format)File Format

Each batch of files to upload is one ZIP file with multiple [JSON Lines](https://jsonlines.org/) files with file extension `.jsonl` files. The JSON Lines files are named by convention:

- `[data set id].jsonl` for files containing records for a single data set

- `[data set id]_[entity id].jsonl` for files containing names and IDs of individual entities

See [Logical Model](https://help.salted.cx/en/collections/1755206106-logical-model) for details on model structure.

![](https://www.notion.so/icons/warning_yellow.svg?mode=light)

The examples of JSON Lines files in examples in this article are formatted for readability. However, in the actual files required by Salted CX, the new line is the separator between individual records. So when generating the JSON Lines files do not format them and ensure that each single record is on one line and the new line separator is used between records.





## [](#properties)Properties

The JSON Lines files contain the following types of properties:

- Attribute in string format. The string has a maximum length of 100 characters (including spaces and any other characters in between the quotes).

- Text in string format limited to 64K. This type is used rarely. The current usage is the content of the conversations. Text type is not used for metadata.

- Date in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format with second precision. We do not accept more granular date precision.

- External ID is a reference between data sets and entities. External IDs can be also a string with a maximum of 100 characters. These properties can be easily identified as the their names end with `externalId` . We recommend using External IDs to reference entities.

- Source ID is a reference to a source that created the entity. For each entity this is optional. If you do not provide a Source ID then the Source ID of the uploader

- Integer is a 32-bit signed integer number.

- Decimal is a 32-bit signed decimal (floating) number. In the examples each decimal is represented by a decimal number.

Any value can be `null` except External IDs that are primary identifiers of the submitted data sets and entities.

## [](#reserved-values)Reserved Values

These values are reserved:

- `-2,147,483,648` for Integer values

- `00000000-0000-0000-0000-000000000000` for references to entities (for Pid)

- `<empty string>` for enums and attributes

- `0000-01-01T00:00:00Z` for Date dimension

- `4.9E-324` for decimal values

These values are reserved for forced `null` value for the property. When a property in `null` or is missing it is not updated in our [Logical Model](https://help.salted.cx/en/collections/1755206106-logical-model). Using these reserved values forces the values to be `null`.

## [](#agent-agent-jsonl)Agent `agent.jsonl`

Agents data set represents people, bots and other systems that engage in Conversations with customers. Each [Engagement](https://help.salted.cx/en/articles/model-engagement) is attributed to at most one agent.





```json
{
  "externalId": "agent.name@company.com",
  "agentName": "Juan Mann",
  "state": "Active",
  "type": "User",
  "version": "1.27",
  "hourlyCost": 6,
  "engagementCost": 5,
  "agentDepartmentExternalId": null,
  "agentTeamExternalId": null,
  "agentLocationExternalId": null,
  "agentOrganizationExternalId": null
}
```

See [Agent](https://help.salted.cx/en/articles/model-agent) for details of individual properties.

## [](#answer-answer-jsonl)Answer `answer.jsonl`

```json
{
	"externalId": "any-string-identifying-this-answer",
	"name": "Answer Display Name",
	"souceType": "INTENT TYPE"
}
```

## [](#customer-customer-jsonl)Customer `customer.jsonl`

The file `customer.jsonl` contains individual contacts and the relations between multiple contacts. You can use this file to link multiple known individual (such as phone, email) contact information together to build the customer profile.

The following table describes fields that are not present in the Logical Model but they are used to create links between individual contacts to build a customer profile.

| Property | Type | Description |
|---|---|---|
| `externalId` | String | Customer ID (can be email, phone, username, etc.). |
| `customerRelatedCustomerContacts` | Array | List of other contacts that enables to build identity graph in the customer profile. |
| `customerName` | String | Name of the customer that does not expose personal information. We recommend using the customer first name. |
| `contactType` | String | Type of the contact. Email — email address Phone — international phone number [E.164](https://en.wikipedia.org/wiki/E.164) format Customer ID — internal customer identifier (for example from the CRM) |



```json
{
  "externalId": "this-is-id-of-the-customer-in-your-system",
  "customerRelatedCustomerContacts": [
    {
      "externalId": "alex@company.com",
      "type": "Email"
    },
    {
      "externalId": "+15551234567",
      "type": "Phone"
    }
  ],
  "customerName": "Alex",
  "type": "Customer",
  "contactType": "Customer ID",
  "customerSegmentExternalId": "VIP"
}
```

See [Customer](https://help.salted.cx/en/articles/model-customer) for details of individual properties.

## [](#engagement-engagement-jsonl)Engagement `engagement.jsonl`

Engagement data is a core data set containing all customer engagements organized into conversations and linked to important attributes that enable to filter and segment them.





```json
{
  "externalId": "platform-id-of-the-engagement",
  "engagementName": "User friendly name of the engagement",
  "engagementLink": "https://company.com/engagement/platform-id-of-the-engagement",
  "conversationStartTime": "2023-10-12T08:02:07Z",
  "startTime": "2023-10-12T08:02:07Z",
  "endTime": "2023-10-12T08:02:07Z",
  "conversation": "my-conversation-id",
  "case": "my-case-id",
  "channelType": "Voice",
  "channelVendor": "Genesys",
  "direction": "Inbound",
  "language": "English",
  "location": "United States",
  "platform": "Genesys",
  "serviceLevel": "Within SLA",
  "state": "Completed",
  "source": "genesys-instance-id",
  "type": "Agent",
  "cost": 408.0,
  "engagementTime": 3,
  "focusTime": 2,
  "holdTime": 4,
  "invitationTime": 5,
  "menuTime": 3,
  "preparationTime": 1,
  "waitTime": 9,
  "wrapUpTime": 0,
  "terminatedBy": "Customer",
  "agentExternalId": "agent-id-in-source-platform",
  "contactExternalId": "agent-id-in-source-platform",
  "campaignExternalId": "campaign-id-in-source-platform",
  "channelExternalId": "channel-id-in-source-platform",
  "companyContactExternalId": "company-id-in-source-platform",
  "engagedDepartmentExternalId": "department-id-in-source-platform",
  "engagedTeamExternalId": "team-id-in-source-platform",
  "menuPathExternalId": "menuPath-id-in-source-platform",
  "outcomeCategoryExternalId": "outcomeCategory-id-in-source-platform",
  "outcomeExternalId": "outcome-id-in-source-platform",
  "queueExternalId": "queue-id-in-source-platform",
  "reasonExternalId": "reason-id-in-source-platform"
}
```

See [Engagement](https://help.salted.cx/en/articles/model-engagement) for details of individual properties.

## [](#question-question-jsonl)Question `question.jsonl`

```json
{
	"externalId": "any-string-that-uniquely-identifies-the-question",
	"name": "Question Display Name",
	"type": "singleChoice",
	"sourceType": "Salted Intent Detector"
}
```

## [](#recording-recording-jsonl)Recording `recording.jsonl`

This data set enables to attach recordings to engagements. Recordings are not present in [Logical Model](https://help.salted.cx/en/collections/1755206106-logical-model) but they are important when you open the [Customer Journey](https://help.salted.cx/en/collections/1755250527-customer-journey) so you can listen to what exactly happened in the conversations.

Each line on this file represents link between a single participant (or mixed if the source platform does not separate speakers) audio track in a recording with an engagement.

| Property | Type | Description |
|---|---|---|
| engagementExternalId | String | Identifier of the engagement this recording is associated with this recording. |
| startTime | Time | Start time of the recording. This enables to align the time of transcripts with the actual recording. |
| channel | Integer | Index number of the channel in which the participant is speaking. |
| participantType | String | Agent — an agent speaking Customer — a customer is speaking Mixed — multiple speakers are speaking Unknown — it is not possible to identify the speaker in the source platform |
| location | String | Absolute path to the recording. |



```json
{
	"externalId": "unique-id-of-the-recording",
	"sourceId": "source-id-of-the-recording-associated-with-"
	"engagementExternalId": "id-of-the-engagement-this-recording-is-realted-to",
	"startTime": "2024-05-01T10:06:35.600Z",
	"channel": 0,
	"participantType" : "Agent",
	"location": "s3://mydomain.com/recordings/2024/05/01/recording-id.mp3"
}
```

## [](#review-review-jsonl)Review `review.jsonl`

Reviews contain individual feedback related to engagements or turns. Reviews have large scale use in Salted CX. Reviews are created among others in the following cases:

- During [manual quality assurance](https://help.salted.cx/en/collections/1755201479-quality-assurance).

- Salted CX auto reviewers that review 100% of conversations.

- Customer satisfaction surveys.

Each individual item in Review data set contains an answer to a single question. So if you review an engagement with a form and you reply to multiple questions within that form, you will have multiple review items related to the same engagement.





```json
{
	"externalId": "unique-string-identifying-this-review",
	"turnExternalId": "optional-external-id-of-the-turn-if-the-review-is-specific-for-a-turn",
	"engagementExternalId": "unique-string-identifying-the-engagement",
	"reviewerExternalId": "external id of the reviewer",
	"questionExternalId": "external id of the qeustion",
	"answerExternalId": "external id of the answer",
	"reviewTime": "2024-05-01T10:06:35.600Z",
	"status": "Completed",
	"type": "Intent",
	"confidence":98.0
}
```

Check [Review](https://help.salted.cx/en/articles/model-review) for details of individual properties.

## [](#reviewer-reviewer-jsonl)Reviewer `reviewer.jsonl`

Reviewer data set contains people and services that provided the feedback related to conversations, engagements or even individual turns.





```json
{
	"externalId": "<unique string identifying the reviewer>",
	"name": "Salted Intent Detector",
	"type": "Auto"
}
```

Check [Reviewer](https://help.salted.cx/en/articles/model-reviewer) for details of individual properties.

## [](#service-service-jsonl)Service `service.jsonl`



```json
{
  "externalId": "the-service-or-product-internal-name",
  "name": "Great Service we sell on behalf of the Partner",
  "status": "Active",
  "servicePartnerExternalId": "service-partner-external-id",
  "servicePartnerManagerExternalId": "themanager@ourcompany.com",
  "attribute01ExternalId": "custom-attribute-of the service",
  "attribute02ExternalId": "custom-attribute-of the service",
  "attribute03ExternalId": "custom-attribute-of the service",
  "serviceVerticalExternalId": "id-of-the-vertical-on-the-market",
  "serviceRegionExternalId": "Europe",
  "serviceCountryExternalId": "Czech Republic",
  "serviceCategoryExternalId": "retail",
  "serviceTierExternalId": "vip",
  "servicePartnerSizeExternalId": "enterprise",
  "servicePartnerTierExternalId": "aaa"
}
```

Check [Service](https://help.salted.cx/en/articles/model-service) for details of individual properties.

## [](#turn-turn-jsonl)Turn `turn.jsonl`

Turns are the most granular units of the customer journey. They represent individual messages, continuous talk, menu steps, actions, and transactions individual participants do during the engagement. There are different types of turns representing different activities.





```json
{
  "externalId": "platform-id-of-the-turn",
  "turnTime": "2023-10-12T08:02:07Z",
  "participant": "Agent",
  "type": "Message Sent",
  "origin": "Carlo Bartell",
  "duration": 7,
  "length": 5,
  "sentiment": 99.91,
  "confidence": 15.29,
  "quality": 80.54,
  
  "engagementExternalId": "platform-id-of-the-engagement",
  "categoryExternalId": "category-id-in-source-platform",

  "content": "Content in the language of the contact center.",
  "languageContent": "en",
  "contentAgent": "Contenido en el idioma dicho por el agente.",
  "languageAgent": "es",
  "contentCustomer": "Obsah v jazyce zákazníka.",
  "languageCustomer": "cs",
  
  "mediaName": "Name of the media if this turn represents a file, image, etc.",
  "mediaPath": "https://full-path.to/the-media-shown-in-this-turn",

  "attachments": [
    {
      "pid": "2e021b2e-c98d-4152-8a6c-34fe39dbcc2c",
      "name": "invoice.pdf",
      "path": "year=2026/month=03/day=12/2e021b2e-c98d-4152-8a6c-34fe39dbcc2c.pdf",
      "mimeType": "application/pdf"
    },
    {
      "name": "screenshot.png",
      "s3Path": "s3://mydomain.com/media/2026/03/12/screenshot.png",
      "mimeType": "image/png",
      "imageWidth": 1280,
      "imageHeight": 720
    }
  ]
}
```

See [Turn](https://help.salted.cx/en/articles/model-turn) for details of individual properties.

### [](#turn-attachments)Turn Attachments

A turn can carry one or more attachments — files associated with the turn such as images or documents (for example files attached to an email). Attachments are provided as an array in the `attachments` property of a turn record. Each attachment supports the following properties:

| Property | Type | Description |
|---|---|---|
| `pid` | UUID | Unique identifier of the attachment within Salted CX. Optional — generated from `externalId` if not provided. When the file was uploaded via the media upload endpoint, use the `mediaPid` returned by that endpoint. |
| `externalId` | String | Stable identifier of the attachment in the source system. Optional. |
| `name` | String | File name of the attachment shown to users (for example `invoice.pdf`). |
| `path` | String | Relative path of a file uploaded to Salted CX via the media upload endpoint. Use the `path` value returned by that endpoint. Resolved within your account storage. Use either `path` or `s3Path`. |
| `s3Path` | String | Absolute S3 path to a file already stored in a bucket that Salted CX can read (same mechanism as recordings). Use either `path` or `s3Path`. |
| `mimeType` | String | MIME type of the file, for example `image/png` or `application/pdf`. |
| `imageWidth` | Integer | Width of the image in pixels. Optional, applies to images. |
| `imageHeight` | Integer | Height of the image in pixels. Optional, applies to images. |
| `body` | Text | Inline text content of the attachment. Optional. |



ℹ️

Provide exactly one of `path` or `s3Path` to point to the file. Use `path` for files uploaded through the media upload endpoint (see [Ingest API](https://help.salted.cx/en/collections/1755273563-ingest-api)); use `s3Path` for files that already live in an S3 bucket Salted CX can read.





## [](#entity-json-lines-files)Entity JSON Lines Files

Entities represent attributes in analytics that have structure to enable combination of primary stable identifiers and human readable names.

The table below lists all properties of an each entity. All properties are optional. Typically you will use `externalId` and `name` properties for creating and updating entities.

| Property | Type | Description |
|---|---|---|
| pid | UUID | Unique identifier within Salted CX. This is generated from the `externalId` if not provided. You typically do not need to provide this property. Referencing an entity by `externalId` works for the most use cases. |
| externalId | String | Unique and stable identifier of the entity in the original system. This can be a primary key of the entity in the database, Salesforce ID, Ticket ID, etc. In case the entity does not have a stable identifier in the source system you can make `externalId` equal to a `name`. However |
| sourceId | String | Identifier of the data source. You do not need to use this property unless you need to combine data from multiple sources. If you do not provide this property Salted CX considers your loader to be the source. Sources enable Salted CX to create separate entities from two systems even when they have the same `externalId` within that system but are logically two separate entities. You can use `sourceId` to reference entities from a different source. For example you load data about your employees from EMS and then want them to reference from a contact center platform. |
| name | String | Human readable name of the entity. This does not need to be unique as externalId or pid are used as an identifier. However for users it is best that this value is also unique and recognizable from the others. You can change a name of an existing entity (for example if renamed in the original system) by providing an existing (original) `externalId` and a new `name`. |
| link | String | Hyperlink including a protocol that leads to the entity in the external system. You can use this to give users an option to click the entity in Salted CX analytics and open them in the browser. For example `https://company.com/team/12345`. |



The below example shows a simple JSON that you will typically use to create or update a leaf entity.

```json
{
  "externalId": "customer-category-VIP",
  "name": "VIP"
}
```

The following table lists all entity files that are supported. They use the convention `[data set id]_[entity id].jsonl` . You can check documentation for individual data sets and their attributes in article focused on [Logical Model](https://help.salted.cx/en/collections/1755206106-logical-model).

| File Name |
|---|
| activity\_agent\_status.jsonl |
| agent\_department.jsonl |
| agent\_location.jsonl |
| agent\_manager.jsonl |
| agent\_organization.jsonl |
| agent\_role.jsonl |
| agent\_team.jsonl |
| customer\_category.jsonl |
| customer\_country.jsonl |
| customer\_organization.jsonl |
| customer\_region.jsonl |
| customer\_segment.jsonl |
| customer\_state.jsonl |
| engagement\_attribute\_01.jsonl |
| engagement\_attribute\_02.jsonl |
| engagement\_attribute\_03.jsonl |
| engagement\_attribute\_04.jsonl |
| engagement\_campaign.jsonl |
| engagement\_case.jsonl |
| engagement\_category.jsonl |
| engagement\_channel\_vendor.jsonl |
| engagement\_channel.jsonl |
| engagement\_company\_contact.jsonl |
| engagement\_flow.jsonl |
| engagement\_language.jsonl |
| engagement\_menu\_path.jsonl |
| engagement\_outcome\_category.jsonl |
| engagement\_outcome.jsonl |
| engagement\_platform.jsonl |
| engagement\_priority.jsonl |
| engagement\_queue.jsonl |
| engagement\_reason.jsonl |
| engagement\_source.jsonl |
| question\_category.jsonl |
| review\_review\_session.jsonl |
| service\_attribute\_01.jsonl |
| service\_attribute\_02.jsonl |
| service\_attribute\_03.jsonl |
| service\_category.jsonl |
| service\_country.jsonl |
| service\_partner\_manager.jsonl |
| service\_partner\_size.jsonl |
| service\_partner\_tier.jsonl |
| service\_partner.jsonl |
| service\_region.jsonl |
| service\_tier.jsonl |
| service\_vertical.jsonl |
| transaction\_attribute\_01.jsonl |
| transaction\_attribute\_02.jsonl |
| transaction\_attribute\_03.jsonl |
| transaction\_original\_state.jsonl |
| transaction\_process.jsonl |
| transaction\_product.jsonl |
| transaction\_target\_state.jsonl |
| transaction\_vendor.jsonl |
| turn\_category.jsonl |

*Tags: Integration*


---

## Similar Turns

Source: https://help.salted.cx/en/articles/customer-journey-similar-turns


Similar turns help you to discover turns with similar meaning as the currently selected turn in other customer journeys. You can use it to check if a given message appears more often in conversations and thus whether it requires attention. You can use similar turns to quickly understand whether a a behavior pattern is more common.

When you select a turn the right pane shows you similar turns in other engagements in the last 7 days. Similar turns use AI to find turns where the person expresses similar things in different ways. Unlike traditional search the words you search for do not have to be contained in the turn as long as it has similar meaning.

When you select a customer turn only customer turns are listed in the Similar Turns panel. When you select an agent turn only agent turns are listed in Similar Turns — both human agents and bots. The part of the turns that is the most related to the currently selected turn is highlighted.

![](https://media.notiondesk.so/upload/698d90a27203a212948164.png)

Click individual turns in Similar Turns pane to jump to that turn in its customer journey. You will get to that turn and it will be selected.

*Tags: Customer Journey, Semantic Search*


---

## Your Logic Actions

Source: https://help.salted.cx/en/articles/your-logic-actions


Your Logic decides what actions Salted CX should take and sends these updates to Your Logic. This can be as a response to a [Your Logic event](https://help.salted.cx/en/articles/your-logic-requests), or it can be sent without any prior event, just as an update of the conversation.

## [](#your-logic-actions-endpoint)Your Logic Actions Endpoint

Your Logic implementation sends the request to `https://api.eu.salted.cx/api/v1/live/your-logic` endpoint that contains account ID and conversation PID.

```plain
https://api.eu.salted.cx/api/v1/live/your-logic/accounts/{accountId}/conversations/{conversationPid}
```

Each call to this endpoint MUST contain shared secret in the `Authorization` header. Each response that does not contain the header or contains unexpected value is ignored and no action is taken.

```plain
Authorization: Bearer <shared secret>
```

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

Reach to Salted CX to retrieve the token for your account.









## [](#common-properties)Common Properties

| Property | Type | Description |
|---|---|---|
| requestId | UUID (Optional) | Unique identifier of the request. Use it to tell Salted CX that it can consider the request to be resolved and move forward. |
| conversation | UUID (Path parameter) | Identifier of the conversation this request is related to. This property cannot be present together with the request property. |
| [control](https://help.salted.cx/en/articles/your-logic-actions#1d65d3a2a8dc803692acecea05a9fb88) | Object | Gives Salted CX information about how to process the response and what actions to take. |
| customer (Upcoming) | Object | Object with customer attributes to be updated. You can use this to provide information about the customer that will appear in analytics when you use one of the supported attributes. You can also use custom object in the customer object to provide additional details that you will receive with the next request. |
| actions | Array | List of actions that are executed by Salted CX after receiving this response. There are many different actions such as sending a message, saving a note for agents, inviting people to the conversation. If Salted CX fails to execute an action the rest of the actions are ignored. |



```json
{
	"requestId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
	"actions": [
		{
			"type": "MESSAGE",
			"content": "Thanks! Let me check that for you."
		}
	]
}
```

Example response object### [](#conversation-object-upcoming)Conversation Object (Upcoming)

The top-level conversation object is not supported yet — update conversation properties with the CONVERSATION\_UPDATE action instead.

| Property | Type | Description |
|---|---|---|
| `conversationId` | UUID | The unique ID of the conversation. |
| `info` | String | Structured object that contains information visible in the agent side bar. |
| `urgency` | Integer | How the item should be sorted in needs help section for the agents. |



## [](#control-upcoming)Control (Upcoming)

Control enables you to modify the default Salted CX behavior for processing the participant actions. Control enables Your Logic to deal with asynchronous communication, provide faster responses to customers and optimize costs by processing less incremental requests.

| Property | Type | Description |
|---|---|---|
| `skipToTime` | Time | Ignore all events up to this time. Request will be sent only for events that happened after this time. |
| `skipToLatest` | Boolean | This will skip to the latest event. In case this property is set to true the `skipToTime` is ignored. |
| `ignoreOnCustomerAction` | Boolean | Actions returned by this response are ignored if there are any updates from the customer side. |
| `ignoreOnAgentAction` | Boolean | Actions returned by this response are ignored if there are any updates from the agent side. |



```javascript
{
	"requestId": "a9c9f343-8a80-43f5-a6b2-d61cc06d4d1d",
	
	"control": {
		"skipToTime": "2025-04-15T18:15:51Z",
		"skipToLatest": true,
		"ignoreOnCustomerAction": true,
		"ignoreOnAgentAction": true
	}
}
```





## [](#response-without-request)Response without Request

You can also send responses unrelated to any specific requests. In this case you have to reference a conversation. A good example would be a very long running background task that needs to be completed or some action you perform after an timeout unless it is canceled during the conversation.

![](https://media.notiondesk.so/upload/6a9e6441d1e2a112595894.png)

Responses without requests can contain exactly the same actions as the responses related to a request. The conversation is identified by the Conversation PID in the endpoint URL path; simply omit the `requestId` from the body.

```json
{
	"actions": [
		{
			"type": "MESSAGE",
			"content": "Your travel plans have been confirmed with all the travel agencies. Here is your itenerary https://demoadventures.com/trips/1679287. Have a nice trip!"
		}
	]
}
```





## [](#response-with-multiple-actions)Response with Multiple Actions

Your Logic can send response with multiple actions. Salted CX executes those actions sequentially. If one action fails the rest of the actions are not executed. In the example below Your Logic lets customer know that it may take a while to involve a human agent and thens write a short summary of the previous conversation as a note.

```json
{
	"requestId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
	
	"actions": [
		{
			"type": "MESSAGE",
			"content": "Sorry, I do not know about that. Give me a moment to connect you with a human colleague."
		},
		{
			"type": "NOTE",
			"content": "The customer is asking about a product not mentioned in our knowledge base - Star Plan."
		},
		{
			"type": "NEEDS_HELP",
			"needsHelp": true
		}
	]
}
```

You can check for examples of responses with multiple actions in [Your Logic Response Examples](https://help.salted.cx/en/articles/your-logic-response-examples).

## [](#available-actions)Available Actions

There are these actions currently available in Your Logic.

Some actions are restricted by the conversation's default channel. On EMAIL conversations only EMAIL, MESSAGE, QUESTION, and QUESTION\_DYNAMIC can produce a customer-visible turn; on SMS conversations only MESSAGE, QUESTION, and QUESTION\_DYNAMIC. A request containing a customer-visible action that is not compatible with the channel (for example SEND\_FILE or WHATSAPP\_TEMPLATE on an EMAIL conversation) is rejected as a whole. Actions that do not produce customer-visible turns (NOTE, NEEDS\_HELP, CONVERSATION\_UPDATE, and others) are available on every channel.

| Action | Description |
|---|---|
| MESSAGE | Sends a message visible to the customer as a bot. |
| NEEDS\_HELP | Asks any agent for help. |
| NOTE | Saves a note invisible to the customer. |
| QUESTION | Asks a question defined in Salted CX to a customer. |
| QUESTION\_DYNAMIC | Sends a dynamically built question. Your Logic can customize the question and the answers. |
| CONVERSATION\_UPDATE | Update custom properties of a conversation. |
| INVITE\_EXTERNAL\_AGENT | Invites an external to the conversation by sending an email to them. |
| ENGAGEMENT\_COMPLETE | Completes the engagement. You can use this to kick the agents out of the conversation. |
| CONVERSATION\_COMPLETE | Completes the conversation and all engagements in that conversation. Customers can still write back and reopen the conversation. |
| CREATE\_CONVERSATION | Creates an empty conversation. |
| SEND\_FILE | Sends a file to a user. |
| WHATSAPP\_TEMPLATE | Sends approved WhatsApp template to the customer. |
| EMAIL | Sends an email to the customer, with optional attachments. |
| CUSTOMER\_UPDATE | Updates customer attributes. |
| ENGAGE\_YOUR\_LOGIC | Engages or disengages Your Logic in the conversation. |
| CALL\_START | Starts an outbound voice call (to a voice bot or an agent). |



![](https://www.notion.so/icons/warning_yellow.svg?mode=light)

Sending an action type that is not in this list (including ones marked Upcoming or Idea) fails parsing of the whole response — none of the actions in that payload are executed.





## [](#no-actions)No Actions

Empty list of actions means that Salted CX will do nothing as the response. You SHOULD send empty responses to tell Salted CX that it can move forward with the conversation and send the next event into Your Logic if there is any. Sending this event as soon as possible is important for reducing latency.

```json
{
	"actions": [
	]
}
```

Empty response is an empty JSON object



## [](#send-message)Send Message

This response sends a message that is visible to a customer.

| Property | Type | Description |
|---|---|---|
| `content` | String | The content of the message to send to the customer. |
| `language` (Upcoming) | String (Optional) | Two-letter [ISO-639 alpha-2](https://en.wikipedia.org/wiki/List_of_ISO_639_language_codes) language code. Not supported yet — currently ignored. |
| `link` (Upcoming) | String (Optional) | Link that opens if the customer clicks the turn in Universal Chat. Not supported yet — currently ignored. |
| `openLinkIn` (Upcoming) | Enum (Optional) | `Chat` (default) — Opens the link directly in the chat. `Current Page` — Opens the link in the current page (on the background page in which the chat is embed into).`New Window` |
| `attachments` | Array (Optional) | Attachments to send with the message; each item has `name`, `path` (from the media upload-url endpoint), and `mimeType`. |
| `channel` | Enum (Optional) | Channel to send the message on; defaults to the conversation's default channel. |
| `contactPid` | UUID (Optional) | Contact to send the message to; must be one of the customer's contacts. Defaults to the conversation's primary contact. |



### [](#basic-text-message)Basic Text Message

```json
{
	"actions": [
		{
			"type": "MESSAGE",
			"content": "Would moving the booking to this Friday at 17:00 work for you?"
		}
	]
}
```

### [](#text-message-opening-a-knowledge-article-upcoming)Text Message Opening a Knowledge Article (Upcoming)

This action creates a new message that opens a knowledge base article in the chat window directly. The `link` and `openLinkIn` properties are not supported yet.

```json
{
	"actions": [
		{
			"type": "MESSAGE",
			"content": "Learn about Live Conversations",
			"link": "https://help.salted.cx/en/collections/1755577083-live-conversations",
			"openLinkIn": "Chat"
		}
	]
}
```





## [](#send-email-message)Send Email Message

Email has a dedicated action with email specific properties:

| Property | Type | Description |
|---|---|---|
| `subject` | String | The subject of the email. |
| `body` | String | The body of the email to send to the customer. |
| `contactPid` | UUID | Identifier of the email contact to send the email to. Use objects in `customer` ⏵ `contacts` to find contactPid for the email address you want to use for the recipient. |
| `attachments` | Array of Attachments | The array of attachments. Each attachment requires `path`, `name`, and `mimeType`. |
| `cc` | Array of Strings (optional) | Recipients in copy. |
| `bcc` | Array of Strings (optional) | Recipients in blind copy. |



```json
{
  "requestId": "550e8400-e29b-41d4-a716-446655440000",
  "actions": [
    {
      "type": "EMAIL",
      "contactPid": "550e8400-e29b-41d4-a716-446655440001",
      "subject": "Your requested document",
      "body": "Please find the requested document attached.",
      "attachments": [
        {
          "path": "<path to media uploaded to previously>",
          "name": "document.pdf",
          "mimeType": "application/pdf"
        }
      ]
    }
  ]
}
```

### [](#attachments)Attachments

To send an attachment, first upload a file to Salted CX and then reference it in the EMAIL action. You can include multiple attachments in a single email. You have to first upload them all. You upload the file in two steps:

Obtain Upload Link

Send a `POST` request with an empty body to the `/api/v1/live/media/accounts/{accountId}/upload-url` endpoint. You will retrieve two properties:

`s3PresignedUrl` — The URL to which you perform the upload.

`path` — The path to use in the EMAIL action to attach the dashboard.

Upload the file

Send a `PUT` request to the `s3PresignedUrl` URL with the body containing the attachment data and the `Content-Type` header set to the attachment's mime type.





## [](#send-whatsapp-template-message)Send WhatsApp Template Message

![](https://www.notion.so/icons/warning_yellow.svg?mode=light)

Prepared reply is currently specific for WhatsApp. This will change in the future to make it channel independent. Currently you must have a template in WhatsApp that is approved for outbound.





![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

When updating templates in Meta we strongly encourage to create a new template and then switch Your Logic to use the new template.





Sends an approved WhatsApp template to the customer. This enables to start outbound conversations from Your Logic. Prepared messages are picked from the existing approved templates and can be customized using variables.

| Property | Type | Description |
|---|---|---|
| `templateName` | String | Name of the approved template in WhatsApp. |
| `language` | Object |  |
| `parameters` | Object | Key-value pairs of variables to fill into placeholders in the template. These variables enable to customize the message for the specific customer. |



```json
{
  "actions": [
    {
      "type": "WHATSAPP_TEMPLATE",
      "templateName": "offer_help_named_params",
      "language":{"code": "en"},
      "parameters": {
        "customer_name": "Adam",
        "discount_value": "6",
        "questions_reference" : "serving lunch"
      }
    }
  ]
}
```





## [](#needs-help)Needs Help

Ask for help makes the conversation appear in inbox for the agents. Your Logic still receives all the requests during the communication. However agents can join the conversation and help with its resolution.

| Property | Type | Description |
|---|---|---|
| `needsHelp` | Boolean | `true` if the conversation should be flagged with Needs Help, conversations with Needs Help appear in Live Conversations so agents can join the conversations, this flag can be raised even when an agent is currently engaged, which enables another agent to join `false` if the conversation no longer needs help of an agent |
| `targetAgentPid` | UUID (optional) | Invite this specific agent. |
| `agentSelectionStrategy` | String (optional) | `Best Available` — invite the least busy available agent. |
| `timeout` | Integer (optional) | Seconds the invited agent has to accept. |
| `onTimeout` | String (optional) | `All` (default) — after the timeout the conversation goes to the shared Needs Help queue. `Next Agent` — the strategy picks another agent. |
| `scheduleAt` | Time (optional) | Schedule the needs-help escalation for a future time instead of raising it immediately. |
| `cancelOnNeedsHelp` | Boolean (optional) | `true` (default) — a scheduled escalation is canceled if the conversation raises needs help before the scheduled time. |



```json
{
	"actions": [ 
		{
			"type": "NEEDS_HELP",
			"needsHelp": true
		}
	] 
}
```





## [](#save-note)Save Note

This response saves a note that is only visible to agents, external agents but invisible to customers.

| Property | Type | Description |
|---|---|---|
| `content` | String | The content of the note. |
| `responseTo` | UUID (Optional) | The UUID of the turn that the note is attached to. |
| `attachments` | Array (Optional) | Attachments for the note; each item has `name`, `path` (from the media upload-url endpoint), and `mimeType`. |



```json
{
	"actions": [
		{
			"type": "NOTE",
			"content": "It is unlear what it our policy for Switzerland.",
			"responseTo": "<uuid>"
		}
	]
}
```





## [](#send-file)Send File 

This action sends a file to a user. Before triggering the action, you must first call the API, which returns an upload URL and file path. After uploading your file to the provided URL, you can then trigger the action using the file path from the API response.

```javascript
https://api.eu.salted.cx/api/v1/live/media/accounts/[ACCOUNT]/upload-url
```

Each call to this endpoint MUST contain shared secret in the `Authorization` header.

```javascript
Authorization: Bearer <shared secret>
```

| Property | Type | Description |
|---|---|---|
| `path` | String | URL pointing to the storage location of the uploaded media file. |
| `name` | String | Name of the uploaded file (required). |
| `content` | String | Optional content or description associated with the file. |
| `mimeType` | String | MIME type indicating the file format (e.g., `image/png`, `application/pdf`). |
| `channel` | Enum (Optional) | Channel to send the file on; defaults to the conversation's default channel. |



```json
{
	"requestId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
	"actions": [
		{
			"type": "SEND_FILE",
			"path": "/path/that/you/retrieved/from/our/file/service.extension",
			"name": "invoice.pdf",
			"content": "Invoice for Order #739281",
			"mimeType": "application/pdf"
		}
	]
}
```





## [](#ask-question)Ask Question

This action sends a question to the target participant. You can use any Question PID in Salted CX. To find out what is the question PID for a given question open the [question](https://help.salted.cx/en/articles/questions) in Salted CX and copy its PID from the browser address bar.

Salted CX translates the question to visualization of the target platform. In Universal Chat it shows a list of buttons to choose from. On WhatsApp it creates either a list of buttons or a list depending on the number of possible answers.

| Property | Type | Description |
|---|---|---|
| `allowedToRespond` | Array of Enums | Who can respond to the question. Default `["CUSTOMER"]` |
| `allowedToView` | Array of Enums | Who can see the turn with the question and the related answer. Default `["CUSTOMER", "AGENT", "EXTERNAL_AGENT"]` |
| `allowCustomReply` | Boolean | Hint for the front end whether to enable the agent to show write back a custom text. `true` (default) — Enables the participant to reply using a custom text and thus ignoring the question. `false` — The participant cannot reply to the using custom text reaply. |
| `questionPid` | UUID | The PID of question in Salted CX to send to the participant to answer. |
| `note` | String, nullable | Enables to provide addtiional exlanation to the question that is asked from the agents without altering the question itself. |
| `reviewEngagementPid` | UUID, nullable | The PID of an engagement that the review will be associated with. |
| `channel` | Enum (Optional) | Channel to send the question on; defaults to the conversation's default channel. |
| `contactPid` | UUID (Optional) | Contact to send the question to; must be one of the customer's contacts. |
| `content` | String (Optional) | Optional text sent with the question. |
| `emailSubject` | String (Optional) | Subject to use when the question is delivered over email. |



```json
{
	"requestId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
	"actions": [
		{
			"type": "QUESTION",
			"questionPid": "36c8f00c-44c9-4633-bfa7-2f3a3b51c1df"
		}
	]
}
```

You can also ask questions to an agent. This is useful for giving agents closed set of options to choose from and make the process more unified.

```json
{
	"actions": [
		{
			"type": "QUESTION",
			"allowedToRespond": ["AGENT", "EXTERNAL_AGENT"],
			"allowedToView": ["AGENT", "EXTERNAL_AGENT"],
			"allowCustomReply": false,
			"questionPid": "<Salted CX question PID>",
			"note": "What should the user take into consideration when answering this question."
		}
	]
}
```

See [Answer](https://help.salted.cx/en/articles/your-logic-requests) how to listen for answers when participants click on them.

### [](#customer-facing-questions)Customer Facing Questions

The questions that you ask the customers are translated into the communication platform. The below example shows a question asked to a customer in the Universal Chat. Depending on the preferences you allow the customers to provide a custom answer.

![](https://media.notiondesk.so/upload/6a9e645131cca032488049.png)

### [](#agent-facing-questions)Agent Facing Questions

Agent facing questions enable you to guide agents through decisions.

![](https://media.notiondesk.so/upload/6a9e64537bd39703552434.png)





## [](#ask-dynamic-question)Ask Dynamic Question

Asking a dynamic question enables you to give customers and other participant dynamically generated choices without the need for a question created in Salted CX. This enables you to have question and answers that take context into consideration. Answers to these questions are not in reporting but are visible in the [customer journey](https://help.salted.cx/en/collections/1755250527-customer-journey). The action supports the same optional properties as Ask Question (`allowedToRespond`, `allowedToView`, `allowCustomReply`, `note`, `reviewEngagementPid`, `channel`, `contactPid`, `content`, `emailSubject`), plus `question.shouldCreateReview` (Boolean, default `false`). Currently `shouldCreateReview` must stay `false` for dynamic questions — a QUESTION\_DYNAMIC action with `shouldCreateReview: true` is rejected and fails the whole request. Use the QUESTION action with a question defined in Salted CX when the answer should create a review.

When a participant choses an answer you will get the answer in a request sent to Your Logic so you can react to customer clicking on any of the options.

```json
{
  "actions": [
    {
      "type": "QUESTION_DYNAMIC",
      "question": {
        "externalId": "question1",
        "content": "What is your preffered time slot?",
        "answers": [
          {
						"externalId": "16-00",
						"content": "16:00 to 16:30"
					},
					{
						"externalId": "16-30",
						"content": "16:30 to 17:00"
					},
					{
						"externalId": "17-00",
						"content": "17:00 to 17:30"
					}
        ]

      }
    }
  ]
}
```

Example of asking a question to agentsSee [Answer](https://help.salted.cx/en/articles/your-logic-requests) how to listen for answers when participants click on them.





## [](#update-conversation)Update Conversation

Updates conversation properties. Property values are then propagated to individual engagements when they are completed. The top-level properties (`language`, `urgency`, `custom`, `info`, `serviceExternalId`, `serviceSourceId`, `desktop`) sit directly on the action. All attribute pairs listed below must be nested inside an `attributes` object — see the example. Field names are case-sensitive.

Property names that end with `externalId` reference entities that are reportable in analytics. External ID is the stable ID that you can use to reference the entity. If the entity already exists in analytics, users will see its user-friendly display name. If the entity is not available in analytics, it will be created with the External ID as a user-facing name (fallback). You can use the [Ingest API](https://help.salted.cx/en/collections/1755273563-ingest-api) to import user-facing values and other attributes for the entity.

Property names that end with `sourceId` enable to reference leaf entities imported from other data sources. For example if you have queues in a legacy contact center platform that you want to use within Live Conversations you use the `sourceId` of that legacy platform to reference the same same queue.

| Property | Type | Description |
|---|---|---|
| `language` | String | Identifier for the conversation language — two-letter [ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639_language_codes) language code such as `en`, `de`, `cs`. |
| `urgency` | Integer | The [urgency of the conversation](https://help.salted.cx/en/articles/1765376502-conversation-urgency) that sorts the conversations in Needs Help section in Live Conversations. |
| `custom` | Object | You can use `custom` attribute to store a custom object associated with the conversation. Keep it small — about 1kB at most (the limit is currently not enforced, but oversized objects may be rejected in the future). This enables you to keep conversation-related information in Salted CX without maintaining it in Your Logic. This enables you to handle some scenarios more easily, such as restarting or upgrading your service. We take the value of the `custom` attribute as-is. The custom attribute value has to be a valid JSON value to be parsed successfully. Beyond this requirement and size limitation, we do not do any validation of the value. The custom object can contain any inner structure. We do not process the content of the object in any way. Your Logic implementation is responsible for providing a complete object with all values set to the latest state. |
| `info` | Array | Structured information visible in the agent sidebar; items have `title`, `text`, and optional `url`. |
| `serviceExternalId``serviceSourceId` | String / UUID | Identifiers of the service associated with the conversation. |
| `desktop` | Object | Controls what agents can see and do in the desktop for this conversation — see the Desktop section. |



### [](#desktop)Desktop

The `desktop` object controls what agents can see and do in the agent desktop for this conversation. Each update replaces the whole stored desktop configuration — always send the complete object, not a diff. Elements you do not mention keep their default behavior (visible and enabled).

| Property | Type | Description |
|---|---|---|
| `defaultReply` | Object | Prefilled reply offered to the agent: `message` (required), optional `title`, and optional `subject` used when the reply goes out over email. An entry without a `message` is ignored. |
| `actions` | Object |  |
| `customActions` | Array |  |
| `attributes` | Array | Attribute fields in the desktop to control; each item has `id` (required) and `status` (`Disabled` or `Hidden`). |



Statuses are case-sensitive: `Disabled` shows the element but prevents its use, `Hidden` removes it from the desktop. Items with a missing `id` or an unrecognized `status` are dropped from the update.

```json
{
  "actions": [
    {
      "type": "CONVERSATION_UPDATE",
      "desktop": {
        "defaultReply": {
          "title": "Suggested reply",
          "subject": "Your order",
          "message": "Hello, thank you for reaching out about your order."
        },
        "actions": {
          "resolve": { "status": "Disabled" },
          "inviteExternal": { "status": "Hidden" }
        },
        "customActions": [
          { "id": "refund", "status": "Hidden", "title": "Issue Refund" }
        ],
        "attributes": [
          { "id": "orderNumber", "status": "Disabled" }
        ]
      }
    }
  ]
}
```

### [](#attributes)Attributes

The following reporting attributes are sent nested inside the `attributes` object of the action — not at the top level. All of them are optional strings (max 100 characters); only the fields present in the payload are updated.

| Property | Type | Description |
|---|---|---|
|  | String | Numbered attributes that enable to segment conversation by a custom dimensions. |
| `caseExternalId``caseSourceId` | String | The case is associated with the current engagement. Cases are units that can span many engagements, conversations, and even customers. Thus cases are no directly part of a customer journey as they may touch multiple customers. However, cases might be useful to calculate aggregated metrics to associate effort, costs, etc. with them. |
| `language`(legacy alias `languageExternalId`) | String | The predominant language associated with the engagement. In a multi-lingual contact center this enables you to segment engagements by the language you are serving. `languageSourceId` has been removed and is ignored. |
| `menuPathExternalId``menuPathSourceId` | String | The menu path the customer went through during the last menu engagement. |
| `outcomeExternalId``outcomeSourceId` | String | The outcome associated with the engagement. |
| `queueExternalId``queueSourceId` | String | The queue with which the engagement is associated with. The meaning differs by the type of the engagement. |
| `priorityExternalId``prioritySourceId` | String | The priority of the engagement categorized into discreet buckets such as High, Normal, Low. |
| `reasonExternalId``reasonSourceId` | String | The reason why the customers contact the company. This may be based on customer input, agent input or automatically detected based on the environment. |
| `reasonCategoryExternalId``reasonCategorySourceId` | String | Category for a reason that helps to organize reasons into a higher level units. |



```json
{
  "actions": [
    {
      "type": "CONVERSATION_UPDATE",
      "language": "en",
      "urgency": 1000,
      
      "attributes": {
	      "attribute01ExternalId": "Example Value 1",
	      "attribute01SourceId": "d0a1b2c3-0000-0000-0000-000000000001",
	      "attribute02ExternalId": "Example Value 2",
	      "attribute03ExternalId": "Example Value 3",
	      "attribute04ExternalId": "Example Value 4",
	      "caseExternalId": "Case ID",
	      "language": "en",
	      "menuPathExternalId": "main-customer-support",
	      "outcomeExternalId": "escalated-to-agent",
	      "queueExternalId": "queue-id",
	      "queueSourceId": "d0a1b2c3-0000-0000-0000-00000000000b",
	      "priorityExternalId": "High",
	      "reasonExternalId": "Custom Reason",
	      "reasonCategoryExternalId": "Custom Reason Category"
      },
      "info": [
	      {
		      "title": "Memos",
		      "text": "Holidays opening times for the partner: 9:00AM to 12:00PM"
	      },
	      {
		      "title": "Menu",
		      "url": "https://knowledgebase.company.com/article123",
		      "text": "Holidays opening times for the partner: 9:00AM to 12:00PM"
	      }
      ],
      "serviceSourceId": "56710d6f-72d2-658c-eefc-92554e59dead",
      "serviceExternalId": "YOUR-EXTERNAL-ID",
      "custom": {
	      "customer_name": "Adam",
	      "orderNumber": "ORDER-123",
	      "allOrdersInProgress": [
		      "ORDER-245",
		      "ORDER-982"
	      ]
      }
    }
  ]
}
```





## [](#update-customer)Update Customer

Updates custom customer properties. Note: the CUSTOMER\_UPDATE action currently supports only the attribute fields listed below — `contacts` and `custom` are not yet supported on this action and are ignored. All properties are composed by two parts:

- `<property name>ExternalId` — The identifier of the entity in an external system.

- `<property name>SourceId` — The identifier of an external system, as a UUID. This ID is provided by Salted CX upon request. A `SourceId` value that is not a valid UUID fails parsing of the whole request.

These two parts enable to solve collisions of IDs between individual systems.

| Property | Type | Description |
|---|---|---|
| `countryExternalId` | String | Country of the customer — [ISO 3166-1](https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes) two letter country code. Invalid codes are skipped. The canonical field name is `country`; `countryExternalId` is accepted as a legacy alias. |
| `categoryExternalId``categorySourceId` | String / UUID | Broad grouping of customers into categories. For example split between B2B and B2C customers. |
| `organizationExternalId``organizationSourceId` | String / UUID | Groups customers into their organizations. For example if you provide B2B services to large companies and you want to associate the individual customers with those companies. |
| `regionExternalId``regionSourceId` | String / UUID | Geographic region that the customer is in. This is typically a high level unit covering multiple states such as North America, EMEA, APAC, etc. |
| `segmentExternalId``segmentSourceId` | String / UUID | Groups customers by (market) segment enabling you to better understand differences in customer behavior in different demographics, areas of interest, etc. |
| `stateExternalId``stateSourceId` | String / UUID | The state eventually other territory that is part of the country. |



You can use `custom` attribute to store up to 1kB of custom object associated with the customer. This enables you to keep information related to the customer in Salted CX without having to maintain this information in Your Logic. This enables to handle some scenarios more easily — such as as restarting or upgrading your service.

We take the value of the `custom` attribute as-is. The custom attribute value has to be a valid JSON value to be parsed successfully. Beyond this requirement and size limitation we do not do any validation of the value. The custom object can contain any inner structure.

We do not process the content of the object in any way. Your Logic implementation is responsible for providing complete object with all values set to the latest state.

![](https://www.notion.so/icons/warning_yellow.svg?mode=light)

Your Logic has to be able to handle multiple parallel conversations from the same customer. While we ensure that we will sequence all requests for individual conversations we do no sequence requests for customers. Customers can be involved in multiple conversations by simply emailing you and chatting at the same time about different topics. Make sure you handle race conditions when updating the customer data. Multiple conversations can update it and read it in parallel. We keep the last value it receives as a whole. We do not resolve any conflicts nor do partial updates.





```json
{
	"requestId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
	"actions": [
		{
			"type": "CUSTOMER_UPDATE",
			
			"countryExternalId": "de",
			"segmentExternalId": "enterprise"
		}
	]
}
```





## [](#start-conversation)Start Conversation

Starts a conversation from your logic using the selected channel.

| Property | Type | Description |
|---|---|---|
| `customer` | Object | Object describing the customer. |
| `customer.displayName` | String | Name of the customer as it should show for the agent. It should not be protected personal information. We generally recommend using the first (given) name. |
| `customer.contact` | Object | Object containing the contact itself. |
| `customer.contact.contactType` | String | Type of the contact such as Email or Phone. |
| `customer.contact.contact` | String | The actual contact. |
| `conversation.channelVendor` | Enum |  |
| `conversation.brandPid` | UUID | Required. The brand the conversation belongs to. |
| `conversation.languageCustomer` | String (optional) | Customer language code. |
| `conversation.custom` | Object (optional) | Custom conversation properties. |
| `conversation.url` | String (optional) | Last visited URL to associate with the conversation. |



```json
{
  "actions": [
    {
      "type": "CREATE_CONVERSATION",
      "conversation": {
        "channelVendor": "EMAIL",
        "brandPid": "8a1b2c3d-0000-0000-0000-000000000001",
        "languageCustomer": "cs"
      },
      "customer": {
        "displayName": "Carol",
        "contact": {
          "contactType": "Phone",
          "contact": "+1098765431"
        },
        "relatedContacts": [
	        {
		        "contact": "+420123456789",
			      "contactType": "Phone"
	        },
	        {
		        "contact": "CUSTOMER-12345",
		        "contactType": "Custom"
	        }
        ]
      }
    }
  ]
}
```

Future target JSON```json
{
	"actions": [
		{
			"type": "START_CONVERSATION",
			
			"customer": {
				"displayName": "Radek",
				"contact": {
					"contactType": "Phone",
					"contact": "+1234567890",
				}
			},
			"conversation": {
				"channelVendor": "WhatsApp",
				"companyContact": "+1800111222333",
				
				"custom": {
				}
			}
		}
	]
} 
```









## [](#invite-external-agent)Invite External Agent

This action sends an invite to an external agent to join the conversation. The external agent will receive a notification (email) with link authorizing them to access the conversation.

| Property | Type | Description |
|---|---|---|
| `email` | String | Email that can be used to reach the external agent. This can be a person in your company that does not have user account in Salted CX. |
| `name` | String (required) | User facing name of the external agent. |
| `subject` | String (required) | Subject of the email sent to the external agent. |
| `message` | String (required) | The message to send to the external agent. Use this opportunity to communicate urgency and expectations. |
| `expires` | Time | The time until which the partner has access to the conversation. After this time period the link no longer enables the external agent to access the conversation. In case you want the external agent to engage in the conversation you need to send a new invite. The maximum expiration time is 10 days from the current time. |
| `permissions` | Object | Salted permissions object. (Upcoming) — currently ignored; access permissions for the invited agent are generated automatically. |



```json
{
  "actions": [
    {
      "type": "INVITE_EXTERNAL_AGENT",
      "email": "agent@company.cx",
      "name": "Agent Name",
      "subject": "Help with order",
      "message": "Hello, I need assistance with order from your shop.",
      "expires": "2025-07-29T10:30:00Z"
    }
  ]
}
```





## [](#customize-external-invites-upcoming)Customize External Invites  (Upcoming) 

Enables you to list email addresses that agents are enabled to invite into a conversation. This enables to offer these emails to the agent and also restricts their options. These restrictions do not apply to Your Logic.

| Property | Type | Description |
|---|---|---|
| `inviteSubject` | String | Email subject for all invitations. |
| `inviteMessage` |  |  |



```json
{
	"actions": [
		{
			"type": "CONVERSATION_UPDATE",
			
			"conversation": {
				"externalAgents": {
					"inviteSubject": "Help us with the Customer",
					"inviteMessage": "Hello, how are you?",
					
					"allowCustomization": false,
				
					"allowCustomEmails": true,
					"allowed":[
						{ 
							"name": "Partner",
							"email": "support@partner.com" 
						},
						{
							"name": "Partner - VIP", 
							"email": "vip@partner.com",
						}
					]
				}
			}
		}
	]
}
```





## [](#complete-engagement)Complete Engagement

This action enables you to tell that the engagement is considered complete.

| Property | Type | Description |
|---|---|---|
| `engagementPid` | PID | The engagement that should be completed. |
| `name` | String | The name of the engagement that is shown in the reporting. |
| `reasonCategory` | String (Optional) | Category of the contact reason associated with the engagement. |
| `reason` | String (Optional) | Contact reason associated with the engagement. |
| `outcomeCategory` | String (Optional) | Category of the outcome. |
| `outcomeType` | Enum |  |
| `outcomePid` | PID | The outcome of the engagement. |
| `cost` | Decimal | The costs associated with the engagement. If using LLMs you can feed the final cost here to be available for analytics. |



```json
{
  "actions": [
    {
      "type": "ENGAGEMENT_COMPLETE",
      "engagementPid": "582fa5da-d423-46ae-b69f-aa1d2b01f736",
      "name": "Engagement Outbound #2",
      "outcomePid": "c8b61d87-6fe4-44e2-a419-bbc0963f58f2",
      "outcomeType": "AGENT_RESOLVED",
      "cost": 0.6
    }
  ]
}
```





## [](#complete-conversation)Complete Conversation

This action completes the conversation and all of its engagements (if there are any). Complete conversation action has no properties.

```json
{
	"actions": [
		{
			"type": "CONVERSATION_COMPLETE"
		}
	]
}
```

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

Completing conversation is an indicator for the customer that the conversation is completed. However customer, bots and agents can contribute to a completed conversation and change its status to in progress again.









## [](#engage-your-logic)Engage Your Logic

In case Your Logic no longer wants to be included the conversation in any way it can let Salted CX know by setting the property `engageYourLogic` to `false`. From this moment Your Logic will receive no updates regarding this conversation.

You can also switch the flag to `true` when sending it without responding to any Your Logic event (as you will receive them). For example Your Logic can be performing a time consuming operation, ask not to receive events, after performing the operation it can return back and ask to be notified about the conversation again.

| Property | Type | Description |
|---|---|---|
| `engageYourLogic` | Boolean | Tells whether to engage Your Logic in this conversation. `true` — Your Logic will receive events for this conversation. `false` — Your Logic stops receiving events for this conversation. |



```json
{
	"requestId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
	"actions": [
		{
			"type": "ENGAGE_YOUR_LOGIC",
			"engageYourLogic": false
		}
	]
}
```





## [](#navigate-to-page-upcoming)Navigate to Page (Upcoming)

This action enables to navigate a user to the provided web page when using the [Universal Chat](https://help.salted.cx/en/articles/universal-chat-settings). This enables you to guide a user through a process in a more intective way.

When using a channel that does not support automatic navigation. Salted CX uses an alternative behavior such as showing a button that opens the target page.

| Property | Type | Description |
|---|---|---|
| `url` | String | The target URL the customer should be sent to including a protocol. |
| `target` | String | Attribute that tells in which window the page should open. The target cannot start with underscore \_ charcater as it has reserved meaning. `null` (default) — navigate in the same window in which the Universal Chat currnelty is `<framename>` — name of the frame to open the target in |
| `title` | String | Optional but recommended. Title for the fallback button or text for platforms that do not support navigation. If not provided and a button in necessary, Salted CX will use URL instead of the title. |



```json
{
	"requestId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
	"actions": [
		{
			"type": "NAVIGATE_TO_PAGE",
			"target": "help_123",
			"url": "https://help.salted.cx/article/to/navigate/to",
			"title": "Read the help article"
		}
	]
}
```





## [](#start-voice-call)Start Voice Call

The CALL\_START action starts an outbound voice call on the conversation. Salted CX dials the customer and connects the answered call either to a voice bot or to an agent.

| Property | Type | Description |
|---|---|---|
| `contact` | UUID | Required. PID of the customer's phone contact to dial. |
| `target` | String | Required, case-sensitive. `Bot` — the answered call is connected to a voice bot. `Agent` — the conversation is raised as Needs Help while the customer's phone is ringing, so an available agent can pick up the call. |
| `botVendor` | String | Required when `target` is `Bot`. Currently only `ElevenLabs` is supported. |
| `botId` | String | Required when `target` is `Bot`. Identifier of the ElevenLabs agent that should handle the call. The bot must have a phone number assigned in ElevenLabs. |



The action fails if a voice call is already in progress for the conversation, or if the bot cannot be resolved to a phone number in ElevenLabs.

```json
{
  "actions": [
    {
      "type": "CALL_START",
      "contact": "550e8400-e29b-41d4-a716-446655440001",
      "target": "Bot",
      "botVendor": "ElevenLabs",
      "botId": "agent_01234567890abcdef"
    }
  ]
}
```

## [](#mute-the-conversation-idea)Mute the Conversation  (Idea) 

This action mutes the conversation which agents do not receive any notifications about it. You can use this action to silence abusive customers. The messages will be still visible in the customer journey and Your Logic will receive requests related to the conversation.

```javascript
{
	"actions": [
		{
			"type": "CONVERSATION_MUTE",
			"mute": true
		}
	]
} 
```

## [](#block-conversation-idea)Block Conversation  (Idea) 

This action blocks the conversation. Salted CX blocks drops all messages related to this conversation from the customer.

```json
{
	"actions": [
		{
			"type": "CONVERSATION_BLOCK",
			"block": true
		}
	]
} 
```

## [](#mute-the-customer-idea)Mute the Customer  (Idea) 

This action mutes all the conversations (current and future) with the customers. Muted customers can write you and you will receive their messages in Your Logic.

```javascript
{
	"customer": {
		"muted": false
	}
	"actions": [
		{
			"type": "CUSTOMER_MUTE",
			"mute": true
		}
	]
} 
```

## [](#block-customer-idea)Block Customer  (Idea) 

This action blocks the customer. Salted CX blocks drops all messages related to this customer and prevents a conversation from starting.

```json
{
	"customer": {
		"muted": false
	}
	"actions": [
		{
			"type": "CUSTOMER_BLOCK",
			"block": true
		}
	]
}
```

*Tags: Your Logic*


---

## Customer Satisfaction

Source: https://help.salted.cx/en/articles/customer-satisfaction-surveys


Salted CX extracts customer satisfaction from supported platforms if they are available. You can report on customer satisfaction and use customer journey to understand what caused the customers to be happy or not as happy as you would like them to be.

Collecting and acting on customer satisfaction is a discipline by itself. This article tries to cover the basics of collecting customer satisfaction feedback.

Overall you are trying to get feedback to as many conversations as possible, as soon as possible in a way that helps you identify what to focus on and provides you with enough context (either from the conversation itself or from customer comments) that you can take an action.

## [](#general-recommendations)General Recommendations

There are some high-level recommendations that we will elaborate on later in the article:

- Keep it simple. Ask straightforward as few questions as possible. Questions that are easy to answer from the customer's perspective.

- Ask for a rating and opinion. Quantitative rating enables you to calculate averages, monitor trends, and easily find issues. Qualitative feedback enables you to uncover things you were not aware of and provide customer perspective on their experience.

- Maximize coverage. Try to ask customers for opinions on every single conversation you have with the customers.

- Time the survey appropriately: Send the survey shortly after the conversation while the experience is still fresh in the customer's mind. Make sure you do not ask in the middle of an ongoing request before you think it is resolved or at least over.

- Act on survey results. Make sure that you constantly monitor customer feedback and take action to improve customer satisfaction. Even when customer satisfaction rating stays the same and above your target, it is a good practice to check at least the negative customer experiences regularly.

## [](#keep-it-simple)Keep it Simple

A simple customer survey with few easy-to-answer questions increases the response rate and makes the results more reliable as customers are not confused when answering them:

There are general recommendations for keeping the survey simple:

- Minimum number of questions. Fewer questions equals a higher response rate. In most cases knowing that a customer is not satisfied is enough. You have the entire conversation in Salted CX to find out what went wrong. When considering adding questions always consider whether you will act on the specific questions and whether you want to delegate quality control to the customer or you can do it on your side.

- Plain language question. Ask plainly and directly without jargon and encourage customers to be honest and share as much as they can with you.

- Unambiguous clear answers. When forcing customers into picking answers, make sure the answers are not confusing, or overlapping and they cover all possible options. Use open-ended questions to give your customers the option to cover cases you have not thought of. Make sure people understand what exactly individual answers mean especially if you use numeric (stars) scales.

- Optional questions. If you decide you need to ask more questions that is a bare minimum, make the extra questions explicitly and visibly optional. It is better to get some feedback without the customers answering the optional questions than to get no feedback at all. If you ask more than one question, you can consider displaying the first one only and after the customer hits the submit displaying a follow-up to make sure you get at least the first one answered. Long forms can cause you to get much less feedback overall.

- Do not ask what you should know. You should not ask the customer for any information that you already know or the customer thinks you know such as questions they were asked in a menu, or IVR before they even talked to an agent. In Salted CX you should have those data already.

## [](#ask-for-a-rating-and-an-opinion)Ask for a Rating and an Opinion

One question is the least you can ask. However, it is difficult to ask for both quantitative and qualitative feedback in one question. So typical minimum you can get to are two questions — one rating and one free comment.

### [](#rating-questions)Rating Questions

Rating questions are great because it is easy to calculate averages, watch trends, and identify conversations that are below a threshold that need attention. Although there is of course subjectivity when answering the questions, there is also less room for interpretation.

The following table lists a couple of examples of questions you can ask and covers some of their advantages and disadvantages.

| Question | Possible Answers | Discussion |
|---|---|---|
| Was your request resolved? | Yes, No | Often resolving an issue has a critical impact on customer satisfaction. Unresolved issues typically have a higher chance of lower customer satisfaction. The problem with this question is that it does not cover the scenario where a customer had to go through a bad experience to resolve. So you almost always should pair this question with another rating question. To keep the number of questions minimal you might want to consider different means to detect successfully resolved requests, such as using Salted CX auto reviews. |
| How was the conversation you had with us? | Bad, Good, Great | These three options force customers out of the neutral zone. They enable customers to express dissatisfaction and a great experience. At the same time, it forces the customer not to be entirely neutral and choose Good instead of the neutral position. You might consider other options as the middle one, to be more neutral such as “Acceptable”, “OK”, etc. The advantage of having these three options is that they are easy to understand for customers and there is not that much ambiguity (which grows with granularity customers can choose from). |
| How would you rate the conversation on the scale from 1 to 5 stars? | Stars | The clear advantage of this question is that it is easy to understand and customers have a good understanding what starts means. The issue with stars and any other granular scale is that with growing granularity the boundaries between the individual options are not that clear and the scoring becomes very subjective. You can help with naming the stars such as 1 - Terrible, 2 - Bad, 3 - Neural, 4 - Good, and 5 - Great. However the same applies - the more granular scale the less customer are aligned on the meaning of individual scores. |
| On a scale of 0 to 10, how likely are you to recommend our business to a friend or colleague? | Scale 0 to 10 | This is an industry-standard metric for collecting customer satisfaction. The advantage of this metric is that you can compare yourself to other companies in your industry and use it in marketing if you are good at it. The problem is again with the granularity of the scale which NPS eliminates that it actually groups the responses into 3 categories at the end — Promoters, Passives, and Detractors. |
| How would you rate our company? | Stars, Bad/Good/Great, etc. | Often used by companies that want to distinguish between scenarios where an issue is on the company side or the agent side. In theory, this might help you to identify agents that significantly underperform or overperform despite customers being in a bad situation. In most scenarios, we have observed insignificant differences. This distinction might be useful in some scenarios but requires caution. Even when customers express opinions on the company the agent might have an impact on it - both positive and negative. Customers might be often unable to distinguish whether the experience is actually impacted by the company (terms, processes, etc.) or an agent. |
| How would you rate our agent? | Stars, Bad/Good/Great, etc. | Often used by companies that want to distinguish between scenarios where an issue is on the company side or the agent side. In theory, this might help you to identify agents that significantly underperform or overperform despite customers being in a bad situation. In most scenarios, we have observed insignificant differences. This distinction might be useful in some scenarios but requires caution. Even when customers express opinions on the company the agent might have an impact on it - both positive and negative. Customers might be often unable to distinguish whether the experience is actually impacted by the company (terms, processes, etc.) or an agent. |



Always adjust the wording to match your brand language.

### [](#opinion-questions)Opinion Questions

There are key reasons to ask customers for their opinion is to discover unknown problems — and cover your blind spots. As you company evolves and externalities change there might be a new issues customers encounter. Free text customer feedback is one of the sources that helps you raise issues you were not previously aware of.

The exact wording of the opinion question depends on your business and you should align it with your language. We generally recommend asking just one open-ended question at the end of the survey and encourage customers to elaborate on any answer they have given in the questions with a closed set of answers.

### [](#recommendation)Recommendation

Always consider your specific business needs. The survey that tends to work well in many cases has just two questions:

- How was the conversation you had with us? with possible answers Bad, Good, Great

- What we can do to make your experience better the next time? that is open-ended free text

Always word the questions to match your company brand language.

## [](#maximize-coverage)Maximize Coverage

The more customer feedback you have the better. You should gather feedback for any customer conversation with you no matter whether it was handled automatically or by people.

## [](#time-the-survey-appropriately)Time the Survey Appropriately

It is important to ask the customer as soon as possible so their experience is fresh. This will often lead to more opinionated, honest, and emotional answers. This is what you are looking for though. You want the customers’ opinions, honesty, and feelings they went through the experience with you. Customers will also remember the most details about the conversation and the customer survey will be isolated from another conversation that may follow right after that.

The ideal scenario is to ask in the same channel right after you believe the conversation is concluded. For example post call IVR in phone calls, survey right in the chat window on the web, email reply in a thread that is resolved.

## [](#act-on-survey-results)Act on Survey Results

Every company wants their customers to be rather more satisfied than less satisfied. For this reason, it is often expected that when the customer satisfaction is not great you try to mitigate negative root causes in the future. The effort to improve customer satisfaction differs significantly depending on the root cause. So it requires as with any other activity to weight effort and positive impact.

![](https://www.notion.so/icons/warning_yellow.svg?mode=light)

Always take into consideration that when customers respond to customer satisfaction surveys they often take into consideration their entire experience. The experience can be out of control of agents and even out of control of your company in some cases. Always verify the root cause for the feedback you receive from the customers.





General recommendations:

- Act as soon as possible. Review — especially — negative customer feedback as soon as you can ideally right after you receive it. If the root cause of the negative experience can affect more customers and can be resolved quickly you prevent more customers from being affected.

- Be transparent and invite people from the entire company. No company is perfect and it is a continuous process to improve your business. Visibility into customer satisfaction issues enables more people to resolve issues over time.

### [](#negative-customer-feedback)Negative Customer Feedback

One negative experience can overweight a lot of good experiences the customers have with you company, reduce loyalty and thus chances of future use of products and services by the customer and or their friends. Extremely negative experiences can also have more serious consequences including legal.

There are some common root causes and how you can act on them:

- Just one bad conversation. Something went wrong for any reason but it is obvious from the conversation it is not a persistent or repeating issue. You can try using semantic search to confirm it is really rare scenario. In this case, depending on the severity and your policy you can either ignore it or reach out to the customer and turn a bad customer experience into a better one by apologizing or giving compensation.

- Agent behavior issues. If agents behave in a way that is not up to the required standard you can talk to the agents on site and ask them to change their behavior. It is best to do this immediately and verify in the agent profile that the behavior is not an exception but a rule. You can for example check a few conversations in which the agent was engaged and received bad customer feedback.

- Team behavior issues. Similarly to agent behavior issues, you can use dashboards to check if the team dropped in customer satisfaction compared to a previous time period or if they are doing worse than the rest of the teams. Then it is worth talking to their team leader and checking whether the team can benefit from additional training for example.

- Process, product, or service issues. These take often significantly longer to fix or improve. You can use auto reviews in Salted CX to quantify the problem. Understanding the problem scale helps you to prioritize fixing the issue. Auto reviews also contribute to transparency as you can show them in a dashboard to let everyone know that you are aware of the problem.

### [](#positive-customer-feedback)Positive Customer Feedback

Managing a contact center does not always have to be about fixing issues. There are also opportunities that you can take advantage of when you receive extremely positive customer feedback:

- Encourage customers to provide public review. You can reach out to customers that give you very positive feedback and encourage them to review your company or your products and services in public forums such as Google Maps, Facebook, X, Instagram, Trustpilot, etc. Just make sure you have customer permission to use personal information to reach them with such a request.

- Encourage the customer to buy more of your products and services. Positive experience helps with loyalty. You can mark customers who had positive experiences with your company in the past in your CRM as they might be more likely to respond to future product and service offers.

## [](#changing-customer-surveys)Changing Customer Surveys

Depending on your current state and your goals you might need to change how you do customer surveys. The changes might impact the numbers you want to see. In constantly evolving business you need to be ready that trends may be influenced by these changes.

Some changes have an obvious impact, some might have an impact without people realizing it:

- Changing the questions entirely. In this scenario, you can expect that results from these surveys will not be comparable with the previous ones at all.

- Changing possible answers/scales. With different options, customers will interpret them differently and it may skew scores. For example number of people choosing an answer “Very Good” might drop when you rename it to “Great”.

- Rephrasing questions. Even when you just clarify or polish a question it may have an impact on customer perception and customers may reply differently.

As you have typically a 10% or higher response rate in customer surveys you will get a benchmark relatively quickly after changes. So although you will lose long-term continuity, you can get benchmark value to compare against in one day. For having a good benchmark value after changes we recommend timing the changes in customer surveys in a way that it does not collide with major events (new product releases, start of the season, process changes, etc.) that you expect might significantly affect customer satisfaction.

We recommend improving customer surveys over time and would recommend having a track record deep into history. The approach however depends on your company.

---

## Pulse Check

Source: https://help.salted.cx/en/articles/1784385666-pulse-check


Article short description

Pulse Check runs focused quality review programs for precisely selected conversations. Each category defines which conversations need attention and pairs them with the form or verification task designed for that scenario, so reviewers do not have to pick a sample, understand the selection rules, or choose the right form themselves.

![](https://pub-6e850a88e7c944bfb05bc715893a058d.r2.dev/Articles/Quality%20Assurance/PulseCheck.png)

Selection can be based on team, channel, time period, conversation metadata, or existing review results, so different scenarios can follow different review workflows.

Pulse Check supports two workflows:

- Targeted form reviews pair a type of conversation with a purpose-built form, so you can evaluate specific behaviors, risks, opportunities, or process-adherence scenarios.

- Review verification places Salted CX's existing review response workflow inside the targeted queue. You acknowledge a valid finding, dispute an incorrect one, mark the evidence as unclear, or return to it later. It works for any configured review topic; Knowledge Accuracy is one example.

The conversation, its customer journey context, summary, and review task are shown together.

## [](#how-pulse-check-relates-to-agent-home-and-vitals)How Pulse Check relates to Agent Home and Vitals

Pulse Check does not create a new review type or a separate verification system. It presents the familiar Salted CX review card and response choices inside a targeted team queue.

- Agent Home
    - Shows an agent's performance and feedback.
    
    
    - Agents open a conversation and respond to a review with Acknowledge, Dispute, or Unclear.

- Pulse Check
    - Gives team leaders and reviewers a configured queue of specific conversations and review scenarios.
    
    
    - It uses the same review responses and adds team and category navigation, Review Later, and To Review / Done progress.

- Vitals
    - Monitors the aggregate health of Auto Reviewers and their metrics, using acknowledgement and dispute signals to identify healthy metrics, investigate disputed reviews, and improve reviewer instructions.

A response you make in Pulse Check is saved on the underlying Salted CX review, not in a Pulse Check-only record. For Auto Reviews monitored in Vitals, acknowledgements and disputes feed the same signals Vitals aggregates.

Because this verification state is shared, a review completed elsewhere in Salted CX is no longer unverified and may leave your To Review queue. The Done tab shows reviews you completed.

## [](#start-a-review)Start a review

1. Open Pulse Check from the main navigation.

2. Open To Review.

3. Select a category from ‘To Review’ and conversation from the queue.

4. Read the conversation and complete the task in the review panel on the right.

5. Select the completion action. Pulse Check opens the next conversation.

You will meet two task types:

- Targeted form review: answer the questions in the selected form and select Done.

- Review verification: decide whether to Acknowledge, Dispute, or mark the finding Unclear.

Select Review Later in either workflow when you are not ready to complete the item.

## [](#navigate-the-queue)Navigate the queue

Pulse Check has three areas:

- Queue on the left: team, category, and conversation.

- Conversation in the middle, showing what happened and any customer journey context.

- Review panel on the right, showing a summary and the task to complete. If no summary was generated, the panel says so; you can still review from the conversation and other evidence.

Conversations are grouped into categories. A category tells you why a conversation was selected or which review to perform. The number beside a category shows how many conversations it holds; the icon beside each conversation shows its channel, such as chat, email, or voice. Select a category heading to expand or collapse it.

## [](#review-with-a-feedback-form)Review with a Feedback form

The correct form is already selected. Answer its questions or tag behavior while reading the conversation. Learn more about [Forms](https://help.salted.cx/en/articles/forms).

1. Select a conversation from To Review.

2. Read the relevant part of the customer journey.

3. Check the summaries and context in the review panel.

4. Answer the questions in the form.

5. Select Done.

Answers save automatically, so there is no separate save step. Any saved answers remain when you return.

Done becomes active only after the required completion answer has saved. Answering other questions does not complete the review on its own; you must select Done to move the conversation to your Done list.

Select Review Later to move on without completing the current review. The conversation stays in To Review.

## [](#verify-a-review)Verify a review

Some categories ask you to verify an existing review or AI finding. Read the conversation first, then check the review question, result or score, and the comment or evidence.

- Dispute needs a comment explaining what is incorrect and which evidence or knowledge should apply. You cannot submit an empty comment. Disputes help surface misalignment and improve auto reviews. Learn more in [Acknowledge and Dispute Reviews](https://help.salted.cx/en/articles/1755230871-acknowledge-and-dispute-reviews).

- Unclear does not require a comment. Use it only after reviewing the evidence and deciding it is not enough.

![](https://pub-6e850a88e7c944bfb05bc715893a058d.r2.dev/Articles/Quality%20Assurance/PulseCheck_Review1.png)

> Review Later and Unclear are not the same. Review Later leaves the review open with no decision, so it can appear again. Unclear records a completed decision that the evidence is insufficient. Use Review Later for timing, Unclear for uncertainty about the result.

## [](#move-through-the-queue)Move through the queue

After you save Done, Unclear, Dispute, or Acknowledge, Pulse Check opens the next conversation: the next in the current category, then the first in the next category, and the team view when nothing is left. Review Later follows the same sequence without completing the item.

If a save fails, Pulse Check keeps the conversation open and shows an error. Check your connection and try again.

## [](#return-to-completed-reviews)Return to completed reviews

The Done tab shows the reviews you completed for the selected team, not a combined history for all reviewers. Use it at the end of a session to confirm your work saved.

- Open a completed form review to see its saved answers. Updates still autosave, but the completion buttons are hidden.

- Open a completed verification to see the saved decision, with the selected action highlighted. You can change it to correct a decision.

## [](#how-conversations-are-selected)How conversations are selected

Your administrator prepares the teams, categories, forms, selection rules, and time periods. Pulse Check therefore shows a focused queue, not every conversation a team handled, and does not provide controls to change those rules. Conversations in a category run from the newest relevant review to the oldest.

The same conversation can appear in more than one category when it matches more than one scenario. Review it in the context of the category and form shown.

A conversation you expect may be absent when it belongs to another team, its relevant review falls outside the configured period, it does not match the category filters, the configured review is not completed, or another user already verified it.

The queue is focused work, not a representative sample of an agent's overall performance. Read the relevant conversation before deciding, use the summary to orient yourself rather than replace the conversation, and follow your organization's process for discussing disputes, repeated unclear cases, or knowledge gaps.

Learn more in [AI-Powered Quality Assurance](https://help.salted.cx/en/articles/1755188089-ai-powered-quality-assurance) and [Auto Reviews Accuracy](https://help.salted.cx/en/articles/1755254757-auto-reviews-accuracy).

---

## Automatically Detected Metrics

Source: https://help.salted.cx/en/articles/1768187346-automatically-detected-metrics


Article short description

Salted CX automatically processes supported conversations from Salted CX Live Conversations and integrated contact center platforms. It evaluates conversation content and available structured data, then surfaces relevant metrics in dashboards and reports. These metrics do not use biometric signals or claim to determine an employee's feelings, intentions, personality, or internal emotional state. Customers can configure their QA scorecards and omit criteria they do not wish to use.

| Property | Description |
|---|---|
| Expressed Satisfaction | Automatically detected customer satisfaction that is explicitly expressed by the customer. This can be statements like “your process is ridiculous”, “thank you so much, you saved my day”. |
| Customer Satisfaction | An interaction-level service indicator derived from observable conversation content, including customer wording and whether the exchange progresses smoothly. It does not claim to determine the customer's internal emotional state. |
| Understanding | Automatically detected the agent ability to understand the customer request and responding to the actual customer question including details and specifics related to that customer request. When agent responds too generally, responds to a question that is not asked or does not cover customer specifics of the requests it lowers the score. The need of customer to repeat their requests or important details of it lowers this score. |
| Adaptability | Automatically detects agent’s ability to deviate from their script of process to improve the customer experience. This metric requires as an input the processes description in the company for accurate numbers. Without those this metric is filled for small number of conversation where it can be assumed the agent is limited by a process. |
| Adherence | Automatically detects agent adherence to a script or process. This metric requires as an input the processes description in the company for accurate numbers. Without those this metric is filled for small number of conversation where it can be assumed the agent is limited by a process. |
| Clarity | Automatically detects clarity of the response. This tries to identify whether there is no ambiguity. Clarity score is also negatively impacted if there is unnecessary filling phrases or phrases that repeat simple customer requests. |
| Completeness | Automatically detects completeness of the agent responses. When the customer needs to ask additional questions the score is negatively impacted. |
| Language Skills | Automatically detects the agent language — spelling, grammar, interpunction and phrasing. |
| Persuasion | Automatically detects the agent ability to persuade the customer, address their concerns and objections. |
| Resolution | Automatically detects whether the customer request was resolved and categorizes it into one of these: `Resolved` — the agent resolved the customer request so the customer confirms it is resolved `Unresolved` — the customer gives a feedback that the proposed solution does not work for them and there is no other solution provided by the agent `No Response` — the agent seemingly provided a solution from the customer but there is not a followup response from the customer so it is not possible with high confidence to classify the resolution `Declined` — the agent provided the customer with a solution the customer does not agree with but the solution is based on the company policy and the conversation is considered concluded even when the customer request is not addressed they way the customer wanted |
| Severity | Automatically detects severity of the customer request. The severity indicates how impacted the customer would be if their request is not resolved. High severity indicates health impacts, high financial impact, inability to experience important live events, etc. Low severity are generic informative questions. |
| Empathic communication | Evaluates observable transcript wording, such as whether an agent acknowledges a stated concern and responds appropriately. It does not infer feelings, intentions, personality, or internal emotional states, and it does not use biometric signals. |
| Topic | The key topic that is discussed in the engagement. There is only one key topic per engagement even when there are potentially more topics discussed. The topic is intended to be filled by AI. |
| Topic Category | The categorization of the topics to higher level. The topic category is intended to be filled with AI. |



## [](#content-considered-by-auto-summary)Content Considered by Auto Summary

The conversations may be complex, involve multiple participants, the same agent may join multiple times, and the conversation may change channels.

The Auto Summary always provides results on the engagement level. Each conversation may have multiple auto summaries if it has multiple engagements.

Auto summary of individual engagements:

- Takes into consideration selected turns prior the analyzed engagement End Time no matter which engagement in the same conversation the turns are related to. This enables the auto summary to better understand the context (what customer mentioned before agent joined, what information was already collected, etc.)

- Ignores all turns after the engagement End Time even when they are associated with the engagement. This can be for example “Thank you”, “Goodbye” from the customer that is intentionally ignored as it is not actionable.

- At least one non-customer turn must be present in the engagement to be included in the auto summary.

- Auto Summary focuses on the given engagements but is influenced by the rest of the conversation.

- The maximum number of turns preceding the analyzed engagement is limited to 50, but may be lower in conversations that contain very long turns (long emails).

### [](#multiple-participants)Multiple Participants

The following conversation has 3 engagements. Bot, Frank (internal agent), and Japan Travel (external agent) are helping the customer with rebooking their trip.

![](https://www.notion.so/icons/chat_green.svg?mode=light)

Customer: Hello.







Bot joined the conversation.





![](https://www.notion.so/icons/chat_purple.svg?mode=light)

Bot: Hello, how can I help you?





![](https://www.notion.so/icons/chat_green.svg?mode=light)

Customer: I would like to rebook my trip to Japan. My family is sick.





![](https://www.notion.so/icons/chat_purple.svg?mode=light)

Bot: Is this related to the booking ORDER-123?





![](https://www.notion.so/icons/chat_green.svg?mode=light)

Customer: Yes.





![](https://www.notion.so/icons/chat_purple.svg?mode=light)

Bot: Let me escalate your request to an agent to verify whether the rebooking is possible for your case.





![](https://www.notion.so/icons/drafts_purple.svg?mode=light)

Please reach out to the travel agency to verify what the rebooking options are, because the rebooking is less than 2 weeks before departure.







Frank joined the conversation.





![](https://www.notion.so/icons/chat_blue.svg?mode=light)

Frank: Hello, my name is Frank. This trip starts in less than 2 weeks, so changes to the booking are restricted. Let me invite the travel agency to this conversation to see if there are any options. It can take some time for them to join. Please be patient. Is there anything else I can help you with in the meantime?







Frank invited Japan Travel to this conversation





![](https://www.notion.so/icons/chat_green.svg?mode=light)

Customer: Understood. I will wait.







Japan Travel joined the conversation.





![](https://www.notion.so/icons/chat_yellow.svg?mode=light)

Japan Travel: Hello, we can rebook the trip for a $100 change fee. Would you like me to change your travel dates? Available dates are: 10 August to 24 August and 7 Sep to 21 Sep





![](https://www.notion.so/icons/chat_green.svg?mode=light)

Customer: That is great. August, please.





![](https://www.notion.so/icons/chat_yellow.svg?mode=light)

Japan Travel: OK. Done. Anything else I can help you with?





![](https://www.notion.so/icons/chat_green.svg?mode=light)

Customer: No. That’s all.





![](https://www.notion.so/icons/chat_yellow.svg?mode=light)

Japan Travel: Great. Have a nice trip to Japan, bye.







Japan Travel left the conversation





↑ All turns before this event are used for the Japan Travel engagement auto summary

![](https://www.notion.so/icons/chat_green.svg?mode=light)

Customer: Wait, how do I pay the $100?





![](https://www.notion.so/icons/chat_blue.svg?mode=light)

Frank: The rebooking fee was paid from your credits. Is that OK?





![](https://www.notion.so/icons/chat_green.svg?mode=light)

Customer: Yes, that’s fine. Was just wondering.





![](https://www.notion.so/icons/chat_blue.svg?mode=light)

Frank: OK. Anything else I can help you with?





![](https://www.notion.so/icons/chat_green.svg?mode=light)

Customer: No, that’s it.







Frank left the conversation





↑ All turns before this event are used for the Frank engagement auto summary

![](https://www.notion.so/icons/chat_green.svg?mode=light)

Customer: Thanks.





![](https://www.notion.so/icons/chat_purple.svg?mode=light)

Bot: Was your request resolved?





![](https://www.notion.so/icons/cursor-button_green.svg?mode=light)

Customer: Yes.





![](https://www.notion.so/icons/chat_purple.svg?mode=light)

Bot: Thank you for reaching out to us. Have a nice day. Bye.







Bot left the conversation the conversation





↑ All turns before this event are used for the Bot engagement auto summary

![](https://www.notion.so/icons/chat_green.svg?mode=light)

Customer: Bye.





## [](#changing-channels)Changing Channels

Changing a channel creates a new engagement even when the agent does not change. This means one agent gets multiple separate engagements, with a separate auto-summaries per conversation.

![](https://www.notion.so/icons/chat_green.svg?mode=light)

Customer: Hello. I need to get the invoice by email.







Frank joined the conversation.





![](https://www.notion.so/icons/chat_blue.svg?mode=light)

Frank: Hello, my name is Frank. Sure. Give me a few moments, and I will send it over to you.







Frank changed the channel to Email.





↑ All turns before this event are used for the Frank engagement 1 auto summary

![](https://www.notion.so/icons/mail_blue.svg?mode=light)

Frank: Hello,As mentioned in the chat, the invoice is attached. Frank, Demo Adventures









![](https://www.notion.so/icons/chat_green.svg?mode=light)

Customer: Thank you.







Frank changed the channel to Chat.





↑ All turns before this event are used for the Frank engagement 2 auto summary

![](https://www.notion.so/icons/chat_blue.svg?mode=light)

Frank: You are welcome. Anything else I can help with?





![](https://www.notion.so/icons/chat_green.svg?mode=light)

Customer: No. That is all.





![](https://www.notion.so/icons/chat_blue.svg?mode=light)

Frank: You are welcome. Anything else I can help with?







Frank left the conversation





↑ All turns before this event are used for the Frank engagement 3 auto summary

![](https://www.notion.so/icons/chat_green.svg?mode=light)

Customer: Bye.





## [](#multiple-participants-overlapping)Multiple Participants Overlapping

The content from other participants is considered in the summary, bot it is not the focus of it. However it may provide an important context.

![](https://www.notion.so/icons/chat_green.svg?mode=light)

Customer: Hello. I need a refund for my order because I didn’t notice the trip starts from a different city with the same name.







Frank joined the conversation.





![](https://www.notion.so/icons/chat_blue.svg?mode=light)

Frank: Hello, I am sorry. In this case, we cannot provide the refund.





![](https://www.notion.so/icons/chat_green.svg?mode=light)

Customer: Are you serious? I spend thousands of dollars with you every year, and I cannot even get like $200 back in my entire lifetime? There are still 4 days until the trip starts, surely you can still sell my seat to somebody.





![](https://www.notion.so/icons/chat_blue.svg?mode=light)

Frank: I am sorry. According to our policy, I cannot do anything.





![](https://www.notion.so/icons/chat_green.svg?mode=light)

Customer: I want to speak with your manager.





![](https://www.notion.so/icons/chat_blue.svg?mode=light)

Frank: OK. I understand. I have invited my manager to this conversation. Please give her a few moments.





![](https://www.notion.so/icons/chat_green.svg?mode=light)

Customer: OK.







Mellisa joined the conversation.





![](https://www.notion.so/icons/chat_blue.svg?mode=light)

Mellisa: Hello, I am really sorry for the inconvenience. I have looked into the case, and in this exceptional case, I can authorize a refund to the credits in your account. Is that acceptable?





![](https://www.notion.so/icons/chat_green.svg?mode=light)

Customer: That’s OK. Thank you.





![](https://www.notion.so/icons/drafts_blue.svg?mode=light)

Authorized this exceptional refund due to excessive spending by the customer and a clean history.





![](https://www.notion.so/icons/chat_blue.svg?mode=light)

Mellisa: No problem. You should already see the full amount in your credits. Anything else we can help you with?





![](https://www.notion.so/icons/chat_green.svg?mode=light)

Customer: Do the credits expire on something?





![](https://www.notion.so/icons/chat_blue.svg?mode=light)

Frank: These credits do not expire, and you can spend them on any experience on our websites.







Mellisa left the conversation.





↑ All turns before this event are used for Melissa's engagement auto summary

![](https://www.notion.so/icons/chat_green.svg?mode=light)

Customer: Thanks.





![](https://www.notion.so/icons/chat_blue.svg?mode=light)

Frank: Anything else I can help you with?





![](https://www.notion.so/icons/chat_green.svg?mode=light)

Customer: That’s it.





![](https://www.notion.so/icons/chat_blue.svg?mode=light)

Frank: Great. Have a nice day. Goodbye.







Frank left the conversation.





↑ All turns before this event are used for Frank's engagement auto summary

![](https://www.notion.so/icons/chat_green.svg?mode=light)

Customer: Bye

---

## What are AI Agents in Salted?

Source: https://help.salted.cx/en/articles/what-are-ai-agents-in-salted


Understand how customer-facing AI agents operate conversations in Salted, use knowledge and tools, collaborate with people, and remain subject to operational controls.

AI Agents are customer-facing automation that can interpret requests, use knowledge and tools, perform permitted actions, and operate a Salted customer conversation. They participate in Live Conversations alongside customers, human agents, and external experts.

An AI Agent is not the same thing as the automation logic around the conversation. An AI Agent can be one part of that logic, alongside deterministic menus, rules, integrations, and workflows that do not require generative AI. In Salted configuration and technical documentation, this automation logic is called Your Logic.

## [](#what-an-ai-agent-can-do)What an AI Agent can do

Depending on the implementation, knowledge, tools, and permissions, an AI Agent can:

- understand a customer's free-text request,

- answer from approved knowledge and policies,

- ask follow-up questions and collect required information,

- present structured choices or next-step buttons,

- retrieve customer, order, account, booking, or case data,

- perform permitted business actions through connected systems,

- update conversation context and classification,

- route the interaction or ask a human for help,

- invite a specialist or external expert,

- complete eligible work and ask whether the customer's need was resolved.

The exact capabilities come from the configured tools and automation logic. The model should not be treated as having access or authority it has not explicitly been given.

## [](#knowledge-and-tools)Knowledge and tools

An AI Agent can use two broad sources of capability:

### [](#knowledge)Knowledge

Knowledge explains products, policies, procedures, eligibility, tone, and other information the AI needs to answer correctly. It can be provided through configured content, skills, files, or connected knowledge sources.

Knowledge should be governed like an operational dependency. Conflicting or outdated instructions can produce inconsistent behavior even when the AI model is working as designed.

### [](#tools-and-actions)Tools and actions

Tools let the AI retrieve data or ask the surrounding automation logic to perform controlled operations. A tool can check an order, look up an account, create a cart, issue an allowed refund, send a payment or booking link, classify a conversation, or invoke another supported business capability.

Consequential actions should be protected by permissions, deterministic rules, limits, and human approval when appropriate. Tool availability is not the same as permission to use it in every situation.

## [](#structured-and-free-text-interaction)Structured and free-text interaction

Salted can combine:

- free-text conversation,

- menus and customer-facing questions,

- dynamically selected follow-up options,

- files and supported media,

- channel-specific behavior.

The experience should clearly identify that the person is interacting with AI where applicable. The customer does not need a technical explanation of every internal transition between menus, rules, and generative AI. The workflow should preserve context as the customer moves between these modes.

## [](#working-with-human-agents)Working with human agents

An AI Agent can involve a person in several ways:

- request a bounded approval or decision,

- ask for human assistance when it cannot proceed safely,

- prepare context and a suggested reply for the person who joins,

- hand over an unstructured or sensitive interaction,

- remain silent while a human owns the conversation,

- continue after the human contribution when the automation logic knows how to proceed,

- remain visible to authorized supervisors, who can monitor the active conversation and proactively join or take over when intervention is needed.

This makes human involvement a configurable part of the workflow rather than a single one-way escalation path.

## [](#operational-control)Operational control

A production AI Agent should operate within explicit boundaries:

- which knowledge sources it may use,

- which tools and actions it may call,

- which data it may access,

- which decisions require deterministic checks,

- which actions require human approval,

- how confidence and failure affect escalation,

- what the customer is told while waiting,

- how conversation state, reason, priority, and outcome are recorded,

- how new versions are tested before rollout.

Salted and the configured automation logic can provide the conversation and action controls. The organization remains responsible for defining the policy and system authority behind them.

## [](#channel-behavior)Channel behavior

AI Agents can participate in supported digital and connected voice workflows, but the interaction model differs by channel. Chat can use menus and real-time replies, email requires thread-aware free text, WhatsApp can require templates, and voice has its own call lifecycle and latency requirements.

Confirm the production maturity and limitations of each channel and integration for the account.

## [](#evaluation-and-improvement)Evaluation and improvement

AI-operated conversations can feed the same Customer Journey, Quality Intelligence, Search, Ask, analytics, and review workflows used for human interactions. Teams can inspect:

- whether the AI used correct knowledge,

- whether it called the right tool,

- whether it followed policy,

- whether escalation happened at the right time,

- whether a human correction should become a knowledge, workflow, or tool improvement,

- whether the customer outcome was actually resolved.

## [](#technical-documentation)Technical documentation

- See [How automation logic controls a customer conversation](https://help.salted.cx/en/articles/how-automation-logic-controls-a-customer-conversation) for how automation logic controls the conversation.

- See [Conversations SDK](/2af5d3a2a8dc80f0a332f9549fc39c79) for the Conversations SDK overview.

- See [AI Setup](/2fd5d3a2a8dc8007b372cb1ad7c40093) for AI setup.

- See [Intents](/2f75d3a2a8dc80028e25d255e71a10e8) for intents.

- See [Conversations SDK Testing](/37a5d3a2a8dc80b7a001ec2d5421df07) for Conversations SDK testing.

- See [How AI and human agents work together in Salted](https://help.salted.cx/en/articles/how-ai-and-human-agents-work-together-in-salted) for human-AI collaboration.

## [](#availability)Availability

The packaged AI Agent offering, supported models, knowledge sources, tools, channels, testing, observability, and deployment responsibilities can vary. Confirm the current Salted-managed and developer-configured options before making a production commitment.

*Tags: Live Conversations, Your Logic*


---

## What are AI Agents in Salted?

Source: https://help.salted.cx/en/articles/what-are-ai-agents-in-salted


Understand how customer-facing AI agents operate conversations in Salted, use knowledge and tools, collaborate with people, and remain subject to operational controls.

AI Agents are customer-facing automation that can interpret requests, use knowledge and tools, perform permitted actions, and operate a Salted customer conversation. They participate in Live Conversations alongside customers, human agents, and external experts.

An AI Agent is not the same thing as the automation logic around the conversation. An AI Agent can be one part of that logic, alongside deterministic menus, rules, integrations, and workflows that do not require generative AI. In Salted configuration and technical documentation, this automation logic is called Your Logic.

## [](#what-an-ai-agent-can-do)What an AI Agent can do

Depending on the implementation, knowledge, tools, and permissions, an AI Agent can:

- understand a customer's free-text request,

- answer from approved knowledge and policies,

- ask follow-up questions and collect required information,

- present structured choices or next-step buttons,

- retrieve customer, order, account, booking, or case data,

- perform permitted business actions through connected systems,

- update conversation context and classification,

- route the interaction or ask a human for help,

- invite a specialist or external expert,

- complete eligible work and ask whether the customer's need was resolved.

The exact capabilities come from the configured tools and automation logic. The model should not be treated as having access or authority it has not explicitly been given.

## [](#knowledge-and-tools)Knowledge and tools

An AI Agent can use two broad sources of capability:

### [](#knowledge)Knowledge

Knowledge explains products, policies, procedures, eligibility, tone, and other information the AI needs to answer correctly. It can be provided through configured content, skills, files, or connected knowledge sources.

Knowledge should be governed like an operational dependency. Conflicting or outdated instructions can produce inconsistent behavior even when the AI model is working as designed.

### [](#tools-and-actions)Tools and actions

Tools let the AI retrieve data or ask the surrounding automation logic to perform controlled operations. A tool can check an order, look up an account, create a cart, issue an allowed refund, send a payment or booking link, classify a conversation, or invoke another supported business capability.

Consequential actions should be protected by permissions, deterministic rules, limits, and human approval when appropriate. Tool availability is not the same as permission to use it in every situation.

## [](#structured-and-free-text-interaction)Structured and free-text interaction

Salted can combine:

- free-text conversation,

- menus and customer-facing questions,

- dynamically selected follow-up options,

- files and supported media,

- channel-specific behavior.

The experience should clearly identify that the person is interacting with AI where applicable. The customer does not need a technical explanation of every internal transition between menus, rules, and generative AI. The workflow should preserve context as the customer moves between these modes.

## [](#working-with-human-agents)Working with human agents

An AI Agent can involve a person in several ways:

- request a bounded approval or decision,

- ask for human assistance when it cannot proceed safely,

- prepare context and a suggested reply for the person who joins,

- hand over an unstructured or sensitive interaction,

- remain silent while a human owns the conversation,

- continue after the human contribution when the automation logic knows how to proceed,

- remain visible to authorized supervisors, who can monitor the active conversation and proactively join or take over when intervention is needed.

This makes human involvement a configurable part of the workflow rather than a single one-way escalation path.

## [](#operational-control)Operational control

A production AI Agent should operate within explicit boundaries:

- which knowledge sources it may use,

- which tools and actions it may call,

- which data it may access,

- which decisions require deterministic checks,

- which actions require human approval,

- how confidence and failure affect escalation,

- what the customer is told while waiting,

- how conversation state, reason, priority, and outcome are recorded,

- how new versions are tested before rollout.

Salted and the configured automation logic can provide the conversation and action controls. The organization remains responsible for defining the policy and system authority behind them.

## [](#channel-behavior)Channel behavior

AI Agents can participate in supported digital and connected voice workflows, but the interaction model differs by channel. Chat can use menus and real-time replies, email requires thread-aware free text, WhatsApp can require templates, and voice has its own call lifecycle and latency requirements.

Confirm the production maturity and limitations of each channel and integration for the account.

## [](#evaluation-and-improvement)Evaluation and improvement

AI-operated conversations can feed the same Customer Journey, Quality Intelligence, Search, Ask, analytics, and review workflows used for human interactions. Teams can inspect:

- whether the AI used correct knowledge,

- whether it called the right tool,

- whether it followed policy,

- whether escalation happened at the right time,

- whether a human correction should become a knowledge, workflow, or tool improvement,

- whether the customer outcome was actually resolved.

## [](#technical-documentation)Technical documentation

- See [How automation logic controls a customer conversation](https://help.salted.cx/en/articles/how-automation-logic-controls-a-customer-conversation) for how automation logic controls the conversation.

- See [Conversations SDK](/2af5d3a2a8dc80f0a332f9549fc39c79) for the Conversations SDK overview.

- See [AI Setup](/2fd5d3a2a8dc8007b372cb1ad7c40093) for AI setup.

- See [Intents](/2f75d3a2a8dc80028e25d255e71a10e8) for intents.

- See [Conversations SDK Testing](/37a5d3a2a8dc80b7a001ec2d5421df07) for Conversations SDK testing.

- See [How AI and human agents work together in Salted](https://help.salted.cx/en/articles/how-ai-and-human-agents-work-together-in-salted) for human-AI collaboration.

## [](#availability)Availability

The packaged AI Agent offering, supported models, knowledge sources, tools, channels, testing, observability, and deployment responsibilities can vary. Confirm the current Salted-managed and developer-configured options before making a production commitment.

*Tags: Live Conversations, Your Logic*


---

## What is Agent Desktop?

Source: https://help.salted.cx/en/articles/what-is-agent-desktop


Understand the human and supervisory workspace inside Live Conversations, including monitoring ongoing AI-led conversations, joining or taking over, active work queues, context, replies, assistance, actions, and operational controls.

Agent Desktop is the human and supervisory workspace inside Live Conversations. It brings active conversations, customer context, replies, assistance, actions, and operational controls into one place. Human agents can handle assigned work, while authorized supervisors can monitor ongoing AI-led and human conversations before deciding whether to intervene.

Agent Desktop is not only a transcript viewer or a separate AI copilot. It is the interface where people observe and operate customer conversations, collaborate with AI agents and external experts, and take over customer communication when human judgment or ownership is needed.

## [](#find-and-organize-active-work)Find and organize active work

Depending on permissions and account configuration, the Live Conversations navigation can include:

- My Conversations for interactions the current human agent is handling.

- Help Needed for conversations where automation or another participant has requested human assistance.

- Recently Left for interactions the agent recently stopped handling.

- Reach Back for selected abandoned conversations that require follow-up.

- All In Progress and Overview for users who can supervise the wider operation.

Queues, filters, assignment, concurrency, and visibility depend on the account's routing and permission model.

## [](#monitor-join-and-take-over-ai-led-conversations)Monitor, join, and take over AI-led conversations

Authorized supervisors can view conversations across All In Progress and the operational Overview, including conversations currently handled by automation without a human agent engaged. They can open an active conversation to inspect the transcript, participants, alerts, routing, and available context without first joining it.

When intervention is needed, a user with the required permissions can:

- join an ongoing conversation even when it has not entered Help Needed,

- take over customer communication from the AI-led workflow,

- assign the conversation to another human agent,

- contribute a bounded decision or a full customer-facing response,

- leave after the intervention so automation can continue when the configured workflow supports it.

Monitoring does not itself create a human-agent engagement. Joining does: the person becomes an active participant and can communicate with the customer. Whether automation pauses, remains silent, assists the person, or resumes afterward is determined by the configured workflow and operational controls.

## [](#work-with-the-customer-conversation)Work with the customer conversation

The workspace can bring together:

- the live transcript and participant activity,

- customer identity and available customer-journey context,

- the reply composer and channel-specific fields,

- internal and external notes,

- files and attachments on supported channels,

- prepared replies and customer questions,

- information panels and links supplied for the current case,

- conversation attributes such as queue, priority, reason, and outcome.

The reply experience adapts to the channel. For example, email can include a subject, voice interactions can expose call controls, and supported messaging channels can offer their own delivery behavior. Confirm channel availability and limitations for the account before rollout.

## [](#assistance-while-a-human-works)Assistance while a human works

Depending on configuration, a human agent may receive:

- a suggested or prefilled reply that can be edited before sending,

- AI-assisted reply improvement,

- prepared replies and shortcuts,

- a quick message telling the customer that work is in progress,

- an agent-facing question that asks for a structured decision,

- information panels containing policy, case, customer, or system context,

- contextual links into an internal system or knowledge source.

These features reduce unnecessary navigation and help the human focus on the judgment or communication that requires a person.

## [](#dynamic-controls-from-automation-logic)Dynamic controls from automation logic

Configured automation logic can influence what the human sees and can do in Agent Desktop. This can include:

- proposing a default reply,

- showing, disabling, or hiding custom actions,

- showing or restricting conversation attributes,

- controlling standard actions such as leaving, resolving, waiting for the customer, asking for help, or inviting an external participant,

- displaying information panels,

- setting routing, priority, reason, outcome, customer classification, or an external case reference.

In Salted configuration and technical documentation, this automation logic is called Your Logic. The exact UI labels in configuration and reference documentation must remain unchanged. Concept pages explain the purpose; technical guides use the same names that users see in Salted.

## [](#human-ai-collaboration-in-agent-desktop)Human-AI collaboration in Agent Desktop

A human does not always need to take permanent ownership of the interaction. Depending on the workflow, the human can:

- answer a bounded approval or guidance question,

- join and communicate with the customer,

- take over an unstructured or sensitive part of the case,

- ask another person for help,

- invite an external expert,

- leave after contributing the required judgment so AI can continue,

- proactively join and take over an AI-led conversation before automation explicitly requests help.

This preserves context and lets scarce human attention be applied where it changes the outcome.

## [](#what-agent-desktop-does-not-decide-by-itself)What Agent Desktop does not decide by itself

Agent Desktop presents the conversation and controls. Business policy should still be enforced by the appropriate systems and automation logic. A consequential action should not depend only on a generated suggestion or a prompt when a deterministic rule, permission check, or human approval is required.

## [](#technical-documentation)Technical documentation

This article explains the product concept. It does not replace configuration and reference guides.

- For the agent workflow, see [Handling Live Conversation](https://help.salted.cx/en/articles/live-conversations-agent).

- For dynamic controls and suggested replies, see [Dynamic Agent Desktop](https://help.salted.cx/en/articles/1781867273-dynamic-agent-desktop).

- For structured decisions shown only to agents, see [Agent Facing Questions](/2d25d3a2a8dc806fa4e4f15766c30af1).

- For the broader operating model, see [How AI and human agents work together in Salted](https://help.salted.cx/en/articles/how-ai-and-human-agents-work-together-in-salted).

## [](#availability)Availability

The exact queues, channels, controls, information panels, actions, and AI assistance available in Agent Desktop depend on permissions, account configuration, integration, and current product maturity. Verify the relevant setup and reference documentation before making a production commitment.

*Tags: Live Conversations, Your Logic*


---

## Amazon Connect Integration

Source: https://help.salted.cx/en/articles/integration-amazon-connect


This article provides a step by step guide on how to setup an IAM role and policy for secure integration of Amazon Connect with Salted CX.

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

Prerequisites: To connect your Amazon Connect to Salted CX, you will need an AWS account and have administrator privileges.





1. Configure a Kinesis Data Stream as the target for Contact Events in Amazon EventBridge. Please refer to the [official AWS documentation](https://docs.aws.amazon.com/connect/latest/adminguide/contact-events.html) for instructions.

2. Open the [Create new AWS IAM role page](https://us-east-1.console.aws.amazon.com/iamv2/home?region=us-east-1#/roles/create).![](https://media.notiondesk.so/upload/689de8486e3bd677812896.png)

3. Select the AWS account and enter the Salted CX AWS Account ID, `<span class="fw-bold">380525299792</span>`, in the Account ID field.![](https://media.notiondesk.so/upload/689de84b9d5c3485487775.png)

4. Select the Require external ID checkbox and enter the External ID and click Next. > The automatically generated External ID is associated with your account. You will receive your External ID upon request.
    
    ![](https://media.notiondesk.so/upload/689de84ec6030386164446.png)

5. In the Add permissions step, click Next.

6. In the Name, review, and create step, specify the role name, for example Salted, and then click Create role at the bottom of the page.![](https://media.notiondesk.so/upload/689de8515da7b059982653.png)

7. Click the Salted role you created.![](https://media.notiondesk.so/upload/689de853c6d32912795158.png)

8. On the Summary page for the role, select Create inline policy.![](https://media.notiondesk.so/upload/689de857316b1145523252.png)

9. Go to the JSON tab and copy the following policy. Then, paste it into the Policy editor and click Next.![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)
    
    Replace Resource with a list of Amazon Kinesis Data Stream ARNs that you would like to integrate with Salted CX. To achieve full integration with Salted, allow [Contact events](https://docs.aws.amazon.com/connect/latest/adminguide/contact-events.html), [Contact records](https://docs.aws.amazon.com/connect/latest/adminguide/ctr-data-model.html), and [Agent event](https://docs.aws.amazon.com/connect/latest/adminguide/agent-event-streams.html) streams.
    
    
    
    
    
    ```plain
    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Effect": "Allow",
                "Action": [
                    "kinesis:GetRecords",
                    "kinesis:GetShardIterator",
                    "kinesis:DescribeStream",
                    "kinesis:ListShards"
                ],
                "Resource": "<replace with list of Amazon Kinesis Data Stream ARNs>"
            }
        ]
    }
    ```
    
    ![](https://media.notiondesk.so/upload/689de8599e7cf728079901.png)

10. In the Review and created step, specify the policy name, for example salted-kinesis, and then click Create policy at the bottom of the page.![](https://media.notiondesk.so/upload/689de85d422b4702299649.png)

11. Congratulations! You have completed all the configuration steps to integrate your Amazon Kinesis Data Stream with Salted CX. Please provide your Amazon Kinesis Data Stream ARN and IAM role ARN to the Salted CX team. Thank you.![](https://media.notiondesk.so/upload/689de8604fcc6072050729.png)Kinesis Data Stream ARN
    
    AWS Role ARN:
    
    ![](https://media.notiondesk.so/upload/689de86257f3f474187219.png)Kinesis Role ARN

## [](#transcript-in-customer-journey)Transcript in Customer Journey

There are two ways how to enable access to





- [Chat Only](https://help.salted.cx/en/articles/integration-amazon-connect#0adaa53668b943fbbb59a1a16c20b976)

- [Voice &amp; Chat](https://help.salted.cx/en/articles/integration-amazon-connect#1d289acfaa944fff8881e0d48883e9f7) — You need [Amazon Connect Contact Lens](https://aws.amazon.com/connect/contact-lens/) (paid option) enabled

## [](#enable-transcripts-in-customer-journey)Enable Transcripts in Customer Journey

You need to enable access for Salted CX to AWS S3. In this process, you will need to collect information that is necessary. When you encounter this information, store this information and share it securely with Salted CX.





Salted CX needs the following information to connect to your Amazon Connect S3 bucket:

- [S3 URI to the Chat Transcripts Folder](https://help.salted.cx/en/articles/integration-amazon-connect#aa378d6fe9c34f9981f37be8f8ebd420)

- [Access to S3 Bucket with Amazon Connect Data](https://help.salted.cx/en/articles/integration-amazon-connect#aa378d6fe9c34f9981f37be8f8ebd420)





- [Amazon Connect Access URL](https://help.salted.cx/en/articles/integration-amazon-connect#e4e3d315a0e04542b8041a30f21b9115)

## [](#chat-transcripts-s3-uri)Chat Transcripts S3 URI

1. Navigate to AWS Console ⏵ Amazon Connect

2. Click on the Instance that you integrate with Salted CX

3. Select Data storage ⏵ Chat Transcripts ⏵ Edit

![](https://media.notiondesk.so/upload/689de86570412812419752.png)

1. Click Enable chat transcripts and select S3 bucket where you wish to save your transcripts

![](https://media.notiondesk.so/upload/689de8675792e404892359.png)

1. After saving the settings navigate back to Data storage and provide S3 URI where you transcripts are stored

![](https://media.notiondesk.so/upload/689de8695d2b3779650682.png)

## [](#access-to-s3-bucket)Access to S3 Bucket

Salted CX needs permissions to read chat transcripts from S3. You configured S3 folder for chat transcripts in [the previous step](https://help.salted.cx/en/articles/integration-amazon-connect#4e39540bad9949ebad90dd6ece7fc19c).

Follow [AWS documentation](https://docs.aws.amazon.com/AmazonS3/latest/userguide/example-bucket-policies.html) to provide S3 permissions with Salted CX account.

## [](#amazon-connect-access-url)Amazon Connect Access URL

1. Navigate to AWS Console ⏵ Access URL

2. Provide Access URL of the instance that you integrate with Salted CX

![](https://media.notiondesk.so/upload/689de86b52969250225212.png)

## [](#voice-chat-transcripts)Voice &amp; Chat Transcripts

### [](#requirements)Requirements

Salted CX retrieves data to be able to analyze them. You need to enable access of Salted CX to AWS S3. During this process, you will need to collect information that is necessary. When you encounter this information, store this information securely and share it with Salted CX.

Salted CX needs the following information to connect to Amazon Connect S3 bucket:

- [Enable Chat Transcripts](https://help.salted.cx/en/articles/integration-amazon-connect#1fe5629f3f4141838e34568c36662e43)

- [Enable Voice Recordings](https://help.salted.cx/en/articles/integration-amazon-connect#85fda5e1deba4ceca7ba5dbfe155abb8)

- [Configure Flow with Enabled Recordings and Analytics](https://help.salted.cx/en/articles/integration-amazon-connect#64df33bb49f44e1885f2567b2ecc64dd)

- [Access to S3 Bucket with Amazon Connect Data](https://help.salted.cx/en/articles/integration-amazon-connect#9eca88d73757469d859b2948109a1ce1)

- [Amazon Connect Access URL](https://help.salted.cx/en/articles/integration-amazon-connect#9ccf4a5b0dd04126aeba9e92c0066d63)

### [](#enable-chat-transcripts)Enable Chat Transcripts

1. Navigate to AWS Console ⏵ Amazon Connect

2. Click on the Instance that you integrate with Salted CX

3. Select Data storage ⏵ Chat transcripts ⏵ Edit

![](https://media.notiondesk.so/upload/689de86d41952258970338.png)

1. Check Enable chat transcripts

![](https://media.notiondesk.so/upload/689de86f3f51c108321131.png)

### [](#enable-voice-recordings)Enable Voice Recordings

1. Navigate to AWS Console ⏵ Amazon Connect

2. Click on the Instance that you integrate with Salted CX

3. Select Data storage ⏵ Call recordings ⏵ Edit

![](https://media.notiondesk.so/upload/689de87119b68056162862.png)

1. Click Enable call recording

![](https://media.notiondesk.so/upload/689de8732f786869946117.png)

### [](#configure-flow-with-enabled-recordings-and-analytics)Configure Flow with Enabled Recordings and Analytics

There can be multiple flows where the following widget / functionality needs to be configured depending on your IVR / Flow settings. The main idea is to enable the recording and follow-up analysis before the call or chat is assigned to the representative.

In this example we have just one flow for both channels (chat &amp; voice). We configure the widget at the start of the flow to cover everything in one setup:

1. Click Routing menu item (three way fork icon) in the left hand navigation

2. Click Flows in the Routing menu

![](https://media.notiondesk.so/upload/689de8753bd8c030115312.png)

1. Select flow in which you want to enable recording

2. Add the Set recording and analytics behavior into your flow

![](https://media.notiondesk.so/upload/689de877392b3596020541.png)

1. In Call recording section enable recording by clicking On radio button

2. Make sure Agent and customer option is selected

![](https://media.notiondesk.so/upload/689de8791bd3f964852412.png)

1. In Analytics section enable analytics by clicking On radio button

2. Make sure Enable speech analytics is checked

3. Choose Post-call analytics option for the best transcription quality

4. Make sure Enable chat analytics is checked

![](https://media.notiondesk.so/upload/689de87b05531275011564.png)

1. (Optional) You can setup sensitive information redaction based on your company policy

![](https://media.notiondesk.so/upload/689de87d03503836421649.png)

1. Click Save

2. Click Publish to star using the flow

You should be able to see a new folder called Analysis in the same S3 bucket as your Chats / Voice Recordings are stored after a conversation occurs.

### [](#access-to-s3-bucket)Access to S3 Bucket

Salted CX needs permissions to read the Analysis files from S3.

Follow [AWS documentation](https://docs.aws.amazon.com/AmazonS3/latest/userguide/example-bucket-policies.html) to provide S3 folder permissions with Salted CX account.

### [](#amazon-connect-access-url)Amazon Connect Access URL

1. Navigate to AWS Console ⏵ Access URL

2. Provide Salted CX Access URL of the instance that you integrate with Salted CX

## [](#known-issues)Known Issues

- Amazon Connect can sometimes report agent in error agent status. The time the agent is in this error status is not reported in Salted CX and it can manifest itself as a gap in agent activity.

*Tags: Integration*


---

## Customer Journey Structure

Source: https://help.salted.cx/en/articles/model-customer-journey-structure


Communication between customers and companies can be very complex. A single customer may communicate with a company over extended time periods and use variety of channels. It is very hard to represent such a complicated relationship in a rigid structure. So we try to strike a balance between easy to understand, easy to work with, easy to analyze conversation structure and covering all the complexities.

In general we strive to make the most common patterns very easy to work with and natural while rare communication patterns may not be covered entirely.

![](https://media.notiondesk.so/upload/689dde4fa2a4c517089991.png)

Customer Journey has this hierarchical structure in Salted CX:

- [Customer Journey](https://help.salted.cx/en/articles/model-customer-journey-structure#d12e0e28e71c4d0bb6b07e0ae0bb953d) is at the highest level of the structure containing all [Conversations](https://help.salted.cx/en/articles/model-customer-journey-structure#532baca81c6f443fa52373c897de1b36), [Engagements](https://help.salted.cx/en/articles/model-customer-journey-structure#283fad16f29244278bcf15dfa3ae58a4) and [Turns](https://help.salted.cx/en/articles/model-customer-journey-structure#9daf09f040f44ca48d216cfb8df65ee4) that are related to a single customer. Customer Journey never ends and new conversations can be associated with it. There is only one customer journey for one customer.

- [Conversation](https://help.salted.cx/en/articles/model-customer-journey-structure#532baca81c6f443fa52373c897de1b36) is a set of engagements (touch points) customers go through when resolving one request, topic or similar. This corresponds to different concepts in different platforms. Most commonly Conversation in Salted CX represents cases, tickets, phone calls (including transfers), email thread, etc. Deciding when a conversation ends and another conversation starts can be business dependent. Salted CX uses conservative defaults (not to link unrelated engagements) to link engagements into a single Conversation. One customer can have multiple conversations in parallel. Conversations also never end and more engagements can be added to a conversation anytime in the future.

- Engagement is an interaction between a customer and a single agent (person or bot) or a service. Salted CX tries to keep Engagements simple and “analytical-friendly”.

- Turn is a single message or talk by a participant (agent or customer) in an Engagement.

In this hierarchy, a Turn belongs to a single Engagement. An Engagement belongs to a single Conversation. A conversation belongs to a single Customer (and the customer’s journey).

The table below compares the key features of the key objects in the customer journey.

|  | Customer Journey | Conversation | Engagement | Turn |
|---|---|---|---|---|
| Names on Different Platforms | Journey, Timeline, Customer History, Contact History | Interaction, Contact, Call | Interaction, Conversation, Call, Touch, Contact, Segment, Leg | Message |
| High-Level Description | Every experience of one of your customer including notes and internal communication related to that customer. | Communication with a single customer related to a “single topic”. The topic is not determined based on content but based on information from the communication platforms that enable to link walkthrough of the customer into a single one. Exact method depends on the platform but common method to link the conversation together can be case number, ticket number, email thread and similar links. | Contribution of a single agent or a service to a conversation. Whenever agent “talk” to a different agent, or goes through an automated experience (IVR, bot, self-service, etc.) a new engagement is created to represent the agent or the automated service. | A single action or event that happens during an engagement. |
| Technical Description | A container that contains all engagements related to a single customer (physical person). | A container that contains all engagements related to the conversation. | Single item in engagement data set. | Single item in turn data set. |
| Data Level Description | Customers are stored in Customers data set. They | Conversations do not have a dedicated data set in the [Logical Model](https://help.salted.cx/en/collections/1755206106-logical-model). Conversation is only identified by an attribute in Engagement data set. The ID of the conversation is an UUID that can be used to segment data. The conversation does not have its attributes. It relies on attributes of the contained engagements. | Engagement is a primary unit for reporting. Engagement is good for reporting as it can be uniquely attributed to specific attributes. | Turns data set is not exposed in reporting. You cannot build metrics on top of it. |
| Reporting Recommendation | The lifecycle of the customer can be very complex with many attributes changing over time. You can use aggregate reports metrics to calculate overall statistics segmented by attributes in the customer data set. Segmenting by other attributes requires special attention. | Conversation can range from a very simple containing just one engagement to very complex with multiple engagements. This engagements can have very different values in individual attributes (queues in which the agent waited, agents who handled them, outcome, etc.). The different values in attributes among engagements require special attention when reporting. | Engagement is a default reporting unit for most metrics. They are easy to attribute to individual attributes as each engagement has only one value for each attribute. | Reporting on turns is not currently available in Salted CX reporting. Turns are visible when you drill to a customer journey. |
| Examples | Entire customer experience including physical visits, important actions in the web, in an app and any conversation between the company and the customer. | Inbound phone call including all of its transfers. Entire email thread between a customer and a company Live chat session transferred that was escalated to a phone call. | Agent responding to a transfer from another agent. Customer walk through an IVR. | Message send via a chat. Piece of talk in a phone call. |
| When does it start | When a customer first time contacts you in any way or you contact the customer. | When you customer reaches to your company regarding with a request or you reach to the customer. | When an agent (or a service) becomes busy by handling the customer. | When the event happens. |
| When does it end | Never. The customer journey does not have a set end. | Never. Conversation can be appended by additional engagements at any time. | As soon as agent is no longer busy with handling the customer. | Very soon after the start typically. |
| Data |  |  |  |  |
| Start Time Attribute | — | Conversation Start Time | Start Time | Turn Time |
| End Time Attribute | — | — | End Time | — |



## [](#customer-journey)Customer Journey

Customer journey is a complete history of communication between a single customer and the company. The journey can include different communication channels and also customer contact with other company touch points such as activity on the company web, retail visits, etc.

Customers can use multiple Contacts (email addresses, phone numbers, chat handles) to talk to the company. If we have information what contact belong to the same customer we try to link them so users can see customers crossing channels. These information might not always be available to us so the same customer may appear to be separate Customers in different channels.

## [](#conversation)Conversation

The conversation is fairly vaguely defined. It roughly corresponds to communication between one customer and the company regarding a single topic. One conversation can include customers touching multiple touch points, using different channels, talking to different agents, and combining it with self-service.

There can be multiple conversations happening in parallel with the same customer. Salted CX tries to do default minimal grouping of Engagements into Conversations based on available information such as email threads, a call with transfers, etc.

Conversation does not have any attributes of its own. It relies on the attributes of individual Engagements within the conversation.

We enable Developers to link more Engagements into the same Conversation. With this option, we enable them to draw boundaries between conversations that are specific for their business. We also delegate the responsibility to them so we do not develop complex universal heuristics to link Engagements that may or may not be related to the same Conversation.

## [](#engagement)Engagement

Engagement represents a period of time when a customer is interacting with a company touchpoint. The touchpoint can be an agent, bot, web, retail location or anything else that facilitates contact between the company and the customers.

Engagement is an “analytical-friendly” part of Conversation. What makes it analytical friendly is that a single Engagement has one value for the keep attribute that applies to the entire Engagement. This means it is easy to attribute metric values by these attributes. Also whenever these attribute changes it is a good indication that a new Engagement is created. For example when a Customer changes their communication channel, when the customer starts to talk to another agent, etc.

Engagements within a single Conversation can overlap in case the customer is engaged with multiple Agents or in multiple channels.

## [](#turn)Turn

Turn is a sub-unit of Engagement. It represents an action that a participant made during the Engagement. The meaning of turn is dependent on the type of Engagement.

These are examples of Turns:

- In Menu Engagement each Turn represents a single step in the menu.

- In Messaging Engagements each turn represents a message sent by a participant.

- In Voice Engagements each Turn represents a continuous talk by a single participant.

- In Web or Application Engagements each Turn represents a single action performed in the application.

Turn enables very granular reporting on actions and events happening during the Engagement.

See [Turn](https://help.salted.cx/en/articles/model-turn) data set for more information.

*Tags: Logical Model*


---

## Handling Live Conversation

Source: https://help.salted.cx/en/articles/live-conversations-agent


Article short description

Live Conversations is where you talk to customers. One screen holds every conversation you are handling, the full history with each customer, and the tools to reply quickly.

## [](#conversation-sidebar)Conversation Sidebar

![](https://pub-6e850a88e7c944bfb05bc715893a058d.r2.dev/Articles/Live%20Conversations/Live%20Conversations/LC1.png)

The sidebar lists the conversations available to you, grouped into sections. Each section header shows how many conversations it contains.

`<span class="fw-bold">Join Next</span>` ![:n1:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/2dff5b74-a7ac-43f0-a07e-5e1e94fe2372/n1.svg) at the top takes you straight into the conversation that has been waiting longest for an agent. `<span class="fw-bold">New Conversation</span>` ![:n2:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/728e74b0-80de-4f17-b59c-81ded5f70a04/n2.svg) sits beside it if you have permission to start outbound conversations.

Below the buttons, a capacity panel ![:n3:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/2bcc783d-6ec8-47b3-8f54-32550f6272af/n3.svg) shows how many conversations you are handling against your target, and how long the longest-waiting customer has been waiting. Use it to decide whether you have room to take on more.

Every conversation row shows its channel on the right. Voice calls are marked distinctly. A row also shows the number of participants, so you can tell whether a colleague or a bot is already involved.

When a conversation receives messages you have not seen, its row shows a badge ![:n4:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/74ed93e1-d426-44ed-99e1-3d2f7f47a733/n4.svg) with the number of new messages. The badge is color-coded by who sent them — customer, fellow agent, external agent, or bot. If Live Conversations is open in a background browser tab, the tab itself indicates when a conversation needs your attention, so you can work in other applications without checking back.

### [](#sections)Sections

Overview ![:n5:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/be02266f-3708-4926-a942-edbbbdbc004e/n5.svg) shows how loaded your colleagues are, if user hold a correct permission. Supervisors and team leaders use it to assign conversations and to see where help is needed.

My Conversations ![:n6:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/26e762d1-e1d8-4537-a209-63768908e9c3/n6.svg) holds every conversation you are currently engaged in. These are what you should focus on.

Help Needed ![:n7:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/d9453f77-a70c-4a92-9d29-027fd32df745/n7.svg) holds conversations waiting for an agent. Automation flags a conversation as needing help when it cannot answer, when it is unavailable or returns an invalid response, or when the customer asks directly to speak to a person. A colleague can also ask for help on a conversation they are already handling.

Conversations in Help Needed are ordered by [urgency](https://help.salted.cx/en/articles/1765376502-conversation-urgency), highest first, with conversations that have no urgency set at the bottom. Within the same urgency, the longest-waiting customer comes first. You can filter the section by channel — to focus on chats or emails separately — and by the participants currently in the conversation, to separate escalations from a bot from escalations from a colleague.

![](https://pub-6e850a88e7c944bfb05bc715893a058d.r2.dev/Articles/Live%20Conversations/Live%20Conversations/LiveConversation1b.png)

Recently Left ![:n8:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/3663b717-0ca0-4700-81aa-f4f8966a4535/n8.svg) holds conversations you recently participated in but no longer do. Use it to return to a conversation you left by accident or too early.

All In Progress ![:n9:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/510ce12d-cf90-407e-9a17-bd23e52f559f/n9.svg) appears if you have a permission and it shows every conversation currently running, including AI-led conversations with no human agent engaged. It can also be filtered by participant.

---

## [](#joining-a-conversation)Joining a conversation

Before you join, Live Conversations only show customer name and channel rather than its contents. This is deliberate: it stops agents from picking the easy conversations and leaving the hard ones. Click `<span class="fw-bold">Join Next</span>` or the `<span class="fw-bold">Join</span>` button that appears after you hover on a conversation to join the conversation.

Joining creates an engagement, lets you communicate with the customer, and makes your participation visible in reporting.

Two exceptions:

- Users with supervise permission can open an in-progress conversation and read it without joining, so they can monitor the operation. Viewing does not create an engagement.

- If you are already at your maximum number of concurrent conversations, joining is paused until you resolve or leave one.

A supervisor or team leader can also assign a conversation to you directly from Overview.

---

## [](#reading-the-conversation)Reading the conversation

![](https://pub-6e850a88e7c944bfb05bc715893a058d.r2.dev/Articles/Live%20Conversations/Live%20Conversations/LC2.png)

### [](#header)Header

The header shows the customer's name ![:n1:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/2dff5b74-a7ac-43f0-a07e-5e1e94fe2372/n1.svg) from the Salted CX [customer profile](https://help.salted.cx/en/articles/customer-profile) if it is known.

Language selector ![:n2:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/728e74b0-80de-4f17-b59c-81ded5f70a04/n2.svg) shows the conversation's current language. The conversation language drives translation — the customer's messages are translated for you and your replies are translated for them, along with any questions and answers you send.

Status badge ![:n3:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/2bcc783d-6ec8-47b3-8f54-32550f6272af/n3.svg) beside the language shows whether the customer is currently active in Universal Chat. In the example it reads ‘Live’ with a cursor icon, meaning they have the chat open in front of them right now. If it reads ‘Away’, customer is not engaged with the chat currently or has it minimized on the page. ‘Left’ means the have closed the page or disconnected. This matters for pacing — a live customer is sitting with the conversation open and will notice every second of delay. Click the badge to see the page on your site the customer last interacted with.

Journey icon ![:n4:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/74ed93e1-d426-44ed-99e1-3d2f7f47a733/n4.svg) opens the [customer journey](https://help.salted.cx/en/collections/1755250527-customer-journey) for this customer. It shows every prior conversation across every channel and platform, including conversations that happened before you used Live Conversations. Open it when the customer refers to something that happened earlier, when you suspect a repeat contact, or when the current conversation makes no sense without context. You can also scroll up in the transcript itself for recent history — the journey is for going further back and across channels.

Action buttons ![:n5:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/be02266f-3708-4926-a942-edbbbdbc004e/n5.svg) on the right trigger actions in your company's systems without you leaving the conversation. The set is specific to your company. A button can for example run an action in the background, open a page in a new browser tab, copy text to your clipboard. Hover over one to see a description of what it does, if the person who configured it provided one. If there are more buttons than fit across the header, the extras collapse into a menu. Buttons are configured in Settings, see [Live Conversations Toolbar](https://help.salted.cx/en/articles/1759298233-live-conversations-toolbar).

Info button ![:n6:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/26e762d1-e1d8-4537-a209-63768908e9c3/n6.svg) at the far right opens the information available for this conversation. This is where information about the conversation lives that you and your colleagues can read and interact with. Unlike notes, which sit in the transcript and scroll away, information stays available from the header. Use it for what the next person needs to know at a glance: the state of a case, a reference number, what has already been tried or access and interact with any page that your company added there.

### [](#transcript)Transcript

Scroll up to read further back. You can see previous conversations with this customer, including ones that happened on a different channel. Live conversation messages and other content is shown the same way as in the customer journey.

Each participant has a color:

| Participant | Colour |
|---|---|
| Customer | Green |
| Human agents in your company | Blue |
| Bot agents and other automation | Purple |
| External agents invited into this conversation | Yellow |
| System messages and unknown participants | Grey |



Message content ![:n7:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/d9453f77-a70c-4a92-9d29-027fd32df745/n7.svg) sits on the left of each turn; Author ![:n8:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/3663b717-0ca0-4700-81aa-f4f8966a4535/n8.svg) of messages is shown on the right and timestamps and turn actions ![:n9:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/510ce12d-cf90-407e-9a17-bd23e52f559f/n9.svg) sit next to it, visible after hovering on the channel icon.

Timers ![:n10:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/a2056845-1131-461a-b7a1-6325c097a1cf/n10.svg) on the last message show how long it has been since its been sent. Use them to judge whether the customer is waiting on you or you are waiting on them.

Files and images the customer sends appear as attachments on the message they came with, not as separate turns.

---

## [](#composing-a-message)Composing a Message

Everything you do in a conversation happens in the composer at the bottom of the screen. It holds three things: where the message is going, what you are writing, and what you want to happen to the conversation.

![](https://pub-6e850a88e7c944bfb05bc715893a058d.r2.dev/Articles/Live%20Conversations/Live%20Conversations/LC3b.png)

### [](#where-the-message-is-going)Where the message is going

Channel picker ![:n1:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/2dff5b74-a7ac-43f0-a07e-5e1e94fe2372/n1.svg) shows the channel your reply will go out on. Open it to switch channel. If the customer started on chat but has an email address on file, you can follow up by email from the same conversation; you do not need to move to another tool or start again somewhere else.

The picker is also where you add a contact. If the customer gives you an email address or phone number during the conversation, add or link it here — Salted CX looks it up, validates it, and attaches it to the customer. Adding contacts requires permission, so the option may not be available to you.

From the channel dropdown, you might also add a note that the customer never sees. Select Internal Note for your colleagues and External Note for people outside of your organization you might want to share your conversations with. Use them to pass context between agents, or to record what you tried. Notes flow with the conversation in the transcript.

Brand indicator ![:n2:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/728e74b0-80de-4f17-b59c-81ded5f70a04/n2.svg) is the logo or name beside the picker showing which of your company's brands the customer is talking to. Accounts running several brands see a different indicator per conversation, and the customer sees the matching branding in Universal Chat. Check it before you write: tone, signature, and sometimes policy differ by brand.

### [](#writing-the-message)Writing the message

Reply field ![:n3:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/2bcc783d-6ec8-47b3-8f54-32550f6272af/n3.svg): type your message here. The field addresses the customer by name so you can see at a glance who you are writing to — useful when you have several conversations open.

Drafts are kept per conversation, so you can switch away and come back without losing what you had written.

If your message contains a variable placeholder that has not been filled in, sending is blocked until you complete it. This prevents a customer receiving a message with a raw placeholder in it.

Improve reply — write the gist of what you want to say, then type two dots `..` at the end. Salted CX uses the conversation context to expand it into a fuller reply in your organization's communication style.

![](https://pub-6e850a88e7c944bfb05bc715893a058d.r2.dev/Articles/Live%20Conversations/Live%20Conversations/LC3vidA.gif)

Typing `wait..` in a conversation might produce something like "Thank you for your patience. I'm currently reviewing your case and will assist you shortly." You always see the result before it goes anywhere and can edit it.

Attach file ![:n4:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/74ed93e1-d426-44ed-99e1-3d2f7f47a733/n4.svg), with the paperclip icon, lets you attach a file or image to your message. Attachments travel with the message rather than as a separate turn, so the customer — and your automation — see the text and the files together. On email, attachments render inline at their position in the body: images as images, other files as a download chip.

Attach question ![:n5:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/be02266f-3708-4926-a942-edbbbdbc004e/n5.svg) with the plus icon — add a predefined question with a set of answers for the customer to choose from.

1. Click the plus button.

2. Search for the question.

3. Select it.

4. Preview it, including its answers.

5. Send.

![](https://pub-6e850a88e7c944bfb05bc715893a058d.r2.dev/Articles/Live%20Conversations/Live%20Conversations/LC4.png)

The composer only offers questions that fit the current conversation — the right channel, language, brand, and queue — so you are not scrolling past ones you cannot use.

Questions are sent as written; you cannot edit them before sending. Where translation is enabled, both the question and its answers are translated automatically. On phone conversations you can send questions over SMS, and you can send them by email, where the customer answers on a dedicated page.

Automation can also generate questions during a conversation, built for the moment rather than defined in advance.

‘Working on it’ ![:n6:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/26e762d1-e1d8-4537-a209-63768908e9c3/n6.svg) sends a short message confirming that someone is attending to the issue. It goes immediately, with no compose step. Your account holds several phrasings and one is picked at random, so repeated use does not read as mechanical.

Canned replies ![:n7:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/d9453f77-a70c-4a92-9d29-027fd32df745/n7.svg) opens your account's prepared replies. Search by shortcut or by content. Replies you have marked as favorites appear first, alongside the ones you have used recently. As with questions, you only see the replies available for this conversation's channel, language, brand, and queue.

Suggested reply ![:n8:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/3663b717-0ca0-4700-81aa-f4f8966a4535/n8.svg) is where Salted CX can automatically propose a reply for the situation you are in, it appears to the right of the composer with a name. Press `<span class="fw-bold">Tab</span>` to accept it into the reply field, then edit before sending. Nothing is sent until you send it.

Send ![:n9:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/510ce12d-cf90-407e-9a17-bd23e52f559f/n9.svg) will send the message on the channel shown in the picker.

### [](#on-email-conversations)On email conversations

Email replies gain a few controls the chat composer does not have:

- A CC/BCC toggle that reveals recipient fields, each taking multiple addresses.

- Your brand's email signature, which appears in the reply and can be edited before sending. It is combined with your message on send and is included in email question replies too.

### [](#auto-greeting)Auto greeting

When you join a conversation you may be offered a prepared message telling the customer you have joined. Review it before sending, or choose not to use it. Your account can hold several phrasings, and they can include details from the conversation such as your name or the customer's.

### [](#typing-indicators)Typing indicators

You can see when the customer or a fellow agent is typing, which gives you a moment to wait rather than talking over someone. Customers cannot see when you are typing.

---

## [](#conversation-actions)Conversation actions

The row of controls above the reply field decides what happens to the conversation. They sit in the composer because the decision usually comes with the message — you answer, then say whether you are done, waiting, or handing on.

Schedule return to Help Needed ![:n10:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/a2056845-1131-461a-b7a1-6325c097a1cf/n10.svg) parks the conversation and schedules it to come back to the Needs Help queue at a time you choose, up to ten days out. You can aim it at a specific agent and attach an internal note. Use it when nothing can happen until a date — a delivery window, a refund clearing, a callback the customer asked for.

Invite ![:n11:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/7142d30f-95c6-462b-ac3b-69b9105a1b83/n11.svg) a specific person into the conversation. The invitation appears in that agent's sidebar with Join and Decline. If they do not accept in time, it moves to Help Needed where anyone can pick it up. Use it when you know who can help; use Help Needed when you do not.

Help Needed ![:n12:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/92ccd061-3637-4173-a013-68a708ed32e8/n12.svg) puts the conversation into your colleagues' Help Needed queue. The customer does not see this. You stay in the conversation and can keep replying, and any number of colleagues can join.

Leave ![:n13:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/e077e08e-ef08-46a0-a9b3-42a0a3c3451f/n13.svg) leaves the conversation without claiming the request was resolved. Choose the reason from the dropdown honestly — it appears in reporting.

Wait for customer ![:n14:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/706f0da1-e4e8-47c3-9ef8-4b499af17006/n14.svg) marks the conversation as waiting on the customer rather than on you. It becomes less prominent, and the waiting time is reported separately — your account can exclude it from engagement and handling time. Use it when you have answered and the next move is theirs.

Resolve ![:n15:](https://s3-us-west-2.amazonaws.com/public.notion-static.com/69e33586-c095-4651-83b2-02e6b6587ab4/n15.svg) states that you have resolved the request. It does not close the conversation: Salted CX may ask the customer to confirm and collect their feedback. The conversation moves to Recently Left, and returns to Help Needed if the customer writes back.

Supervisors viewing a conversation without joining can flag it as needing help using the Request Help button beside Join, without taking it on themselves.

### [](#sharing-a-specific-moment)Sharing a specific moment

Hover over any turn and open its More menu. The first action copies a link that opens the conversation scrolled to that exact turn and highlights it — the fastest way to point a colleague at the moment that matters when you escalate. The second copies the turn's text, so you can reuse it in notes or another system. Masked personal information is copied as readable labels rather than raw tokens, so nothing sensitive leaks.

### [](#leaving-several-conversations-at-once)Leaving several conversations at once

Click the number of live conversations in the navigation and choose a reason to leave all of them. Use this at the end of a shift or before a break, so customers are handed on rather than left waiting.

*Tags: Live Conversations*


---

## How AI and human agents work together in Salted

Source: https://help.salted.cx/en/articles/how-ai-and-human-agents-work-together-in-salted


Understand guidance, approval, takeover, external expertise, and return-to-AI patterns inside a Salted customer conversation.

Salted lets AI agents, human agents, and external experts contribute to the same customer conversation without treating every human intervention as a permanent handoff.

The appropriate pattern depends on customer preference, confidence, policy, risk, available expertise, and the action being performed. Automation logic controls what happens next. It can combine rules, AI, workflows, and connected systems, then tell Salted which actions to perform. In Salted configuration and technical documentation, this automation logic is called Your Logic.

## [](#collaboration-patterns)Collaboration patterns

### [](#ai-led-conversation)AI-led conversation

An AI agent can answer questions, collect information, use connected systems, perform permitted actions, and complete eligible work. The workflow should still provide a recovery path when the request cannot be completed safely or correctly.

### [](#human-monitoring-and-proactive-takeover)Human monitoring and proactive takeover

Authorized supervisors can monitor ongoing AI-led conversations through Live Conversations without waiting for automation to request help. They can inspect the active transcript, participants, alerts, routing, and available context without joining. When intervention is needed, they can join the conversation, take over customer communication, assign another human agent, or contribute only the judgment required by the workflow.

Monitoring and participation are different states. Viewing an active conversation does not create a human engagement. Joining does, and enables the person to communicate with the customer. The workflow determines whether AI pauses, remains silent, assists the person, or resumes after the human leaves.

### [](#bounded-human-guidance-or-approval)Bounded human guidance or approval

AI can ask a human agent for a structured decision without requiring the human to take ownership of the whole conversation. The customer does not need to see an internal approval question. After the human responds, the workflow can communicate or execute the result and release the human from the interaction.

This pattern is useful when a request is automatable but one decision requires judgment, permission, or accountability.

### [](#human-joins-or-takes-over)Human joins or takes over

A human agent can join or own the interaction when the issue requires empathy, investigation, negotiation, exception handling, or an unstructured decision. Agent Desktop preserves the transcript and available customer context so the human does not receive a cold transfer.

### [](#external-expertise)External expertise

A partner or specialist outside the normal Salted user population can be invited into a selected conversation. This can bring the person closest to the problem into the workflow without routing every exception through a general support team.

### [](#return-to-ai)Return to AI

Human involvement can end without ending the AI workflow. When the configured logic knows how to proceed, AI can continue after the human contribution. This is different from a conventional one-way escalation where the bot permanently disappears.

## [](#guidance-is-not-the-same-as-handoff)Guidance is not the same as handoff

Use guidance or approval when the human is needed for a bounded decision and AI can continue the process.

Use handoff or takeover when a person should own the next part of the customer interaction.

Use external expertise when another organization or specialist is best placed to resolve the issue.

The workflow may move through more than one of these states during a single conversation.

## [](#example-workflow)Example workflow

A customer requests a consequential account action:

1. AI identifies the request and gathers the required information.

2. Automation logic checks the relevant policy and connected account data.

3. The action falls inside a range that requires human judgment.

4. Salted presents an agent-facing approval question with the relevant context.

5. The human approves, changes, or rejects the proposed action.

6. The human contribution ends.

7. AI communicates or executes the result and continues the conversation.

8. The completed interaction remains available for quality review, coaching, and analysis.

The actual policy must be enforced through deterministic controls and connected systems. A prompt alone should not be treated as a hard operational boundary.

## [](#context-available-to-the-human)Context available to the human

Depending on account setup and the configured automation logic, Agent Desktop can show:

- the active transcript and available customer context,

- prior customer-journey information,

- suggested or prefilled replies,

- internal notes,

- information panels and links,

- standard and custom actions,

- routing, priority, reason, and outcome information,

- invitations to other agents or external experts.

## [](#operational-controls)Operational controls

A production workflow should define:

- which actions AI may perform independently,

- which decisions require a person,

- how the correct agent or specialist is selected,

- what happens when an invitation times out,

- what the customer is told while waiting,

- when AI should remain silent during human ownership,

- when and how control can return to AI,

- how the final result is classified and evaluated.

## [](#related-concept-guides)Related concept guides

- See [What is Agent Desktop?](https://help.salted.cx/en/articles/what-is-agent-desktop) for the human workspace inside Live Conversations.

- See [Customer conversation lifecycle in Salted](/3a25d3a2a8dc818dbbb1cd7688d35b1b) for the end-to-end customer conversation lifecycle.

- See [How automation logic controls a customer conversation](https://help.salted.cx/en/articles/how-automation-logic-controls-a-customer-conversation) for the event, decision, and action model behind Your Logic.

## [](#technical-implementation)Technical implementation

This article explains the operating model. It does not replace the technical guides. Configuration, API, and SDK documentation use the exact Salted labels and contracts.

- For conversation lifecycle behavior, see [Live Conversation Lifecycle](https://help.salted.cx/en/articles/1756766407-live-conversation-lifecycle).

- For implementation guidance, see [Your Logic Implementation Tips](https://help.salted.cx/en/articles/your-logic-implementation-tips).

- For response patterns, see [Your Logic Response Examples](https://help.salted.cx/en/articles/your-logic-response-examples).

- For agent-facing questions, see [Agent Facing Questions](/2d25d3a2a8dc806fa4e4f15766c30af1).

- For dynamic Agent Desktop controls, see [Dynamic Agent Desktop](https://help.salted.cx/en/articles/1781867273-dynamic-agent-desktop).

## [](#availability)Availability

The collaboration primitives available in a specific deployment depend on account configuration, channel, integration, and current product maturity. Confirm the required permissions, actions, events, and channel behavior in the linked technical documentation before production rollout.

*Tags: Live Conversations, Your Logic*


---

## How automation logic controls a customer conversation

Source: https://help.salted.cx/en/articles/how-automation-logic-controls-a-customer-conversation


Learn how automation logic receives conversation events, decides what should happen next, and returns actions for Salted to perform. In configuration and technical documentation, this is called Your Logic.

Automation logic decides what should happen next in a customer conversation. It can combine deterministic rules, AI, workflows, conversation state, and connected systems, then tell Salted which supported actions to perform.

In Salted configuration, integration, API, and SDK documentation, this automation logic is called Your Logic. The technical name describes the configured interface; it is not a separate product or a required visual workflow builder.

## [](#the-event-decision-action-loop)The event, decision, action loop

A typical turn follows this sequence:

1. A customer, human agent, AI agent, external participant, channel, or connected integration changes the conversation.

2. Salted creates a conversation event with the relevant trigger and context.

3. Salted sends the event to the configured automation implementation in the order it occurred for that conversation.

4. The automation logic evaluates the event using rules, AI, state, knowledge, customer data, and connected systems.

5. It returns one or more supported actions.

6. Salted performs those actions and updates the conversation.

The loop repeats as the customer and other participants continue the interaction.

## [](#what-automation-logic-can-decide)What automation logic can decide

Depending on the implementation and supported action contract, automation logic can decide:

- what to tell or ask the customer,

- whether to use a menu, free text, or another supported interaction,

- which customer or case information to retrieve,

- which permitted business action to perform,

- whether a human decision is required,

- whether to request help from a human agent,

- whether to invite an external expert,

- how to classify and route the conversation,

- what information, suggested reply, or actions to show in Agent Desktop,

- whether to remain silent while a human owns the interaction,

- whether AI can continue after the human contribution ends,

- when the conversation should be completed.

A production implementation should make these decisions according to explicit policy, permissions, and system state. Prompts can guide behavior, but hard operational boundaries should be enforced by deterministic controls where appropriate.

## [](#events-provide-the-context)Events provide the context

Conversation events describe what happened in or around the interaction. Depending on the contract and channel, events can represent customer messages or answers, participant actions, lifecycle changes, completed engagements, external callbacks, reviews, and other supported triggers.

Salted includes conversation context with the event so the implementation can reason about the current interaction. The exact payload, fields, and trigger names are defined in the Your Logic Events technical reference and must not be paraphrased in implementation code.

## [](#actions-tell-salted-what-to-do)Actions tell Salted what to do

Actions are the instructions returned to Salted. Depending on the current contract, they can cover customer messages and questions, internal notes, help requests, participant invitations, conversation updates, customer updates, files, channel-specific communication, engagement control, completion, and other supported operations.

Actions can also affect the human workspace. For example, automation logic can provide a suggested reply, show information, change the availability of actions, or update routing and disposition data.

## [](#human-oversight-and-takeover)Human oversight and takeover

Authorized supervisors can monitor ongoing AI-led conversations in Live Conversations without first joining them. They can inspect the transcript, participants, alerts, routing, and available context. When intervention is needed, they can join or assign a human agent, take over customer communication, or contribute a bounded decision.

Automation logic should define what happens when a human joins:

- whether AI pauses or remains silent,

- whether it continues to provide assistance,

- how ownership and routing change,

- what happens when the human leaves,

- whether AI can resume the workflow.

Monitoring and joining are different operational states. Viewing does not create a human-agent engagement; joining does.

## [](#conversation-state-and-ordering)Conversation state and ordering

Salted sequences events within an individual conversation so the configured automation can process them in order. An implementation can also maintain its own business state or store supported custom conversation data for use in later turns.

Different conversations from the same customer can still happen at the same time. The implementation must therefore handle concurrency safely when it reads or changes customer-level data in external systems.

## [](#failure-and-fallback-behavior)Failure and fallback behavior

A production implementation should define:

- response deadlines and timeout handling,

- what Salted should do when the automation is unavailable or returns an invalid response,

- which requests should fall back to a human,

- what the customer should be told while waiting,

- how retried or asynchronous work is correlated with the original conversation,

- which operations must be idempotent or protected against duplicate execution.

Use the current technical guides for exact timeout, authentication, sequencing, and fallback behavior.

## [](#ways-to-implement-the-automation)Ways to implement the automation

The automation logic can be implemented through:

- a custom webhook service,

- the Conversations SDK,

- custom code in a supported runtime,

- a workflow or orchestration tool,

- AI agents and tool-calling logic,

- a combination of deterministic and generative components.

These are implementation mechanisms. In the Salted technical contract, the configured automation interface is called Your Logic.

## [](#technical-documentation)Technical documentation

- For exact incoming events, see [Your Logic Events](https://help.salted.cx/en/articles/your-logic-requests).

- For exact outgoing actions, see [Your Logic Actions](https://help.salted.cx/en/articles/your-logic-actions).

- For the integration model, see [Your Logic Integration Guide](/25a5d3a2a8dc807793e1f0a47a33da10).

- For practical implementation guidance, see [Your Logic Implementation Tips](https://help.salted.cx/en/articles/your-logic-implementation-tips).

- For example response patterns, see [Your Logic Response Examples](https://help.salted.cx/en/articles/your-logic-response-examples).

- For the SDK overview, see [Conversations SDK](/2af5d3a2a8dc80f0a332f9549fc39c79).

## [](#availability)Availability

The actions, events, SDK features, channels, and integration patterns available to a specific deployment depend on the current production contract and account configuration. Treat examples and private-library primitives as evidence of possible implementation patterns, not automatic general availability.

*Tags: Live Conversations, Your Logic*


---

## In-App Announcements

Source: https://help.salted.cx/en/articles/1755215154-in-app-announcements


In-app announcements enable us to inform all or selected customers about important changes and eventual incidents affecting our services. In-app announcements are primary communication channels in case of an incident.

In-app announcements are designed to be extremely reliable and independent of our other services. Even when the rest of our services are experiencing issues in-app announcements should keep the communication channel open to our customers. This makes it possible to keep all users informed directly in our application about whatever is happening so they do not have to search for details anywhere else.

## [](#downloading-announcements)Downloading Announcements

You can download announcements directly via HTTPS in case even the Salted CX application user interface is not available. The status files are available at the following locations:

- `https://status.salted.cx/announcements.json` — Global announcements that apply to all customers.

- `https://status.salted.cx/[region]/announcements.json` — Region-specific announcements that apply to all accounts in the given region.

- `https://status.salted.cx/[region]/[account domain]/announcements.json` — Contains announcements for a specific account.

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

We do not disclose any sensitive information in the announcements to enable these announcements to be accessible with a minimum number of services involved to maximize the service availability and reliability.





If you want to retrieve the current status of your account and you have the domain `company.eu.salted.cx` in Salted CX you need to download the following files:

- `https://status.salted.cx/announcements.json`

- `https://status.salted.cx/eu/announcements.json`

- `https://status.salted.cx/eu/company/announcements.json`

## [](#announcement-format)Announcement Format

Each announcement is a JSON file with an array of individual announcements. The following code snippet shows an example announcement file.

```json
[
	{
		"message": "This is an example announcement with all supported properties",
		"details": "This explains the announcement in greater detail.",
		"link": "https://help.salted.cx",
		"color": "blue",
		"fromTime": "2024-05-31T00:00:00Z",
		"toTime": "2024-05-31T03:00:00Z",
		"dismiss": true,
		"type": "fullscreen"
	},
	{
		"message": "Only the message of the announcement is mandatory.",
	}
]
```

The following properties are supported:

- `message` is a free text that is shown to a users

- `details` (optional) is a free text with more details about the announcement

- `link` (optional) to more information outside of the application

- `color` (optional, default `blue`) of the announcement in the user interface, possible values `red`, `yellow`, `green`, `blue` and `grey`

- `fromTime` (optional) is time from which the announcement is shown `fromTime`

- `toTime` (optional) is time until when the announcement is shown `toTime`

- `dismiss` (optional, default `true`) tells whether the announcement can be dismissed by users, possible values are `true` and `false`

- `type` (optional, default `notification`) tells how the announcement is visualized, possible values are `notification` (shows as a notification bar in the application) and `fullscreen` (overlay over the entire application)

## [](#request-incident-report)Request Incident Report

The incident report provides detailed information about the timeline of an incident

You can request a detailed incident report that affected your account by contacting us at <info@salted.cx>. You have to request the incident report from your work email address associated with your account.

---

## Metrics Reference

Source: https://help.salted.cx/en/articles/1755225286-metrics-reference


# [](#active-agents)Active Agents

Number of agents that are currently active in all the connected platforms. Active agent is an agent that exists in the platforms and is not deleted. It does not imply the agent is available to engage with customers.

```sql
SELECT COUNT(Agent) 
  WHERE Agent ⏵ State IN ("Active")
```

public\_active\_agents# [](#agent-conversations)Agent Conversations

Number of conversations in which agent was engaged. If an agent starts multiple engagements in a single conversation in the given time frame it is still counted as 1, unlike number of engagements.

```sql
SELECT COUNT(Engagement ⏵ Conversation) 
  WHERE Engagement ⏵ Type IN ("Agent")
```

public\_agent\_conversations# [](#agent-conversations-per-customer)Agent Conversations per Customer

The average number of conversation per one customer.

```sql
SELECT AVG(
  SELECT Agent Conversations 
    BY Customer)
```

public\_agent\_conversations\_per\_customer# [](#agent-engagements)Agent Engagements

Total number of agent engagements. This includes agent engagements that are associated with the agent including engagements that are in progress or marked as corrupted.

```sql
SELECT COUNT(Engagement) 
  WHERE Engagement ⏵ Type = "Agent"
```

public\_agent\_engagements# [](#agent-engagements-ignored-in-sla)Agent Engagements Ignored in SLA

Number of agent engagements that are not included in service level calculation.

```sql
SELECT Agent Engagements
  WHERE Engagement ⏵ Service Level IN ("Ignore")
```

public\_agent\_engagements\_ignored\_in\_sla# [](#agent-engagements-tagged-as-reviewed)Agent Engagements Tagged as Reviewed

Number of engagements that have at least one tag "Reviewed".

```sql
SELECT COUNT(Engagement)
  # Including only those negagement where an agent was involved
  WHERE Engagement ⏵ Type IN ("Agent")
    # Making sure that we include only completed reviews because those are there to stay
    AND Review ⏵ State IN ("Completed")
    # PID for Questions "Reviewed" that is used to tag reviewed engagements
    AND Question IN ("24bc8f9c-f340-4a41-8e77-9d364384f0ac")
  # We ignore Question level filters as this metric explicitly focused on "Reviewed" tag
  WITH PARENT FILTER EXCEPT Question
```

public\_agent\_engagements\_tagged\_as\_reviewed# [](#agent-engagements-tagged-as-reviewed)Agent Engagements Tagged as Reviewed %

Percentage of enagegemtns that are reviewed out of all agent engagements.

```sql
SELECT Agent Engagements Tagged as Reviewed
  / Agent Engagements
```

public\_agent\_engagements\_tagged\_as\_reviewed\_percentage# [](#agent-engagements-for-sla)Agent Engagements for SLA

The number of agent engagements that is used for the total number of engagements included in the calculation.

```sql
SELECT Agent Engagements
  WHERE Engagement ⏵ State IN ("closed", "solved", "Completed")
    AND Engagement ⏵ Service Level NOT IN (NULL , "Ignore")
```

public\_agent\_engagements\_for\_sla# [](#agent-engagements-in-progress)Agent Engagements in Progress

The number of agent engagements that are in progress. An agent started working on them but they were not marked as completed.

```sql
SELECT Agent Engagements 
  # The condition to include only engagements in progress
  WHERE Engagement ⏵ State IN ("In Progress")
```

public\_agent\_engagements\_in\_progress# [](#agent-engagements-on-hold)Agent Engagements on Hold

The number of agent engagements that are on hold. An agent started working on them but were not finished. In the same time they were marked as on hold meaning the agent is not spending time with them.

```sql
SELECT Agent Engagements 
  # The condition to include only engagements on hold
  WHERE Engagement ⏵ State IN ("On Hold")
```

public\_agent\_engagements\_on\_hold# [](#agent-engagements-out-of-sla)Agent Engagements out of SLA

Number of agent engagements that not match requirements for service level.

```sql
SELECT Agent Engagements
  # Condition to include only engagements out of SLA from the source platform
  WHERE Engagement ⏵ Service Level IN ("Out of SLA")
```

public\_agent\_engagements\_out\_of\_sla# [](#agent-engagements-per-agent)Agent Engagements per Agent

Total number of engagements per agent.

```sql
SELECT AVG(
  SELECT Agent Engagements 
    BY Agent)
```

public\_agent\_engagements\_per\_agent# [](#agent-engagements-per-agent-day)Agent Engagements per Agent, Day

Shows average number of agent engagements per agent per day based on the time when the engagement started. This can be used to show average agent performance when comparing teams or just having an overall performance trend for the entire contact center. Includes only instances in the average when the agent had at least one engagement that day.

```sql
SELECT AVG(
  SELECT Agent Engagements 
    # group the count by both start time and the agent
    # the average then averages nuumber of engagements in those segments
    BY Start Time ⏵ day, Agent)
```

public\_agent\_engagements\_per\_agent\_day# [](#agent-engagements-per-agent-hour)Agent Engagements per Agent, Hour

Shows average number of agent engagements per agent per hour based on the time when the engagement started. This can be used to show average agent performance when comparing teams or just having an overall performance trend for the entire contact center. Includes only instances in the average when the agent had at least one engagement that hour.

```sql
SELECT AVG(
  SELECT Agent Engagements 
    BY Start Time ⏵ hour, Agent)
```

public\_agent\_engagements\_per\_agent\_hour# [](#agent-engagements-per-available-hour)Agent Engagements per Available Hour

Number of enagegement per hour that agent is in any available activity.

```sql
SELECT Agent Engagements
  / (Total Available Time / 3600)
```

public\_agent\_engagements\_per\_available\_hour# [](#agent-engagements-per-case)Agent Engagements per Case

Average number of agent engagements per single case.

```sql
SELECT AVG(SELECT Agent Engagements 
  BY Engagement ⏵ Case)
```

public\_agent\_engagements\_per\_case# [](#agent-engagements-per-conversation)Agent Engagements per Conversation

Average number of agent engagements per single conversations.

```sql
SELECT AVG(
  SELECT COUNT(Engagement) 
    BY Engagement ⏵ Conversation
    WHERE Engagement ⏵ Type = "Agent")
```

public\_agent\_engagements\_per\_conversation# [](#agent-engagements-per-customer)Agent Engagements per Customer

The average number of agent engagements per single customer.

```sql
SELECT AVG(
  SELECT Agent Engagements 
    BY Customer)
```

public\_agent\_engagements\_per\_customer# [](#agent-engagements-per-hour-of-day)Agent Engagements per Hour of Day

Average agent engagements happening every hour.

```sql
SELECT AVG(SELECT Agent Engagements 
  BY Start Time ⏵ hourOfDay)
```

public\_agent\_engagements\_per\_hour\_of\_day# [](#agent-engagements-with-agent-review)Agent Engagements with Agent Review

Number of agent engagements that have at least one given a

```sql
SELECT COUNT(Engagement, Review)
  WHERE Engagement ⏵ Type IN ("Agent") 
    AND Review ⏵ Type IN ("Agent")
    AND Review ⏵ State IN ("Completed")
```

public\_agent\_engagements\_with\_agent\_review# [](#agent-engagements-with-agent-review)Agent Engagements with Agent Review %

The percentage of agent engagements that have at least one review from the agent out of all completed agent engagements.

```sql
SELECT Agent Engagements with Agent Review /
 Completed Agent Engagements
```

public\_agent\_engagements\_with\_agent\_score\_percentage# [](#agent-engagements-with-auto-review)Agent Engagements with Auto Review

Number of completed agent engagements that have at least one automatic review.

```sql
SELECT COUNT(Engagement, Review)
  WHERE Engagement ⏵ Type IN ("Agent") 
    AND Engagement ⏵ State IN ("Completed")
    AND Review ⏵ Type IN ("Auto")
    AND Review ⏵ State IN ("Completed")
```

public\_agent\_engagements\_with\_auto\_review# [](#agent-engagements-with-auto-review)Agent Engagements with Auto Review %

Percentage of engagements that have at least one completed auto review out of all completed engagements.

```sql
SELECT Agent Engagements with Auto Review 
  / Completed Agent Engagements
```

public\_agent\_engagements\_with\_auto\_review\_percentage# [](#agent-engagements-with-customer-review)Agent Engagements with Customer Review

Number of completed agent engagements that have at least one review from the customer.

```sql
# Count engagements and make sure multiple reviews of the engagement only count as one
SELECT COUNT(Engagement, Review)
  # Only in agent engagements, if there was just waiting in the queue or similar experience, we do not care
  WHERE Engagement ⏵ Type IN ("Agent") 
    # Include only completed engagements as in progress may still have chnages in the future
    AND Engagement ⏵ State IN ("Completed")
    # Include only reviews from customers
    AND Review ⏵ Type IN ("Customer")
    # Include only completed, so if there is just a request for review and customer has not (yet) responded it does not count
    AND Review ⏵ State IN ("Completed")
```

public\_agent\_engagements\_with\_customer\_review# [](#agent-engagements-with-customer-review)Agent Engagements with Customer Review %

Percentage of engagements with at least one review from customers out of total completed engagements.

```sql
# Take all metric engagements that have at least on completed customer review
SELECT Agent Engagements with Customer Review 
  # Divide it by all completed agent engagements to get percentage
  /Completed Agent Engagements
```

public\_agent\_engagements\_with\_customer\_review\_percentage# [](#agent-engagements-with-review)Agent Engagements with Review

Number of agent engagements that have a any completed review.

```sql
# Count engagements and make sure multiple reviews of the engagement only count as one
SELECT COUNT(Engagement, Review)
  # Only in agent engagements, if there was just waiting in the queue or similar experience, we do not care
  WHERE Engagement ⏵ Type IN ("Agent") 
    # Include only completed engagements as in progress may still have chnages in the future
    AND Engagement ⏵ State IN ("Completed")
    # Include only completed, so if there is just a request for review and customer has not (yet) responded it does not count
    AND Review ⏵ State IN ("Completed")
```

public\_agent\_engagements\_with\_review# [](#agent-engagements-with-review)Agent Engagements with Review %

```sql
SELECT Agent Engagements with Review /
 Completed Agent Engagements
```

public\_agent\_engagements\_with\_review\_percentage# [](#agent-engagements-with-review-score)Agent Engagements with Review Score

The number of engagements with at least one completed review from a reviewer.

```sql
SELECT COUNT(Engagement, Review)
  WHERE Engagement ⏵ Type IN ("Agent") 
    AND Review ⏵ Type IN ("Reviewer")
    AND Review ⏵ State IN ("Completed")
```

public\_agent\_engagements\_with\_review\_score# [](#agent-engagements-with-reviewer-score)Agent Engagements with Reviewer Score %

```sql
SELECT Agent Engagements with Review Score /
 Completed Agent Engagements
```

public\_agent\_engagements\_with\_reviewer\_score\_percentage# [](#agent-engagements-within-sla)Agent Engagements within SLA

Number of comleted agent engagements that were handled within the service level.

```sql
SELECT Agent Engagements
  WHERE Engagement ⏵ State IN ("Completed", "closed", "solved")
    AND Engagement ⏵ Service Level IN ("Within SLA")
```

public\_agent\_engagements\_within\_sla# [](#agent-score)Agent Score

The score of a review provided by the agent engaged in the reviewed engagement.

```sql
SELECT Review ⏵ Score
  WHERE Review ⏵ Type = "Agent"
```

public\_agent\_score# [](#agent-service-level)Agent Service Level

Service level (SLA) for agent engagements. Percentage of engagements within service level out of all engagements that should be included in the calculation.

```sql
SELECT Agent Engagements within SLA /
  Agent Engagements for SLA
```

public\_agent\_service\_level# [](#agents-with-engagement)Agents with Engagement

Number of agents that had any engagement. Depending on use of start time or end time this metric shows how many agents started resp. concluded their engagements.

```sql
SELECT COUNT(Agent, Engagement) 
  WHERE Engagement ⏵ Type = "Agent"
```

public\_agents\_with\_engagement# [](#auto-score)Auto Score

Review score that was provided by an automated service or tool such as ML/AI model.

```sql
SELECT Review ⏵ Score
  WHERE Review ⏵ Type IN ("Auto")
```

public\_auto\_score# [](#available-time)Available Time %

The percentage of available time out of total.

```sql
SELECT Total Available Time
  / Total Activity Time
```

public\_available\_time\_ratio# [](#average-agent-score)Average Agent Score

Average score from reviews that agents provided for their engagements.

```sql
SELECT AVG(Agent Score)
```

public\_average\_agent\_score# [](#average-auto-score)Average Auto Score

The average score received by automatic reviews.

```sql
SELECT AVG(Auto Score)
```

public\_average\_auto\_score# [](#average-capped-conformance-per-agent-day)Average Capped Conformance per Agent, Day

Conformance averaged per agent per day.

```sql
# Average of conformance that gives an idea of individual performance on agent and daily basis
SELECT AVG(
  # Capped conformance that cannot go over 100%
  SELECT Conformance Capped to Scheduled Time 
    # Average by agent by date, so weekly conformance would calculate it as average of days
    # rather than using total time in activity and scheduled time of the entire week
    BY Agent, Interval Date ⏵ day)
```

public\_average\_capped\_conformance\_per\_agent\_day# [](#average-conformance-per-agent-activity-day)Average Conformance per Agent, Activity, Day

Conformance averaged by agent activity and day.

```sql
SELECT AVG(
  SELECT Conformance
    BY Agent, 
      {label/agent_activity}, 
      Interval Date ⏵ day)
```

public\_average\_conformance\_per\_agent\_per\_month# [](#average-conformance-per-agent-day)Average Conformance per Agent, Day

Conformance averaged per agent per day.

```sql
SELECT AVG(
  SELECTConformance 
    BY Agent, Interval Date ⏵ day)
```

public\_average\_conformance\_per\_agent\_day# [](#average-conformance-per-agent-week)Average Conformance per Agent, Week

Conformance averaged per agent per week.

```sql
SELECT AVG(
  SELECTConformance 
    BY Agent,  Interval Date ⏵ week)
```

public\_average\_conformance\_per\_agent\_week# [](#average-conversation-start-to-engagement-end)Average Conversation Start to Engagement End

Average time from conversation start to engagement end rounded to minutes because date dimensions do not support second level accuracy.

```sql
SELECT AVG(Conversation Start to Engagement End)
```

public\_average\_conversation\_start\_to\_engagement\_end# [](#average-conversation-start-to-engagement-start)Average Conversation Start to Engagement Start

Average time from conversation start to engagement start rounded to minutes because date dimensions do not support second level accuracy.

```sql
SELECT AVG(Conversation Start to Engagement End)
```

public\_average\_conversation\_start\_to\_engagement\_start# [](#average-customer-score)Average Customer Score

Average review score received from all customers.

```sql
SELECT AVG(Customer Score) 
  WHERE Review ⏵ State IN ("Completed")
```

public\_average\_customer\_score# [](#average-customer-score-last-30-days)Average Customer Score - Last 30 Days

```sql
SELECT Average Customer Score 
  WHERE Start Time ⏵ day > THIS(DAY, -30)
    AND Start Time ⏵ day <= THIS(DAY)
```

public\_average\_customer\_score\_last\_30\_days# [](#average-empathy)Average Empathy

```sql
SELECT AVG(Empathy)
```

public\_average\_empathy# [](#average-engagement-time)Average Engagement Time

Average time agents spends engaged to the customer. This is from the moment when agent accepted invitation to join the conversation until the moment the agent moved to wrap up phase or completed the engagement.

```sql
SELECT AVG(Engagement ⏵ Engagement Time)
```

public\_average\_engagement\_time# [](#average-engagement-time-per-conversation)Average Engagement Time per Conversation

Average engagement time required for a single conversation. If multiple agents are engaged in the conversation at the same time this time is counted also multiple times. This metric tries to attribute time spent by all agents on the conversation.

```sql
SELECT AVG(
  SELECT Total Engagement Time 
    BY Engagement ⏵ Conversation)
```

public\_average\_engagement\_time\_per\_conversation# [](#average-engagement-time-per-customer)Average Engagement Time per Customer

Average time agents were engaged with the customer.

```sql
SELECT AVG(
  SELECT Total Engagement Time 
    BY Customer)
```

public\_average\_engagement\_time\_per\_customer# [](#average-engagement-time-without-agent)Average Engagement Time without Agent

```sql
SELECT Average Engagement Time 
  BY ALL OTHER
```

public\_average\_engagement\_time\_without\_agent# [](#average-engagement-time-without-agent-filter)Average Engagement Time without Agent Filter

```sql
SELECT Average Engagement Time 
  WITH PARENT FILTER 
  EXCEPT Agent
```

public\_average\_engagement\_time\_without\_agent\_filter# [](#average-focus-time)Average Focus Time

The average time the agent was focused on the customer. Unlike the Engagement Time this attributes time when the user had the engagement actually open in the agent desktop and does not include time when the agent was focused on something else while the engagement was not yet focused. This includes time during both engagement and wrap up phase. Most data sources do not support this level of detail.

```sql
SELECT AVG(Engagement ⏵ Focus Time)
```

public\_average\_focus\_time# [](#average-invitation-time)Average Invitation Time

The average time it takes an agent to respond to an invitation to the conversation. For rejected or missed invitation this it the time it takes an agent to reject the invitation.

```sql
SELECT AVG(Engagement ⏵ Invitation Time)
```

public\_average\_invitation\_time# [](#average-preparation-time)Average Preparation Time

Average preparation time the agent spends before engagement preparing for it.

```sql
SELECT AVG(Engagement ⏵ Preparation Time)
```

public\_average\_preparation\_time# [](#average-review-delay)Average Review Delay

```sql
SELECT AVG(Review Delay)
```

public\_average\_review\_delay# [](#average-reviewer-score)Average Reviewer Score

The average score received from a reviewer normalized to range 0 to 100%.

```sql
SELECT AVG(Reviewer Score)
```

public\_average\_reviewer\_score# [](#average-schedule-adherence-per-agent-day)Average Schedule Adherence per Agent, Day

Average schedule adherence averaged by agent and day. This metric is average of individual agent daily performance.

```sql
SELECT AVG(
  SELECT Schedule Adherence
    # Average by agent and date
    BY Agent, Interval Date ⏵ day)
```

public\_average\_schedule\_adherence\_per\_agent\_day# [](#average-scheduled-time-per-agent)Average Scheduled Time per Agent

The average scheduled time an agent is scheduled for activities.

```sql
SELECT AVG(
  SELECTTotal Scheduled Time
    BY Agent)
```

public\_average\_scheduled\_time\_per\_agent# [](#average-score)Average Score

The average score of all reviews that are completed.

```sql
SELECT AVG(Review ⏵ Score)
  WHERE Review ⏵ State IN ("Completed")
```

public\_average\_score# [](#average-wait-time)Average Wait Time

Average wait time before a customer is connected to an agent or leaves the queue.

```sql
SELECT AVG(Engagement ⏵ Wait Time)
```

public\_average\_wait\_time# [](#average-wait-time-previous-time-period)Average Wait Time 🜄 Previous Time Period

```sql
SELECT Average Wait Time
  FOR PREVIOUSPERIOD(Start Time ⏵ day)
```

public\_average\_wait\_time\_previous\_time\_period# [](#average-wrap-up-time)Average Wrap Up Time

Average time it takes agents to wrap up an engagement. This includes work such as filling information about the engagement into a CRM or create followups.

```sql
SELECT AVG(Engagement ⏵ Wrap Up Time)
```

public\_average\_wrap\_up\_time# [](#completed-agent-engagements)Completed Agent Engagements

Number of agent engagements that were completed.

```sql
SELECT COUNT(Engagement) 
  WHERE Engagement ⏵ Type IN ("Agent")
    AND Engagement ⏵ State IN ("Completed")  
```

public\_completed\_agent\_engagements# [](#completed-agent-reviews)Completed Agent Reviews

The number of reviews that the agent provided.

```sql
SELECT COUNT(Review) 
  WHERE Review ⏵ Type IN ("Agent")
    AND Review ⏵ State IN ("Completed")
```

public\_completed\_agent\_reviews# [](#completed-auto-reviews)Completed Auto Reviews

The number of reviews that customer provided by the AI.

```sql
SELECT COUNT(Review) 
  WHERE Review ⏵ Type IN ("Auto")
    AND Review ⏵ State IN ("Completed")
```

public\_completed\_auto\_reviews# [](#completed-customer-reviews)Completed Customer Reviews

The number of reviews that customer provided responses to.

```sql
SELECT COUNT(Review) 
  WHERE Review ⏵ Type IN ("Customer")
    AND Review ⏵ State IN ("Completed")
```

public\_completed\_customer\_reviews# [](#completed-queue-engagements)Completed Queue Engagements

Number of queue engagements that were completed.

```sql
SELECT Queue Engagements
  WHERE Engagement ⏵ State IN ("Completed")
```

public\_completed\_queue\_engagements# [](#completed-reviewer-reviews)Completed Reviewer Reviews

Number of completed reviews by the reviewer.

```sql
SELECT COUNT(Review) 
  WHERE Review ⏵ Type IN ("Reviewer")
    AND Review ⏵ State IN ("Completed")
```

public\_completed\_reviewer\_reviews# [](#completed-reviews)Completed Reviews

Number of reviews of all types that are completed. Results from this reviews can be used for the reporting.

```sql
SELECT COUNT(Review) 
  WHERE Review ⏵ State IN ("Completed")
```

public\_completed\_reviews# [](#conformance)Conformance

Conformance reports on total time spent in agent activities compared to scheduled time. This metric uses weighted average of individual activities thus spending more time in individual activities than scheduled time may offset for less then scheduled time spent in other activities. Note that agent by spending more time in an unproductive activity such as "break" may hide shorter activity time in a productive activities. For this reason use filters and/or segmentation by Agent Activity in insights and dashboards. You can also use metric Conformance Capped to Scheduled Time to mitigate this behavior.

```sql
# Total of all actual activity time of the agent (the time the agent actually spent in that activity)
SELECT Total Activity Time
# As this is weighted average by Scheduled Time we use its total actoss all activities as denominator
/ Total Scheduled Time
```

public\_conformance# [](#conformance-capped-to-scheduled-time)Conformance Capped to Scheduled Time

Conformance reports on total time spent in agent activities compared to scheduled time. This metric uses weighted average of individual activities but caps individual activities to their scheduled time. This prevents behavior in which spending more time than scheduled in unproductive activities such as "break" offset less time spent in productive activities.

```sql
# The actual time spent in the give activitities
SELECT SUM(
  # Choose the lower time from the total scheduled time and actual activity time
  SELECT LEAST(
      Total Scheduled Time, 
      Total Activity Time)
    # Group the individual activities to cap each individually
    BY {label/agent_activity})
# Total time scheduled actoss all activities as denominator in the weighted average
/ Total Scheduled Time
```

public\_conformance\_capped\_to\_scheduled\_time# [](#conformance-unavailable-capped-to-scheduled-time)Conformance Unavailable Capped to Scheduled Time

Conformance reports on total time spent in agent activities compared to scheduled time. This metric uses weighted average of individual activities but caps individual activities to their scheduled time. This prevents behavior in which spending more time than scheduled in unproductive activities such as "break" offset less time spent in productive activities.

```sql
# The actual time spent in the give activitities
SELECT (
  # First sum all unavailable time
  SELECT SUM(
  # Choose the lower time from the total scheduled time and actual activity time
    SELECT LEAST(
      Total Scheduled Time, 
      Total Activity Time)
      # Group the individual activities to cap each individually
      BY {label/agent_activity} 
      WHERE {label/availability} IN ("Unavailable"))
    # Then add all activity time in available activities
    + (SELECT 
        Total Activity Time 
        WHERE {label/availability} IN ("Available")))
# Total time scheduled actoss all activities as denominator in the weighted average
/ Total Scheduled Time
```

public\_conformance\_unavailable\_capped\_to\_scheduled\_time# [](#conformance-for-available-activities)Conformance for Available Activities

Conformance reports on total time spent in agent activities compared to scheduled time. This metric uses weighted average of individual activities thus spending more time in individual activities than scheduled time may offset for less then scheduled time spent in other activities. Note that agent by spending more time in an unproductive activity such as "break" may hide shorter activity time in a productive activities. For this reason use filters and/or segmentation by Agent Activity in insights and dashboards. You can also use metric Conformance Capped to Scheduled Time to mitigate this behavior.

```sql
# Total of all actual activity time of the agent (the time the agent actually spent in that activity)
SELECT Total Activity Time
  # As this is weighted average by Scheduled Time we use its total actoss all activities as denominator
  / Total Scheduled Time
  # This prevents the unavailable activities from offsetting time spent in available activities
  WHERE {label/availability} IN ("Available")

```

public\_conformance\_for\_available\_activities# [](#constant-100)Constant 100%

Convenience constant metric equal to 100%. You can use this number as a target in insights and dashboards.

```sql
SELECT 1
```

public\_constant\_100\_percent# [](#conversation-start-to-engagement-end)Conversation Start to Engagement End

The time from conversation start to engagement start.

```sql
SELECT DATETIME_DIFF(
  Conversation Start Time ⏵ minute, 
  End Time ⏵ minute)
  # Recalculate to seconds to have the same units as other metrics
    * 60;
```

public\_conversation\_start\_to\_engagement\_end# [](#conversation-start-to-engagement-start)Conversation Start to Engagement Start

The time from conversation start to engagement start.

```sql
SELECT DATETIME_DIFF(
  Conversation Start Time ⏵ minute, 
  Start Time ⏵ minute)
  # Recalculate to seconds to have the same units as other metrics
    * 60;
```

public\_conversation\_start\_to\_engagement\_start# [](#conversations)Conversations

Total number of conversations. When reporting on conversations make sure you understand that any conversation that have at least one engagement matching a filtering criteria or belonging to a given segment is counted. If you have one conversation with 2 engagements each starting at a different date the conversation will get reported in both days.

```sql
SELECT COUNT(Engagement ⏵ Conversation) 
  WHERE Engagement ⏵ Type IN ("Agent")
```

public\_conversations# [](#conversations-per-agent-per-day)Conversations per Agent per Day

Total number of conversations. When reporting on conversations make sure you understand that any conversation that have at least one engagement matching a filtering criteria or belonging to a given segment is counted. If you have one conversation with 2 engagements each starting at a different date the conversation will get reported in both days.

```sql
SELECT AVG(
  SELECT Conversations 
    BY Agent, Conversation Start Time ⏵ day)
```

public\_conversations\_per\_agent\_per\_day# [](#conversations-per-agent-per-hour)Conversations per Agent per Hour

Total number of conversations. When reporting on conversations make sure you understand that any conversation that have at least one engagement matching a filtering criteria or belonging to a given segment is counted. If you have one conversation with 2 engagements each starting at a different date the conversation will get reported in both days.

```sql
SELECT AVG(
  SELECT Conversations 
    BY Agent,  Conversation Start Time ⏵ hour)
```

public\_conversations\_per\_agent\_per\_hour# [](#conversations-with-review)Conversations with Review

Number of conversations that have a any completed review.

```sql
# Count engagements and make sure multiple reviews of the engagement only count as one
SELECT COUNT(Engagement ⏵ Conversation, Review)
  # Only in agent engagements, if there was just waiting in the queue or similar experience, we do not care
  WHERE Engagement ⏵ Type IN ("Agent") 
    # Include only completed engagements as in progress may still have chnages in the future
    AND Engagement ⏵ State IN ("Completed")
    # Include only completed, so if there is just a request for review and customer has not (yet) responded it does not count
    AND Review ⏵ State IN ("Completed")
```

public\_conversations\_with\_review# [](#conversations-with-review)Conversations with Review %

```sql
SELECT Conversations with Review /
  Conversations
```

public\_conversations\_with\_review\_percent# [](#corrupted-engagements)Corrupted Engagements

Total number of corrupted engagements. These are engagements where the original data source provided incomplete or unexpected information about the engagement and it is impossible to represent the metrics with confidence.

```sql
SELECT Engagements
  WHERE Engagement ⏵ State = "Corrupted"
```

public\_corrupted\_engagements# [](#customer-review-coverage-fix)Customer Review Coverage FIX

```sql
SELECT Completed Customer Reviews 
  / Started Conversations
```

public\_customer\_review\_coverage# [](#customer-review-response-rate)Customer Review Response Rate

The percentage of customer reviews that got a response from the customer out of total number of requested.

```sql
SELECT Completed Customer Reviews 
  / Requested Customer Reviews
```

public\_customer\_review\_response\_rate# [](#customer-score)Customer Score

The score that is received from the customer normalized to percentages in range from 0 to 100%.

```sql
SELECT Review ⏵ Score
  WHERE Review ⏵ Type = "Customer"
```

public\_customer\_score# [](#customers)Customers

The total number of customers.

```sql
SELECT COUNT(Customer)
```

public\_customers# [](#customers-left)Customers Left

Number of queue engagements in which the customer has left before being moved to another queue or an agent started to engage with them.

```sql
SELECT Queue Engagements 
  WHERE Engagement Outcome ⏵ Name IN ("Customer Left")
```

public\_customers\_left# [](#customers-left)Customers Left %

Percentage of queues in which customer left before transfer to another queue or starting to talk to agents.

```sql
SELECT Customers Left 
/ Completed Queue Engagements
```

public\_customers\_left\_percentage# [](#customers-left-previous-time-period)Customers Left % 🜄 Previous Time Period

```sql
SELECT Customers Left %
  FOR PREVIOUS(Start Time ⏵ day)
```

public\_customers\_left\_percentage\_previous\_time\_period# [](#customers-left-previous-time-period)Customers Left 🜄 Previous Time Period

```sql
SELECT Customers Left 
  FOR PREVIOUS(Start Time ⏵ day) 
```

public\_customers\_left\_previous\_time\_period# [](#deprecated-engagements-tagged-as-reviewed)DEPRECATED Engagements Tagged as Reviewed

Number of engagements that have at least one tag "Reviewed".

```sql
SELECT COUNT(Engagement)
  # Making sure that we include only completed reviews
  WHERE Review ⏵ State IN ("Completed")
    # PID for Questions "Reviewed" that is used to tag reviewed engagements
    AND Question IN ("24bc8f9c-f340-4a41-8e77-9d364384f0ac")
  # We ignore Question level filters as this metric explicitly focused on "Reviewed" tag
  WITH PARENT FILTER EXCEPT Question
```

public\_engagements\_tagged\_as\_reviewed# [](#difference-between-agent-and-review-score)Difference Between Agent and Review Score

```sql
SELECT ( Average Agent Score - 
  X Average Review Score)
  # we do not use percentage formating but percentage points so we multiply this to get from 0 to 1 range to 0 to 100 range
  * 100 
```

public\_difference\_between\_agent\_and\_review\_score# [](#difference-between-agent-and-robot-score)Difference Between Agent and Robot Score

```sql
SELECT ( Average Agent Score - 
  X Average Auto Score)
  * 100 # we do not use percentage formating but percentage points so we multiply this to get from 0 to 1 range to 0 to 100 range
```

public\_difference\_between\_agent\_and\_robot\_score# [](#difference-between-customer-and-agent-score)Difference Between Customer and Agent Score

```sql
SELECT (Average Customer Score - 
  Average Agent Score)
  * 100 # we do not use percentage formating but percentage points so we multiply this to get from 0 to 1 range to 0 to 100 range

```

public\_difference\_between\_customer\_and\_agent\_score# [](#difference-between-customer-and-review-score)Difference Between Customer and Review Score

```sql
SELECT (Average Customer Score - 
  X Average Review Score)
  * 100 # we do not use percentage formating but percentage points so we multiply this to get from 0 to 1 range to 0 to 100 range
```

public\_difference\_between\_customer\_and\_review\_score# [](#difference-between-customer-and-robot-score)Difference Between Customer and Robot Score

```sql
SELECT (Average Customer Score - 
  X Average Auto Score)
  * 100 # we do not use percentage formating but percentage points so we multiply this to get from 0 to 1 range to 0 to 100 range
```

public\_difference\_between\_customer\_and\_robot\_score# [](#difference-between-review-and-robot-score)Difference Between Review and Robot Score

```sql
SELECT (X Average Review Score - 
  X Average Auto Score)
  * 100 # we do not use percentage formating but percentage points so we multiply this to get from 0 to 1 range to 0 to 100 range
```

public\_difference\_between\_review\_and\_robot\_score# [](#empathy)Empathy

The difference between agent and customer score associated with an engagement. The lower the value the larger difference between how agents perceive themselves and how customers perceive them.

```sql
SELECT 1 - ABS(
  SELECT Average Customer Score 
    - Average Agent Score 
    BY Engagement)
```

public\_empathy# [](#engagements)Engagements

Raw count of engagements. This metrics should be used for technical purposes mostly or just a building block as it does not exclude any engagements even those that are corrupted, technical and similar. It is very unlikely to see those in a single report with the rest unless for technical reasons.

```sql
SELECT COUNT(Engagement)
```

public\_engagements# [](#engagements-per-agent-per-day)Engagements per Agent per Day

Average number of engagements per agent per day.

```sql
SELECT AVG(
  SELECT Agent Engagements 
    BY Start Time ⏵ day, Agent)
```

public\_engagements\_per\_agent\_per\_day# [](#good-reviews)Good Reviews

The number of reviews that have normalized score 100% or higher (if bonus score is allowed).

```sql
SELECT Completed Reviews
  WHERE Review ⏵ Score >= 1
```

public\_good\_reviews# [](#greatest-difference-between-scores)Greatest Difference between Scores

```sql
SELECT GREATEST(
  ABS(Difference Between Customer and Agent Score),
  ABS(Difference Between Customer and Robot Score),
  ABS(Difference Between Customer and Review Score),
  ABS(Difference Between Agent and Robot Score),
  ABS(Difference Between Agent and Review Score),
  ABS(Difference Between Review and Robot Score))
```

public\_greatest\_difference\_between\_scores# [](#handling-time)Handling Time

Handling time is a time agent uses on their side to engage in a conversation. It represents the effort invested by the agent expressed in time.

```sql
SELECT IFNULL(Engagement ⏵ Preparation Time, 0) 
+ IFNULL(Engagement ⏵ Engagement Time, 0)
+ IFNULL(Engagement ⏵ Wrap Up Time, 0)
```

public\_handling\_time# [](#in-adherence-time)In Adherence Time

```sql
SELECT LEAST(Scheduled Time, {fact/activitytime})
  WHERE Activity ⏵ Type IN ("Agent Activity") # todo remove this condition after clean up
```

public\_in\_adherence\_time# [](#max-engagement-time)Max Engagement Time

Longest engagement time.

```sql
SELECT MAX(Engagement ⏵ Engagement Time)
```

public\_max\_engagement\_time# [](#max-focus-time)Max Focus Time

The maximum time the agent was focused on the customer. Unlike the Engagement Time this attributes time when the user had the engagement actually open in the agent desktop and does not include time when the agent was focused on something else while the engagement was not yet focused. This includes time during both engagement and wrap up phase. Most data sources do not support this level of detail.

```sql
SELECT MAX(Engagement ⏵ Focus Time)
```

public\_max\_focus\_time# [](#max-invitation-time)Max Invitation Time

The longest time it took an agent to accept, reject or miss an invitation to a conversation. You can filter by engagement status attribute to focus on accepted, rejected or missed invitations.

```sql
SELECT MAX(Engagement ⏵ Invitation Time)
```

public\_max\_invitation\_time# [](#max-preparation-time)Max Preparation Time

Average preparation time the agent spends before engagement preparing for it.

```sql
SELECT MAX(Engagement ⏵ Preparation Time)
```

public\_max\_preparation\_time# [](#max-wait-time)Max Wait Time

Longest time a customer waited for connection with an agent.

```sql
SELECT MAX(Engagement ⏵ Wait Time)
```

public\_max\_wait\_time# [](#max-wrap-up-time)Max Wrap Up Time

Longest time an agent spent in a wrap up phase.

```sql
SELECT MAX(Engagement ⏵ Wrap Up Time)
```

public\_max\_wrap\_up\_time# [](#median-engagement-time)Median Engagement Time

Median time agents spends engaged to the customer. This is from the moment when agent accepted invitation to join the conversation until the moment the agent moved to wrap up phase or completed the engagement.

```sql
SELECT AVG(Engagement ⏵ Engagement Time)
```

public\_median\_engagement\_time# [](#median-invitation-time)Median Invitation Time

The median time it takes an agent to respond to an invitation to the conversation. For rejected or missed invitation this it the time it takes an agent to reject the invitation.

```sql
SELECT MEDIAN(Engagement ⏵ Invitation Time)
```

public\_median\_invitation\_time# [](#median-wrap-up-time)Median Wrap Up Time

Median time it takes agents to wrap up an engagement. This includes work such as filling information about the engagement into a CRM or create followups.

```sql
SELECT AVG(Engagement ⏵ Wrap Up Time)
```

public\_median\_wrap\_up\_time# [](#mixed-reviews)Mixed Reviews

The number of reviews that have normalized score higher than 0% but lower than 100%.

```sql
SELECT Completed Reviews
  WHERE Review ⏵ Score > 0 AND Review ⏵ Score < 1
```

public\_mixed\_reviews# [](#order-of-engagement-in-conversation)Order of Engagement in Conversation

The order of engagement in a conversation ranked by start time of the engagement.

```sql
SELECT RANK(Engagement ⏵ Time) WITHIN(Engagement ⏵ Conversation)
```

public\_order\_of\_engagement\_in\_conversation# [](#out-of-adherence-time)Out of Adherence Time

The time the agent was out of adherence in a single time interval for a single activity.

```sql
SELECT GREATEST(Scheduled Time - {fact/activitytime}, 0)
```

public\_out\_of\_adherence\_time# [](#pending-reviews)Pending Reviews

The number of reviews that are still pending. A customer or a user was asked to provide the review but there is no response yet.

```sql
SELECT COUNT(Review) 
  WHERE Review ⏵ State IN ("Pending")
```

public\_pending\_reviews# [](#poor-reviews)Poor Reviews

The number of reviews that have normalized score 0% or lower (if negative score is allowed).

```sql
SELECT Completed Reviews
  WHERE Review ⏵ Score <= 0
```

public\_poor\_reviews# [](#queue-engagements)Queue Engagements

```sql
SELECT COUNT(Engagement)
  WHERE Engagement ⏵ Type = "Queue"
```

public\_queue\_engagements# [](#queue-engagements-completed)Queue Engagements Completed

The number of completed queue engagements.

```sql
SELECT Queue Engagements
 WHERE Engagement ⏵ State = "Completed"
```

public\_queue\_engagements\_completed# [](#queue-engagements-ignored-in-sla)Queue Engagements Ignored in SLA

Number of queue engagements that should be excluded from SLA calculation. These are often engagements that were too short and customer left before the company had any realistic chance of handling them properly.

```sql
SELECT Queue Engagements
  WHERE Engagement ⏵ Service Level IN ("Ignore")
```

public\_queue\_engagements\_ignored\_in\_sla# [](#queue-engagements-by-date)Queue Engagements by Date

```sql
SELECT AVG(
  SELECT Queue Engagements 
    BY Start Time ⏵ day)
```

public\_queue\_engagements\_by\_date# [](#queue-engagements-in-progress)Queue Engagements in Progress

Number of queue engagements that were in progress during the last load of data.

```sql
SELECT Queue Engagements
  WHERE Engagement ⏵ State IN ("In Progress")
```

public\_queue\_engagements\_in\_progress# [](#queue-engagements-out-of-sla)Queue Engagements out of SLA

The number of queue engagements that are not handled within the targets for service level.

```sql
SELECT Queue Engagements
  WHERE Engagement ⏵ Service Level IN ("Out of SLA")
```

public\_queue\_engagements\_out\_of\_sla# [](#queue-engagements-within-sla)Queue Engagements within SLA

Number of completed queue engagements that were handled within the target service level.

```sql
SELECT Queue Engagements
  WHERE Engagement ⏵ Service Level IN ("Within SLA")
```

public\_queue\_engagements\_within\_sla# [](#queue-engagements-previous-time-period)Queue Engagements 🜄 Previous Time Period

```sql
SELECT Queue Engagements 
  FOR PREVIOUS(Start Time ⏵ day)
```

public\_queue\_engagements\_previous\_time\_period# [](#queue-service-level)Queue Service Level

Percentage of completed queue engagements that were handled within the target service level.

```sql
SELECT Queue Engagements within SLA /
   Completed Queue Engagements
```

public\_queue\_service\_level# [](#queue-service-level-previous-time-period)Queue Service Level 🜄 Previous Time Period

```sql
SELECT Queue Service Level
  FOR PREVIOUS(Start Time ⏵ day)
```

public\_queue\_service\_level\_previous\_time\_period# [](#rank-in-engagement-time)Rank in Engagement Time

```sql
SELECT RANK(Engagement ⏵ Engagement Time)
```

public\_rank\_in\_engagement\_time# [](#rejected-invitations)Rejected Invitations

```sql
SELECT COUNT(Engagement)
  WHERE Engagement ⏵ Type IN ("Invitation")
    AND Engagement Outcome ⏵ Outcome IN ("Rejected")
```

public\_rejected\_invitations# [](#requested-customer-reviews)Requested Customer Reviews

Total number of reviews that were requested from the customer. Includes reviews that were completed but also those that are still pending, were ignored or rejected.

```sql
SELECT COUNT(Review)
  WHERE Review ⏵ Type IN ("Customer")
```

public\_requested\_customer\_reviews# [](#review-coverage)Review Coverage

```sql
SELECT Completed Reviews / Started Conversations
```

public\_review\_coverage# [](#review-delay)Review Delay

```sql
SELECT DATETIME_DIFF(
  End Time ⏵ minute, 
  Review Time ⏵ minute) 
  * 60 # So we have time in seconds as we have all duration times
```

public\_review\_delay# [](#reviewer-score)Reviewer Score

Score for a single review received from a reviewer. Normalized to 0 to 100%.

```sql
SELECT Review ⏵ Score 
  WHERE Review ⏵ Type IN ("Reviewer")
```

public\_reviewer\_score# [](#schedule-adherence)Schedule Adherence

```sql
SELECT Total In Adherence Time 
/ Total Scheduled Time
```

public\_schedule\_adherence# [](#started-agent-engagements-per-hour)Started Agent Engagements per Hour

```sql
SELECT AVG(
  SELECT Agent Engagements 
    BY Start Time ⏵ hour) 
```

public\_started\_agent\_engagements\_per\_hour# [](#started-conversations-2)Started Conversations 2

```sql
SELECT Agent Engagements 
  WHERE Engagement ⏵ Time = (SELECT MIN(Engagement ⏵ Time) 
      BY Engagement ⏵ Conversation ALL OTHER)
```

public\_started\_conversations# [](#started-conversations-per-agent)Started Conversations per Agent

```sql
SELECT AVG(
  SELECT Started Conversations 
    BYAgent)
```

public\_started\_conversations\_per\_agent# [](#started-conversations-per-agent-day)Started Conversations per Agent, Day

```sql
SELECT AVG(
  SELECT Started Conversations 
    BY Start Time ⏵ day, Agent)
```

public\_started\_conversations\_per\_agent\_day# [](#started-conversations-per-agent-hour)Started Conversations per Agent, Hour

```sql
SELECT AVG(
  SELECT Started Conversations 
    BY Start Time ⏵ hour, Agent)
```

public\_started\_conversations\_per\_agent\_hour# [](#started-conversations-per-hour)Started Conversations per Hour

The number of conversations that were started per hour.

```sql
SELECT AVG(
  SELECT Started Conversations 
    BY Start Time ⏵ hour)
```

public\_started\_conversations\_per\_hour# [](#tags)Tags

```sql
SELECT COUNT(Review) 
  WHERE Review ⏵ State IN ("Completed")
    AND Review Answer ⏵ Answer IN ("f3a5cbc7-cea1-4dfe-b90b-e992c36e585d")
```

public\_tags# [](#technical-max-scheduled-time)Technical - Max Scheduled Time

```sql
SELECT MAX(SELECT Total Scheduled Time BY Agent)
```

public\_technical\_max\_scheduled\_time# [](#technical-unknown-engagements)Technical - Unknown Engagements

```sql
SELECT COUNT(Engagement)
  WHERE Engagement ⏵ Type IN ("Unknown")
```

public\_technical\_unknown\_engagements# [](#total-activity-time)Total Activity Time

Total time agent actually spent in a given activity.

```sql
# TODO Remove filter - now because of schedule still being in data
SELECT SUM({fact/activitytime}) 
  WHERE Activity ⏵ Type IN ("Agent Activity")
```

public\_total\_activity\_time# [](#total-available-time)Total Available Time

Total time the agent was in any agent activity that is considered that the agent is available.

```sql
SELECT Total Activity Time
  WHERE {label/availability} IN ("Available")
```

public\_total\_available\_time# [](#total-engagement-time)Total Engagement Time

Total time spent engaged to the customer. If an agent is engaged to multiple customers at one time this metric counts that time multiple times.

```sql
SELECT SUM(Engagement ⏵ Engagement Time)
```

public\_total\_engagement\_time# [](#total-engagement-time-by-agent-by-day)Total Engagement Time by Agent by Day

The average total engagement time per agent per day. This metric is useful to measure how close the agents are to an expected time spent with the customer

```sql
SELECT AVG(
  SELECT Total Engagement Time 
    BY Agent, Start Time ⏵ day)
```

public\_total\_engagement\_time\_by\_agent\_by\_day# [](#total-focus-time)Total Focus Time

The total time the agent was focused on the customer. Unlike the Engagement Time this attributes time when the user had the engagement actually open in the agent desktop and does not include time when the agent was focused on something else while the engagement was not yet focused. This includes time during both engagement and wrap up phase. Most data sources do not support this level of detail.

```sql
SELECT SUM(Engagement ⏵ Focus Time)
```

public\_total\_focus\_time# [](#total-in-adherence-time)Total In Adherence Time

Total time in schedule adherence based on individual 15 minute intervals.

```sql
SELECT SUM(In Adherence Time)
```

public\_total\_in\_adherence\_time# [](#total-negative-transactions-revenue)Total Negative Transactions Revenue

Total of all negative revenue from all the transactions. This metric focuses specifically on transactions that had a negative financial impact such as refunds.

```sql
SELECT Total Transactions Revenue
  WHERE Transaction ⏵ Revenue < 0
```

public\_total\_negative\_transactions\_revenue# [](#total-out-of-adherence-time)Total Out of Adherence Time

Total time out of adherence based on individual 15 minute intervals.

```sql
SELECT SUM(Out of Adherence Time)
```

public\_total\_out\_of\_adherence\_time# [](#total-positive-transactions-revenue)Total Positive Transactions Revenue

Total of all positive revenue from all the transactions. This metric excludes all negative revenue such as refunds, charge backs, etc.

```sql
SELECT Total Transactions Revenue
  WHERE Transaction ⏵ Revenue > 0
```

public\_total\_positive\_transactions\_revenue# [](#total-revenue)Total Revenue

The total revenue from all transactions.

```sql
SELECT SUM(Transaction ⏵ Revenue)
```

public\_total\_revenue# [](#total-scheduled-time)Total Scheduled Time

Total time scheduled for agents to spend in a given activity.

```sql
SELECT SUM(Scheduled Time) 
```

public\_total\_scheduled\_time# [](#total-transaction-goods-volume)Total Transaction Goods Volume

Total volume of goods included in the transactions.

```sql
SELECT SUM(Transaction ⏵ Volume)
```

public\_total\_transaction\_goods\_volume# [](#total-transactions-cost)Total Transactions Cost

Total cost of goods reported in the transactions.

```sql
SELECT SUM(Transaction ⏵ Cost)
```

public\_total\_cost# [](#total-transactions-discount)Total Transactions Discount

Total value of discounts provided in the reported transactions.

```sql
SELECT Total Transactions Price 
- Total Revenue
```

public\_total\_transactions\_discount# [](#total-transactions-price)Total Transactions Price

Total (standard) price of items involved in the reported transactions.

```sql
SELECT SUM(Transaction ⏵ Price)
```

public\_total\_transactions\_price# [](#total-transactions-profit)Total Transactions Profit

Total profit generated in all reported transactions.

```sql
SELECT SUM(Transaction Profit)
```

public\_total\_transactions\_profit# [](#total-transactions-revenue)Total Transactions Revenue

Total revenue generated by the reported transactio

```sql
SELECT SUM(Transaction ⏵ Revenue)
```

public\_total\_transactions\_revenue# [](#total-unavailable-time)Total Unavailable Time

Total time the agent was in any agent activity that is considered that the agent is not available..

```sql
SELECT Total Activity Time
  WHERE {label/availability} IN ("Unavailable")
```

public\_total\_unavailable\_time# [](#total-wrap-up-time)Total Wrap Up Time

```sql
SELECT SUM(Engagement ⏵ Wrap Up Time)
```

public\_total\_wrap\_up\_time# [](#transaction-discount)Transaction Discount

Transaction discount is calculated as the (standard) price minus the actual transaction revenue.

```sql
SELECT Transaction ⏵ Price - Transaction ⏵ Revenue
```

public\_transaction\_discount# [](#transaction-profit)Transaction Profit

The profit of a transaction calculated as a revenue generated minus associated costs.

```sql
SELECT Transaction ⏵ Revenue - Transaction ⏵ Cost
```

public\_transaction\_profit# [](#transactions)Transactions

Total number of transactions associated with engagements. Transactions are operations that happened during the engagements and may or may not have financial implications. A transaction can be a sold product, refund of an existing product, change of state of an order, support request for a specific product and similar.

```sql
SELECT COUNT(Transaction)
```

public\_transactions# [](#unavailable-time)Unavailable Time %

The percentage of not available time out of total.

```sql
SELECT Total Unavailable Time
  / Total Activity Time
```

public\_unavailable\_time\_ratio# [](#user-engagements)User Engagements

Total number of engagements with users - agents that are people. This metric excludes engagements with bots and other services.

```sql
SELECT COUNT(Engagement) 
  WHERE Engagement ⏵ Type = "Agent"
    AND Agent ⏵ Type = "User"
```

public\_user\_engagements# [](#view)View

Metric useful for sorting the engagements and having click through to detailed customer journey. This metric does not show the actual number. It shows a constant text "View" that encourages users to click on it when viewing customer journey.

```sql
SELECT MAX(Engagement ⏵ Time)
```

public\_view# [](#view-engagements-with-review)View - Engagements With Review

Metric useful for sorting the engagements and having click through to detailed customer journey. This metric does not show the actual number. It shows a constant text "View" that encourages users to click on it when viewing customer journey.

```sql
SELECT MAX(Engagement ⏵ Time)
  WHERE (SELECT Completed Reviews 
    BY Engagement) >= 1
```

public\_view\_engagements\_with\_review# [](#view-engagements-without-reviews)View - Engagements Without Reviews

Metric useful for sorting the engagements and having click through to detailed customer journey. This metric does not show the actual number. It shows a constant text "View" that encourages users to click on it when viewing customer journey.

```sql
SELECT MAX(Engagement ⏵ Time)
  WHERE IFNULL(
    SELECT Agent Engagements with Review 
      BY Engagement, 0) = 0
```

public\_view\_engagements\_without\_reviews# [](#view-engagements-with-named-turns)View - Engagements with Named Turns

Metric useful for sorting the engagements and having click through to detailed customer journey. This metric does not show the actual number. It shows a constant text "View" that encourages users to click on it when viewing customer journey.

```sql
# Enables use for sorting by Engagement start time
SELECT MAX(Engagement ⏵ Time)
  # Include only engagements that have at least one named turn
  WHERE (SELECT DEMO Named Turns 
    # Number of turns is individually calculated for every engagement
    BY Engagement) >= 1
```

public\_view\_engagements\_with\_named\_turns

---

## Permissions

Source: https://help.salted.cx/en/articles/permissions


Permissions enable users to view different data and content in Salted CX and perform actions. Salted CX has granular permissions that give individual users the level of access they need.

By default, a user logged to Salted CX using an Identity Provider has no permissions and cannot access any part of the application. To enable users to access Salted CX you have to explicitly add permissions in the identity provider.

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

Always give users the minimum level of access they need to do their job efficiently. We recommend identifying just a few combinations of permissions you will be giving your users so it is fairly consistent across your company. We have tried to put some common combinations of permissions into [Permission Sets](https://help.salted.cx/en/articles/permissions#a3ca048eb32b4fa4b458bfae409ca5b6).





## [](#scope)Scope

Scope defines to what metadata, content, and objects the permissions apply.

| Scope | Description |
|---|---|
| \* | Users can perform the action on any entity within Salted CX. |
| ME | View only metadata and content related to my engagements. The meaning of this scope depends on the permission and context. |



## [](#permissions-list)Permissions List

Each permission has a scope. Supported scopes depend on the permission.

| Permission | Description | Scopes |
|---|---|---|
| account.manage | Change preferences for the entire account. | `*` |
| account.settings.ask | Change Ask settings for the entire account. | `*` |
| agent.view | Access to agent profile. | `*` |
| ask.engineering | Technical settings of asks enabling to adjust how AI model behaves. | `*` |
| ask.journey | Ask questions to AI in the customer journey on individual engagements, conversations and customer journey. | `*` |
| ask.sample | Ask questions to AI about larger set of engagements or reviews. | `*` |
| coaching.session.manage | Create and edit coaching sessions for agents. | `*` |
| content.salted.dashboards | View built-in Salted CX dashboards. | `*` |
| data.audio.agent | Play audio of the conversation in the customer journey | `*` — view metadata for all agents `ME` — view metadata only for engagements the user has handled |
| data.content.agent | View turn content in the customer journey. | `*` — view metadata for all agents `ME` — view metadata only for engagements the user has handled |
| data.metadata.agent | View metadata in dashboards and visualizations. | `*` — view metadata for all agents `ME` — view metadata only for engagements the user has handled |
| earlyAcccess.experiments | Access to experimental features. | `*` |
| form.manage | Create and modify forms. Enables to use existing questions in any of the forms. | `*` |
| protectedInformation.view | Reveal protected information in the customer journey. | `*` |
| question.manage | Create and modify questions. Enables to create and edit questions that can be used for building forms. | `*` |
| reporting.edit.metrics | Edit metrics. This also enables user to view all dashboards in Salted, include private, for technical reasons. | `*` |
| reporting.edit.reports | Edit dashboards and visualization. | `*` |
| reporting.savedView.manage | Save current filtering criteria as personal saved views in dashboards. | `*` |
| reporting.view | View dashboards and visualizations. | `*` |
| review.agent.acknowledge | Acknowledge agent reviews. | `*` |
| review.agent.dispute | Dispute agent reviews. | `*` |
| review.auto.acknowledge | Acknowledge auto reviews. | `*` — acknowledge any auto review `ME` — acknowledge only auto reviews of engagements that are associated with and turn (of any type) related to those engagements |
| review.auto.dispute | Dispute auto reviews. | `*` — dispute any auto review `ME` — dispute only auto reviews of engagements that are associated with and turn (of any type) related to those engagements |
| review.auto.verify | Provide feedback to auto reviews. This permission enables them to mark the auto reviews as Correct, Incorrect and Unclear. This permission has strong influence of Auto Reviewer accuracy. Users should receive training before getting this permission. | `*` |
| review.autoreviewer.manage | Create, fine-tune and manage auto reviewers. Auto reviewers enable to find reviews automatically. | `*` |
| review.customer.acknowledge | Acknowledge customer reviews. | `*` — acknowledge any customer review `ME` — acknowledge only customer reviews of engagements that are associated with and turn (of any type) related to those engagements |
| review.customer.dispute | Dispute customer reviews. | `*` — dispute any customer review `ME` — dispute only customer reviews of engagements that are associated with and turn (of any type) related to those engagements |
| review.review | Review engagements and turns by answering questions, providing tags and answers to questions. | `*` — review any engagement or turn `ME` — review only engagements that are associated with and turn (of any type) related to those engagements |
| review.reviewer.acknowledge | Acknowledge manual reviews. | `*` — acknowledge any manual review done by a reviewer `ME` — acknowledge only manual reviews of engagements that are associated with and turn (of any type) related to those engagements |
| review.reviewer.dispute | Dispute manual reviews. | `*` — dispute any manual review done by a reviewer `ME` — dispute only manual reviews of engagements that are associated with and turn (of any type) related to those engagements |
| saveSearch.shared.manage | Manage saved searches. Users can share their searches with the all users in their account. | `*` |
| user.settings.ask | Change Ask AI settings per user. | `*` |



## [](#permission-sets)Permission Sets

To simplify permission management we also provide permission sets that group multiple permissions under one common named item. By convention, the permission sets are in capital letters.

One user can have multiple permission sets and also have additional permissions that expand their permissions. Users can view and perform all actions listed in any permission set they have attached or in any individual permission.

| Role | Description |
|---|---|
| ALL | Access to every feature of Salted CX. Any new functionality added to our application is automatically available to this user. We do not recommend to assign this permission to anybody. It is intended primarily for the evaluation period before single sign-on is set up for the account. |
| AGENT | Permissions suitable for agents that give access to view reports filtered to their data and drill to the customer journey. |
| AGENT\_ALL\_CONTENT | Agents that are allowed to see all the data in the contact center. This can help agents to better understand complete customer journeys and see their performance compared to other agents. |
| ANALYST | Permissions suitable for analyst role - a dashboard creator that give access to create reports and edit metrics. |
| AUTO\_QA\_MANAGER | Permissions suitable for experienced users enabling full stack of analytical features including management of auto-reviewer models and ask AI. |
| REVIEWER | Permissions suitable for a person that performs manual quality assurance. |
| TEAM\_LEADER | Permissions suitable for team leaders that give access to all reports and search and drill to the customer journey of all agents. |
| TEAM\_LEADER\_QA | Team leaders who also perform quality assurance. |
| VIEW\_CONTENT | Permissions that enable to view all metadata and content. You can combine this permission set with other permissions set to widen the data available to the user but keeping the same set of actions the user can perform. |
| VIEW\_METADATA | Permissions that enable to view all metadata. You can combine this permission set with other permissions set to widen the data available to the user but keeping the same set of actions the user can perform. |
| VIEW\_PROTECTED | Permissions that enable to reveal protected (redacted) information in the customer journey. You can combine this permission set with other permissions set to widen the data available to the user but keeping the same set of actions the user can perform. |



![](https://www.notion.so/icons/warning_yellow.svg?mode=light)

Permissions sets are managed by Salted CX and we may add more permissions to give users access to features suitable for the given roles. If you need to be really strict with access to individual features of Salted CX do not use permission sets but always list individual permissions.





The following matrix contains what permissions are enabled for each permission set.

| Permission / Permission Set | ADMIN | AGENT | AGENT\_ALL\_CONTENT | ANALYST | AUTO\_QA\_MANAGER | REVIEWER | TEAM\_LEADER | TEAM\_LEADER\_QA | VIEW\_CONTENT | VIEW\_METADATA | VIEW\_PROTECTED |
|---|---|---|---|---|---|---|---|---|---|---|---|
| account.manage | `*` |  |  |  |  |  |  |  |  |  |  |
| agent.view |  | `ME` | `ME` | `*` | `*` | `*` | `*` | `*` | `ME` | `*` | `*` |
| ask.journey |  |  | `*` | `*` | `*` | `*` | `*` | `*` | `*` |  | `*` |
| coaching.session.manage |  |  |  |  |  |  | `*` | `*` |  |  |  |
| content.salted.dashboards |  |  |  |  | `*` | `*` |  | `*` |  |  |  |
| data.audio.agent |  | `ME` | `*` | `*` |  |  |  |  | `*` |  |  |
| data.content.agent |  | `ME` | `*` | `*` | `*` | `*` | `*` | `*` | `*` |  | `*` |
| data.metadata.agent |  | `ME` | `*` | `*` | `*` | `*` | `*` | `*` | `*` |  | `*` |
| form.manage |  |  |  |  | `*` | `*` |  | `*` |  |  |  |
| protectedInformation.view |  |  |  |  |  |  |  |  |  |  | `*` |
| question.manage |  |  |  |  | `*` | `*` |  | `*` |  |  |  |
| reporting.edit.metrics |  |  |  | `*` | `*` |  |  |  |  |  |  |
| reporting.edit.reports |  |  |  | `*` | `*` |  |  |  |  |  |  |
| reporting.view |  | `*` | `*` | `*` | `*` | `*` | `*` | `*` | `*` | `*` | `*` |
| review.agent.acknowledge |  |  |  |  |  |  | `*` |  |  |  |  |
| review.agent.dispute |  |  |  |  |  |  | `*` |  |  |  |  |
| review.auto.acknowledge |  | `ME` | `ME` |  |  |  | `*` |  |  |  |  |
| review.auto.dispute |  | `ME` | `ME` |  |  | `*` | `*` | `*` |  |  |  |
| review.auto.verify |  |  |  |  | `*` |  |  | `*` |  |  |  |
| review.autoreviewer.manage |  |  |  |  | `*` |  |  |  |  |  |  |
| review.customer.acknowledge |  | `ME` | `ME` |  |  |  | `*` |  |  |  |  |
| review.customer.dispute |  | `ME` | `ME` |  |  |  | `*` |  |  |  |  |
| review.review |  | `ME` | `ME` |  | `*` | `*` | `*` | `*` |  |  |  |
| review.reviewer.acknowledge |  | `ME` | `ME` |  |  |  | `*` |  |  |  |  |
| review.reviewer.dispute |  | `ME` | `ME` |  |  |  | `*` | `*` |  |  |  |
| saveSearch.shared.manage |  |  |  |  |  |  | `*` | `*` |  |  |  |



## [](#permissions-definition)Permissions Definition

You define permissions for individual users in a JSON object that you edit in your Identity Provider. Each user that should have access to Salted CX has to have the permission definition in stored in their attribute.

The example permission definition below uses just one permission set without version. User with this permission will able to perform tasks that we consider suitable for agents including getting new features.

```json
{
	"sets": ["ALL"]
}
```

The example permission definition below uses combination of 2 roles and individual permissions. This enables to empower Team Leaders with all AI features available and also gives them permission to review engagements.

```json
{
	"sets": ["TEAM_LEADER", "AI"],
	"review.view": "*",
	"review.edit": "*"
}
```

![](https://www.notion.so/icons/warning_yellow.svg?mode=light)

If the permission definition is not in a valid format the user has no access to Salted CX. Issues include invalid JSON structure, unknown permission set name, unknown permission name, values are not of the expected type and unsupported scope for a permission.





![](https://www.notion.so/icons/warning_yellow.svg?mode=light)

The limit for permissions is 2048 characters (including spaces, new lines and other empty characters). For this reason Salted CX enables you to specify permissions in a short way using [permissions sets](https://help.salted.cx/en/articles/permissions#a3ca048eb32b4fa4b458bfae409ca5b6). If the length of the permissions exceeds the 2048 characters and thus the permissions are not in valid JSON format Salted CX ignores the permissions and the given user has no access to Salted CX.





## [](#setting-permissions)Setting Permissions

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

Permissions are evaluated during login as they are passed to Salted CX from an identity provider. Users have to logout and login to have updated permissions.





User permissions are passed to Salted CX from identity providers in custom user attributes. Claim is a key-value pair associated with the user. Claims can be used to provide additional attributes that might be useful for applications such as Salted CX.

To give users access to Salted CX you need to provide value in `cxsaltedpermissions` in the [JSON format that Salted CX expects](https://help.salted.cx/en/articles/permissions#34a9548b062441ed8c8152062bf6ef6b). How the value is set depends on your identity provider.

*Tags: Users*


---

## Search

Source: https://help.salted.cx/en/articles/1759143839-search


Article short description

Salted offers a powerful search capability.

![](https://media.notiondesk.so/upload/698d90fc45cdd647610166.png)

---

## Vitals

Source: https://help.salted.cx/en/articles/1774997602-vitals


Article short description

Vitals monitors the key Conversation quality metrics and their alignment with your standards. It provides a short feedback loop between human and AI-generated reviews and the agents who receive them — replacing traditional calibration sessions with continuous, crowdsourced verification that builds trust and alignment.

![](https://media.notiondesk.so/upload/69ccd414b57c1086349971.png)

## [](#the-problem-with-traditional-calibration)The Problem with Traditional Calibration

In a conventional QA workflow, a small team of calibrators manually reviews a handful of conversations to verify that scores are fair and consistent. This approach has fundamental limitations:

- Low coverage — calibration typically touches a small fraction of all scored conversations, leaving the vast majority of feedback unverified.

- Slow feedback loop — calibration happens periodically (weekly, monthly), so inaccurate scoring criteria can persist for a long time before anyone notices.

- Limited perspective — calibrators assess quality from their own viewpoint, which may not reflect the reality of the agent's situation during the engagement.

## [](#crowdsourced-verification-through-agents)Crowdsourced Verification through Agents

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

You can start with each metric in a draft mode that clearly communicates to agents that the metric results have no impact on them yet, while they are already part of the process to make scoring fair and based on the ground experience.





Vitals shifts verification from a small calibration team to the agents themselves. Every agent who receives feedback can acknowledge or dispute it:

- Acknowledged — the agent agrees with the feedback. This is a positive signal that the scoring criteria and AI instructions are working as expected.

- Disputed — the agent disagrees with the feedback and provides a comment explaining why. This signals a potential problem with how the reviewer scores that particular metric.

By collecting these signals across all agents and all engagements, Vitals turns the entire agent population into a distributed calibration team. The result is:

- Near-complete coverage — every reviewed engagement can be verified, not just a sampled few.

- Near real-time signal — disputes surface within hours, not weeks. Agents still have a fresh memory of the conversations. This improve

- Agent perspective — the people closest to the conversation provide the feedback, catching context that a calibrator reviewing after the fact might miss.

- Alignment at scale — when agents consistently acknowledge feedback, it means the organization's quality standards are understood and shared. Disputes highlight where alignment is missing.

## [](#vitals-dashboard)Vitals Dashboard

The dashboard is organized around three areas:

- Headline metrics give at quick overview whether the performance overall is within the expected bounds.

- Questions health give you overview what feedback from agents you get on individual metrics

- Review Volume trends

### [](#key-metrics)Key Metrics

Five indicators at the top of the dashboard give an at-a-glance summary for the selected reviewer and time period (24 hours, 7 days, or 30 days):

| Metric | What it measures |
|---|---|
| Overall QA Score | Average score across all reviewed engagements |
| Conversations Processed | Number of distinct engagements the reviewer evaluated |
| Acknowledged | Number of reviews the agents confirmed as correct- |
| Disputed | Count of reviews the agents challenged — color-coded by health status. High number indicates that the attention is needed. |
| Feedback Coverage | Percentage of total engagements that received a review |



Each metric includes a comparison to the previous equivalent period (day-over-day, week-over-week, or month-over-month), so trends are immediately visible.

### [](#metrics-health)Metrics Health

Below the headline numbers, every review question (metric) the reviewer evaluates is listed in a table. Each row shows:

- Health status — a green or red indicator based on the dispute rate.

- Total reviews — how many times this question was scored.

- Average score — displayed as a color-coded ring (green &gt;= 3.5, amber &gt;= 2.5, red &lt; 2.5).

- Acknowledged / Disputed counts — the raw numbers from agent feedback.

Unhealthy metrics (those with a high dispute rate) are sorted to the top. A metric is considered unhealthy when it has 5 or more disputes and the disputed-to-acknowledged ratio exceeds 10%.

Each row is expandable. Expanding a disputed metric reveals individual disputed reviews, each showing:

- The answer the AI selected.

- The AI reviewer's comment explaining its reasoning.

- The agent's dispute comment explaining their disagreement.

You can open the conversation in the sidebar from the expanded view of the metric.

You can drill from a high-level health signal all the way down to a specific moment in a conversation to understand whether the AI or the agent was right. Based on this information, you can adjust the AI reviewer's instructions accordingly, or better talk to an agent to better align on expectations.

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

As with human reviews it is close to impossible to align on every single scenario. There will always be rare scenarios in which human and AI reviews are not accurate and you should consider whether it makes sense to cover those scenarios in 





### [](#volume-charts)Volume Charts

Two time-series charts track trends over the selected period:

- Engagements chart — how many engagements the reviewer processed over time. Any sudden changes may be a reason to investigate why extra engagements we reviewed, and why some were not.

- Agent feedback chart — a stacked view of acknowledged and disputed reviews. The overall volume tells you about the agents' engagement in the review process. The ratio indicates how the AI scores are aligned with the agents' perspective. Expect natural changes in the volume, for example when a new metric is introcuced or changed the usage may spike and the ratio of disputes may raise.

## [](#the-continuous-improvement-loop)The Continuous Improvement Loop

Vitals is designed to drive a virtuous cycle that moves your quality and performance forward in many incremental steps:

1. AI reviews engagements using last version of scoring criteria.

2. Agents acknowledge or dispute the feedback they receive.

3. QA Managers or Team Leaders watch Vitals to see which metrics are healthy and which require their attention.

4. They investigate disputes — they triage the AI's reasoning, the agent's counter-argument, and the actual content of the conversation.

5. They refine reviewer instructions to improve inaccurate criteria or clarify ambiguous scenarios.

6. Accuracy improves, dispute rates drop, and agents see fairer feedback — reinforcing their trust in the score and their willingness to provide more feedback.

This loop runs continuously rather than in periodic calibration cycles, which means the quality program adapts faster and stays closer to ground truth.

## [](#access-and-permissions)Access and Permissions

The vitals screen requires the `reporting.view` permission.

---

## What is Salted CX?

Source: https://help.salted.cx/en/articles/what-is-salted-cx


Understand Salted as an AI-native customer-service and contact-center platform, how its product areas fit together, and the ways companies can adopt it.

Salted CX is an AI-native customer-service and contact-center platform where AI agents, human agents, and external experts can operate customer conversations together.

Salted connects the work of handling customer interactions with the controls and evidence needed to improve that work. Depending on the account, channels, integrations, and deployment model, companies can use Salted to operate conversations directly or add selected Salted capabilities alongside an existing contact-center stack.

## [](#the-salted-operating-model)The Salted operating model

### [](#operate-conversations)Operate conversations

AI agents can interpret customer requests, use knowledge, collect information, call connected systems, perform permitted actions, route work, and resolve eligible requests. Human agents can work in the same conversation environment when a person should guide or own the interaction.

### [](#add-human-judgment-without-losing-context)Add human judgment without losing context

AI does not always need to disappear when a person becomes involved. A configured workflow can ask a human for guidance or approval, invite a specialist or external expert, or hand over the conversation. The human sees the conversation and customer context. When the human contribution ends, AI can continue where the workflow permits it.

### [](#prove-and-improve-outcomes)Prove and improve outcomes

Salted connects operated conversations with automated and manual quality review, agent feedback, coaching, customer-journey context, Search, Ask, and analytics. This gives teams shared evidence for improving people, AI behavior, knowledge, policy, routing, and operational workflows.

## [](#how-the-product-areas-fit-together)How the product areas fit together

- AI Agents are customer-facing automation that interprets requests, uses knowledge and tools, performs permitted actions, and operates conversations.

- Live Conversations is the environment where AI agents, human agents, and external experts operate active customer conversations together. It is not only the interface people see; behind the interface, it coordinates conversation state, participants, routing, engagements, events, actions, handoffs, joining, leaving, and channel behavior.

- Agent Desktop is the human workspace inside Live Conversations. It brings together the transcript, customer context, replies, information, actions, and controls needed to work the conversation. Authorized supervisors can also monitor ongoing AI-led and human conversations, open them without joining, and then join or take over when intervention is needed.

- Automation logic controls what happens next in a customer conversation. It can combine rules, AI, workflows, and connected systems, then tell Salted which actions to perform. In Salted configuration and technical documentation, this automation logic is called Your Logic.

- Quality Intelligence evaluates and improves service delivered by human agents, AI agents, and mixed human-AI workflows.

- Conversation Intelligence uses Search, Ask, analytics, references, and customer-journey context to explain what happened and what should change.

## [](#two-common-adoption-paths)Two common adoption paths

### [](#operate-conversations-in-salted)Operate conversations in Salted

Use Salted channels, Live Conversations, Agent Desktop, AI Agents, and connected automation logic as the operating environment for selected or all customer interactions.

### [](#complement-an-existing-contact-center-stack)Complement an existing contact-center stack

Connect conversations from existing platforms and adopt selected Salted capabilities for quality, coaching, analytics, customer journeys, or automation. The exact boundary depends on the customer's systems and migration plan.

## [](#what-makes-the-operating-model-different)What makes the operating model different

Salted supports more than a one-way bot-to-human handoff. Depending on the configured workflow, a person can contribute only the judgment that requires a human, take full ownership when needed, or return control to AI afterward. The same interaction can then be evaluated and used to improve the operation.

## [](#availability-and-maturity)Availability and maturity

Capabilities, channels, and deployment modes vary by account and integration. A developer primitive, demo, private library, or planned capability is not automatically generally available to every customer. Use the relevant setup and reference articles to confirm current production availability, prerequisites, permissions, and limitations.

## [](#where-to-go-next)Where to go next

- Understand customer-facing automation in [What are AI Agents in Salted?](https://help.salted.cx/en/articles/what-are-ai-agents-in-salted).

- Understand the human workspace in [What is Agent Desktop?](https://help.salted.cx/en/articles/what-is-agent-desktop).

- Learn how AI agents and people collaborate in [How AI and human agents work together in Salted](https://help.salted.cx/en/articles/how-ai-and-human-agents-work-together-in-salted).

- Follow the interaction from first message to completion in [Customer conversation lifecycle in Salted](/3a25d3a2a8dc818dbbb1cd7688d35b1b).

- Learn how Your Logic controls conversation behavior in [How automation logic controls a customer conversation](https://help.salted.cx/en/articles/how-automation-logic-controls-a-customer-conversation).

- Learn how Salted evaluates and improves human and AI service in [What is Quality Intelligence?](/3a25d3a2a8dc81ac8576e00cc0c4a5bd).

- Learn how Salted investigates customer and operational behavior in [What is Conversation Intelligence?](/3a25d3a2a8dc81aea6c2e06ee7946227).

- See individual performance, feedback, and coaching in [Agent Home](https://help.salted.cx/en/articles/1784371079-agent-home).

---

## Your Logic Events

Source: https://help.salted.cx/en/articles/your-logic-requests


Salted CX sends conversation-related data using an HTTP `POST` method. Each request represents an event that happens in the conversation. Salted CX also sends entire context with each event. This enables keeping your logic implementation stateless for many scenarios.

Salted CX ensures that all requests related to the same conversation are sent sequentially, and Salted CX waits for Your Logic response before sending another request related to the same conversation.

## [](#performance-considerations)Performance Considerations

Salted CX does send an event for every major action that happens in the conversation, such as sending a message, an agent joining or leaving the conversation, etc. This can be a significant traffic that grows with the number of conversations that are handled in Salted CX. You need to scale your implementation accordingly. Ideally, responding elastically to load.

You can expect roughly 20 to 30 events/requests per conversation. However, this strongly depends on your processes and the type of conversations you have with your customers.

## [](#request-headers)Request Headers

Each request has the following headers:

| Header | Type | Description |
|---|---|---|
| `Authorization` | String | The token you can use to verify that this event was sent by Salted CX. This is a shared secret and you have to ensure you protect the token on your side so a bad actor cannot use it to pretend they are Salted CX. Value is in format `Bearer <shared secret>` |



## [](#request-structure)Request Structure

Requests have a common structure as described below.

| Property | Type | Description |
|---|---|---|
| `requestId` | UUID | Unique identifier of this request. This identifier is important when responding back so Salted CX knows that the request is resolved. |
| `expires` | Time | The time until which Your Logic has time to respond to this request. Salted CX may or may not provide additional grace period that you should not rely on and may change based on different conditions. |
| `trigger` | Object | Describes the event that caused this request to be sent to Your Logic. You can filter by trigger type and other properties whether you want to process the request. |
| `accountId` | UUID | Unique identifier of the account in Salted CX. (SHOULD NOT BE NECESSARY) |
| `domain` | String | The domain of the customer within Salted CX. |
| `region` | String | The region in which the account has all the data. |
| `url` | String, optional | The URL of the last known customer location in Universal Chat. It is sent inside the `conversation` object as `lastVisitedUrl`, not as a top-level request field. This enables you to tailor the response to the content the customer is currently looking at. |
| `customer` | Object | Structured information about the customer including custom data. |
| `conversation` | Object | Structured information about the conversation including custom data. |
| `engagements` | Array | Engagements related to this conversation. |
| `turns` | Array | Chronologically ordered turns. |



See example request JSON that you would receive.

```json
{
  "requestId": "3c99280a-9871-4656-a472-5da68d30c01f",
  "accountId": "{{account_id}}",
  "time": "2025-07-31T05:10:08.263515641Z",
  "expires": "2025-07-31T05:10:28.263515641Z",
  "trigger": {
    "time": "2025-07-31T05:10:07Z",
    "type": "MESSAGE",
    "participantType": "CUSTOMER",
    "content": "Order is still not delivered",
    "contentCustomer": "Order is still not delivered",
    "languageCustomer": "en",
    "contentAgent": "Order is still not delivered",
    "languageAgent": "en"
  },
  "domain": "demo-development",
  "region": "eu",
  "customer": {
    "pid": "e00609f4-1fa5-44b1-ad43-84c59a3450ca",
    "displayName": "Adam Novak",
    "contacts": [
      {
	      "pid": "a6d165b8-0e91-432b-b6d2-ac8ec6d78dc7"
        "contact": "+420123456789",
        "type": "Phone"
      },
      {
	      "pid": "c6d165b8-0e91-432b-b6d2-ac8ec6d78dc7"
        "contact": "adam.novak@salted.cx",
        "type": "Email"
      }
    ]
  },
  "conversation": {
    "pid": "005ea483-5151-479d-842e-f5ef0a1fa5cc",
    "startConversationTime": "2025-07-31T05:09:24Z",
    "needsHelp": false,
    "status": "IN_PROGRESS",
    "platform": "WHATSAPP",
    "direction": "INBOUND",
    "languageCustomer": "en",
    "url": "https://help.demoadventures.com/article/12345",
    
    "custom": {
	    "orderState": "In Progress",
	    "orderNumber": "ORD-1234",
	    "history": [
		    {
		    }
	    ]
    },
    
    "info": [
	    {
		    "title": "Help",
			   "text": "Manual",
			   "url": "https://help.demo-advetures.com"
	    }
    ]
  },
  "engagements": [
    {
      "pid": "615ea483-5151-479d-842e-f5ef0a1fa5cc",
      "time": "2025-07-31T05:09:24Z",
      "type": "QUEUE",
      "status": "COMPLETED",
      "agent": {
	       "type": "BOT",
      }
    },
    {
      "pid": "a142fb87-c5b7-4e9f-b047-34ab7c480ae6",
      "time": "2025-07-31T05:09:31.995513Z",
      "type": "AGENT",
      "status": "IN_PROGRESS",
      "agent": {
        "pid": "732e8047-73ab-5ada-bd8e-b11b764f8b08",
	      "type": "BOT",
	      "email": null,
	      "name": "Your Logic"
      }
    }
  ],
  "turns": [
    {
      "time": "2025-07-31T05:09:24Z",
      "engagementPid": "615ea483-5151-479d-842e-f5ef0a1fa5cc",
      "type": "MESSAGE",
      "participantType": "CUSTOMER",
      "content": "Parcel is gone",
      "contentCustomer": "Parcel is gone",
      "languageCustomer": "en",
      "contentAgent": "Parcel is gone",
      "languageAgent": "en",
      "status": "RECEIVED",
      "id": "893da24c-32c9-4bcd-959a-bf58ef779619",
      "pid": "a68d8992-1ad5-5c7d-97dc-95fe1344f6ce"
    },
    {
      "time": "2025-07-31T05:09:32.042590Z",
      "engagementPid": "a142fb87-c5b7-4e9f-b047-34ab7c480ae6",
      "type": "MESSAGE",
      "participantType": "BOT",
      "content": "I'm not sure I understand. Can you rephrase or provide more details?",
      "contentCustomer": "I'm not sure I understand. Can you rephrase or provide more details?",
      "languageCustomer": "en",
      "contentAgent": "I'm not sure I understand. Can you rephrase or provide more details?",
      "languageAgent": "en",
      "status": "VIEWED",
      "id": "043b40d0-96a4-4e9d-8d70-f4cd8bcceec5",
      "pid": "4688baf4-5c80-5b63-8d7f-c11c1fbe2d95"
    },
    {
      "time": "2025-07-31T05:10:07Z",
      "engagementPid": "a142fb87-c5b7-4e9f-b047-34ab7c480ae6",
      "type": "MESSAGE",
      "participantType": "CUSTOMER",
      "content": "Order is still not delivered",
      "contentCustomer": "Order is still not delivered",
      "languageCustomer": "en",
      "contentAgent": "Order is still not delivered",
      "languageAgent": "en",
      "status": "WAITING_FOR_ENRICHMENTS",
      "id": "3c99280a-9871-4656-a472-5da68d30c01f",
      "pid": "c2eb7856-7e9f-5d27-bac9-7b917604d69c"
    }
  ]
}
```

### [](#trigger)Trigger

The trigger has a common properties.

| Property | Type | Description |
|---|---|---|
| time | Time | The time when the event was received by Salted CX. |
| type | String |  |
| participantType | String | The type of the participant to distinguish customer, agents, external agents, bots, etc. Values |



Depending on the type of the trigger there are additional properties covering specifics of the trigger.

## [](#triggers-list)Triggers List

| Trigger | Description |
|---|---|
| [Message](https://help.salted.cx/en/articles/your-logic-requests#1d45d3a2a8dc80b5a868e1fed137b7ef) | A participant sent a text message. |
| [File](https://help.salted.cx/en/articles/your-logic-requests#1d45d3a2a8dc8050af64cdfc841ef816) | A participant sent a media or a file. |



## [](#message-from-customer)Message from Customer

This request is sent when a customer sends a message.

| Property | Type | Description |
|---|---|---|
| `content` | String (Optional) | Content sent from the customer translated to the account content language. The content is not available in case translation is not enabled. Also if Salted CX is unable to translate the message in a short timeframe for any reason (for example translation service issues). |
| `contentCustomer` | String | The verbatim content the customer wrote in their language. |
| `languageCustomer` | String | Detected language of the customer message. Remember that the detection is not 100% accurate and the accuracy depends on many factors including the length of the message. |
| `languageAgent` | String | The language in which the agent sent the message. |



```json
{
	"requestId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
	"time": "2025-04-11T10:57:42Z",
	"expires": "2025-04-11T10:57:57Z",
	
	"domain": "company",
	"region": "eu",
	
	"trigger": {
		"time": "2025-04-11T10:57:42Z",
		"type": "MESSAGE",
		"participantType": "CUSTOMER",
		"content": "Hello, how are you?",
		"language": "en",
		"contentCustomer": "Hola, qué tal?",
		"languageCustomer": "es"
	}
	
	/* rest of the event */
}
```

## [](#message-from-agent)Message from Agent

You can use your logic to intercept messages from agents.

```json
{
	"requestId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
	"time": "2025-04-11T10:57:42Z",
	"expires": "2025-04-11T10:57:57Z",
	
	"domain": "company",
	"region": "eu",
	
	"trigger": {
		"time": "2025-04-11T10:57:42Z",
		"type": "MESSAGE",
		"participantType": "AGENT",
		"agent": "a7ac10b-58cc-4372-a567-0e02b2c3d472",
		"content": "How can I help you?",
		"language": "en"
	}
	
	/* rest of the event */
}
```

## [](#send-files-and-media)Send Files and Media

This request informs about media exchange. Salted CX also sends you a link to the file you can use to access the file data. The link to the media is valid for 24 hours.

| Property | Type | Description |
|---|---|---|
| `time` | Time | When the turn was received or sent. |
| `type` | File | Constant `File` for this requests. |
| `participantType` | String — AGENT, BOT, CUSTOMER, EXTERNAL\_AGENT, SYSTEM | Who sent the file. |
| `mediaName` | String | The name of the file. |
| `mimeType` | String | MIME type of the file. |
| `mediaLink` | String | The full path to the file that can be used to download it. The link is valid for a time restricted time period 2č hours. |



```javascript
{
	"requestId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
	"time": "2025-04-11T10:57:42Z",
	"expires": "2025-04-11T10:57:57Z",
	
	"domain": "company",
	"region": "eu",
	
	"trigger": {
		"time": "2025-04-11T10:57:42Z",
		"type": "FILE",
		"participantType": "CUSTOMER",
		"mediaName": "theLastNameOfThe.pdf",
		"mimeType": "application/pdf"
		"mediaLink": "https://storage.aws.com/theLastNameOfThe.pdf"
	}
	
	/* rest of the event */
}
```





## [](#navigation-step-upcoming)Navigation Step (Upcoming)

Event that notifies Your Logic about user navigating to a new web page. You can watch this event to trigger actions based on customer steps in your web application. The URL the customer went to is passed in the trigger and it is contained in all subsequent events so you can tailor Your Logic responses based on what customer looks at.

The length of the URL is 2048 characters. Longer URLs are trimmed to 2048.

```json
{
	"requestId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
	"time": "2025-04-11T10:57:42Z",
	"expires": "2025-04-11T10:57:57Z",
	
	"domain": "company",
	"region": "eu",
	
	"conversation": {
		"lastVisitedUrl": "https://help.demoadventures.com/article/12345"
	},
	
	"trigger": {
		"time": "2025-04-11T10:57:42Z",
		"type": "Navigation",
		"lastVisitedUrl": "https://help.demoadventures.com/article/12345"
	}
}
```





## [](#action)Action

When an agent presses a button in [Live Conversations](https://help.salted.cx/en/collections/1755577083-live-conversations) Salted CX sends an event notifying Your Logic that it should perform an action with the given name. Salted CX is not aware what the action does.

The action is identified only by its name and does not contain any parameters. Your Logic implementation can retrieve any value from the context sent with the event.

| Property | Type | Description |
|---|---|---|
| `participantType` | Enum | Type of the participant who triggered an action. `AGENT``CUSTOMER``EXTERNAL_AGENT` |
| `agent` | PID | The identifier of the agent who triggered the action. |
| `action` | String | A name of the action that was triggered. |



```json
{
	"requestId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
	"time": "2025-04-11T10:57:42Z",
	"expires": "2025-04-11T10:57:57Z",
	
	"domain": "company",
	"region": "eu",
	
	"trigger": {
		"time": "2025-04-11T10:57:42Z",
		"type": "ACTION",
		"participantType": "AGENT",
		"agent": "dac1c10b-58cc-4372-a567-0e02b2c3d479",
		"action": "schedule-followup-code"
	}
}
```

We recommend you send back at least a feedback to the agent using a [note action](https://help.salted.cx/en/articles/your-logic-actions#1d45d3a2a8dc80fda3d1f7b4212358b8) to let them know that the action perfomed an operation. In some cases triggering an action can send a message also directly to the customer.

For example if an agent presses a button to create an internal task in an issue tracking system you can send the message with the link to that task in an external system. The following example shows how that can look in the customer journey:

![](https://www.notion.so/icons/chat_green.svg?mode=light)

Can you raise the issue with our account manager?





![](https://www.notion.so/icons/cursor-button_blue.svg?mode=light)

Maria triggered the action Create Internal Ticket





![](https://www.notion.so/icons/compose_purple.svg?mode=light)

Created a related ticket in the issue tracker [INTERNAL-1234](https://help.salted.cx/)





![](https://www.notion.so/icons/chat_blue.svg?mode=light)

Sure. I have escalated the issue internally. We will keep you posted about any updates.









## [](#menu-step-idea)Menu Step (Idea)

Salted CX sends menu step whenever a customer reaches an article that has set the Technical ID property to any value. You can watch for these requests to trigger actions.

```json
{
	"requestId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
	"time": "2025-04-11T10:57:42Z",
	"expires": "2025-04-11T10:57:57Z",
	
	"domain": "company",
	"region": "eu",
	
	"trigger": {
		"time": "2025-04-11T10:57:42Z",
		"type": "MENU_STEP",
		"participantType": "CUSTOMER",
		"technicalID": "refund-credits"
	}
	
	/* rest of the event */
}
```

## [](#answer)Answer

When a customer or an agent replies to a question.

```json
{
	"trigger": {
		"time": "2025-04-11T10:57:42Z",
		"type": "ANSWER",
		"participantType": "CUSTOMER",
		"answerId": "refund-credits",
		"answerName": "Refund credits"
	}
	
	/* rest of the event */
}
```

## [](#review)Review

When there is a review created by a participant Your Logic lets you know about it. This enables you to respond to customer or agent feedback. For example if the customer is unhappy with the response from a bot you ask agents for help.

```json
{
	"trigger": {
		"time": "2025-04-11T10:57:42Z",
		"type": "REVIEW",
		"reviewType": "Customer",
		"questionPid": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
		"questionName": "Thumbs Down",
		"answerPid": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
		"answerName": "Thumbs Down"
	}
}
```





## [](#conversation-state-upcoming)Conversation State  (Upcoming) 

Triggered by changes in the conversation attributes.

```json
{
	"trigger": {
		"time": "2025-04-11T10:57:42Z",
		"type": "Conversation Update",
		"conversation": {
			"state": "Customer Resolved"
		}
	}
	
	/* rest of the event */
}
```

## [](#completed-engagement)Completed Engagement

This request is sent when an engagement gets completed. Using this event you can detect that an agent considers their engagement done and Your Logic can take over control of the conversation. This is useful for example for closing the conversation — asking the customer whether their issue is resolved, how they are satisfied, etc.

```json
{
  "requestId": "a7b8c9d0-1234-5678-9abc-def012345678",
  "accountId": "550e8400-e29b-41d4-a716-446655440000",
  "time": "2025-11-05T14:30:00Z",
  "expires": "2025-11-05T15:30:00Z",
  "domain": "example.eu.salted.cx",
  "region": "eu",
  "trigger": {
    "type": "ENGAGEMENT_COMPLETE",
    "time": "2025-11-05T14:29:55Z",
    "engagement": {
      "pid": "d3e4f5a6-7890-1234-5678-90abcdef1234",
      "time": "2025-11-05T14:00:00Z",
      "agent": {
        "pid": "b1c2d3e4-5678-9012-3456-789012345678",
        "type": "USER",
        "email": "agent@example.com",
        "name": "John Smith"
      },
      "type": "AGENT",
      "status": "COMPLETED",
      "name": "Customer Support Chat",
      "outcomeType": "AGENT_RESOLVED",
      "outcomePid": "e5f6a7b8-9012-3456-7890-123456789012",
      "cost": 5.50
    }
  }
}
```







## [](#offered-conversation)Offered Conversation

This event notifies Your Logic that a conversation was offered to the customer. This means that a conversation is offered to the customer. This event is created in the moment before the customer sends any message, or other content.

Offered conversations enable Your Logic to send dynamic content to the customers at the very beginning of the conversations. While the conversation is in the Offered state Your Logic (and agents) can send any content as if the covnerssation was In Progress. Once the the customer sends any message or other content the conversation state is switched to In Progress state.

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

Conversations without the customer response that stay in offered state are hard deleted after a timeout. Offered conversations are not visible in reporting and analytics.





| Property | Type | Description |
|---|---|---|
| `conversationPid` | UUID | The ID of the conversation that was offered to the customer. |



```json
{
	"requestId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
	"time": "2025-04-11T10:57:42Z",
	"expires": "2025-04-11T10:57:57Z",
	
	"trigger": {
		"type": "CONVERSATION_OFFERED",
		"conversationPid": "4644535e-5d63-4dd8-8018-528bf55fcbac"
	}
}
```





## [](#completed-conversation)Completed Conversation

This event notifies Your Logic about a completed conversation.

| Property | Type | Description |
|---|---|---|
| `conversationPid` | UUID | The ID of the conversation that was completed. |



```json
{
	"requestId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
	"time": "2025-04-11T10:57:42Z",
	"expires": "2025-04-11T10:57:57Z",
	
	"trigger": {
		"type": "CONVERSATION_COMPLETE",
		"conversationPid": "4644535e-5d63-4dd8-8018-528bf55fcbac"
	}
}
```





## [](#inactive-conversation)Inactive Conversation

The event is sent to Your Logic when there is inactivity in a conversation for a setup time frame. This event enables you to respond to inactivity in the conversation without having to schedule tasks or maintain state in your implementation.

You can set up how often you receive inactive conversation events. The maximum frequency is every 15 minutes, but you can set up less frequent notifications or turn them off in Live Conversations settings.

We do our best to deliver the inactive conversation event at latest within 1 minute after a given time period passes. So for 15 minute time internal you should receive the first inactive conversation event latest 16 minutes after the inactivity started.

| Property | Type | Description |
|---|---|---|
| `lastActiveTime` | Time | The time of the last activity in the conversation. |



```json
{
	"requestId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
	"time": "2025-04-11T10:57:42Z",
	"expires": "2025-04-11T10:57:57Z",

	"trigger": {
		"type": "CONVERSATION_INACTIVE",
		"conversationPid": "4644535e-5d63-4dd8-8018-528bf55fcbac",
		"lastActiveTime": "2025-04-11T10:57:42Z"
	}
}
```





## [](#your-logic-disengaged)Your Logic Disengaged

This event is sent when Your Logic is disengaged from the conversation. A typical cause is that Your Logic became unresponsive. Salted CX sends this event to give Your Logic the chance to reengage in the conversation.

```json
"requestId" : "5b1f0c2e-9d3a-5c4e-8f7a-2d6b1e9c0a41",
    "accountId" : "3f2b9c1a-7d4e-4b8a-9c6d-1e2f3a4b5c6d",
    "time" : "2026-09-03T09:41:12.318Z",
    "expires" : "2026-09-03T09:41:22.318Z",
    "trigger" : {
      "time" : "2026-09-03T09:41:12.318Z",
      "type" : "YOUR_LOGIC_DISENGAGED"
    }
}
```

To re-engage in the conversation, respond to this event with the [Engage Your Logic action](https://help.salted.cx/en/articles/your-logic-actions#1d45d3a2a8dc804b9a92ddf2e055408a). Reengaging only means that Your Logic receives all the events it does not do anything else. If the conversation fell into Needs Help in Live Conversations it stays there unless the bot explicitly removes it.

![](https://www.notion.so/icons/warning_yellow.svg?mode=light)

Before you reengage, check the conversation's current state. For example, you can check whether the conversation is waiting in Needs Help and remove it so agents don’t join it.





## [](#custom-data)Custom Data

Customer and Conversation objects have a custom JSON object. This object can hold any data that you need to handle the conversation. Unlike the rest of the JSON, the structure of this object is not restricted and may contain any keys and values of any type.

The custom data object size is limited to 1kB. The object is not intended to contain large complex data. If you need large data associated with the conversation, store a reference to the data in the custom object and store the actual referenced data in your infrastructure.

*Tags: Your Logic*


---

## Built-in Metrics Overview

Source: https://help.salted.cx/en/articles/metrics-overview


Salted CX provides set of built-in metrics that are independent on data source and you can use them from day one to build insights and dashboards.

This article focuses on some common KPIs contact centers use to measure performance and how Salted CX understands them. For details on how individual metrics are calculated please check [Metrics Reference](https://help.salted.cx/en/articles/1755225286-metrics-reference).

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

Quality and granularity of data from the source platforms may be impact what metrics are available for the given platform.





## [](#handling-time)Handling Time

Salted CX calculates handling time using a simple formula:

HandlingTime = PreparationTime+EngagementTime+WrapUpTimeHandling Time is focused on reporting time agents are reserved to engage in a given conversation.

Preparation Time is the time agent spends preparing for the engagement without actually engaging with the customer. For example during some outbound campaigns the agent may need some time to learn basic information about the customer to have shorter engagement time and better rapport building with the customer.

Engagement Time is the time the agent is in conversation and engaging with the customer. This is from the moment when agent joins the conversation until the moment the agent leaves the conversation with the customer and transitions to wrap up work if any.

Wrap Up Time is the time agent spends after they leave the conversation with the customer to perform tasks such as filling information into a CRM.

There can be multiple engagements in a single conversation. These engagements can overlap. This means that sum of handling time (and engagement time) for a conversation can be more that the conversation lasted. For example if two agents would be engaged with the customer from start to end the sum of engagement time for that conversation would be twice the actual duration.

## [](#service-level)Service Level

Service level represents percentage of engagements that were handled within required

Built-in metrics for service level rely on `Engagement ⏵ Service Level` attribute. This attribute has several possible values as shown in the table below.

| Service Level | Description |
|---|---|
| Within SLA | The engagement was handled according to service level requirements. |
| Out of SLA | The engagement was not handled within the service level requirements. |
| Ignore | The engagement should be excluded from any calculation of SLA-based metrics. |







The general formula for calculating the service level is the following:

SLA = \\frac{EngagementsWithinSLA}{TotalEngagements-IgnoredEngagements}There are several other considerations for the built in SLA metrics:

- Only engagements that are completed are included in SLA calculation

- Engagements that have any other value from the above table are included in the number of total engagements

- There are separate metrics related to engagements with `Type` equal to `Agent` and `Queue` because different connected platforms provide different SLA calculations

- The categorization to the categories above depends on settings in the connected platform.

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

You can create a custom metric for service level calculation that takes into consideration specifics of you business.





## [](#transactions)Transactions

Transactions represent a operations that were made during an engagements. They may or may not have a financial impact.

Each transaction has the following facts:

| Fact | Description |
|---|---|
| Cost | All the costs associated with this transitions. |
| Price | Base price for this transaction before any discounts for the entire volume. |
| Revenue | Total actual revenue generated from this transaction. This includes any discounts and applies to the entire volume of the transaction. |
| Volume | Number of items or volume of products or services associated with this transaction. |



There are built-in metrics calculated facts available in the [Transaction](https://help.salted.cx/en/articles/model-transaction) data set based on formulas below:

Profit = Revenue - CostMargin = \\frac{Profit}{Revenue}Discount = Price - RevenueDiscount\\ \\% = \\frac{Discount}{Price} = \\frac{Price - Revenue}{Price}![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

You can create custom metrics for transactions-related reporting.





![](https://www.notion.so/icons/warning_yellow.svg?mode=light)

Salted CX is not intended as a financial reporting tool. The transaction data are supported to help contact centers be more aligned with the overall business and understand relationships and tradeoffs between estimated financial performance and other performance metrics.





## [](#in-progress-metrics)In Progress Metrics

There are multiple metrics showing engagements in progress. This means that these engagements were in progress during the last data load. In the meantime they may have been resolved. Be careful when drawing conclusions from those metrics. They are intended to show a long running engagements that are still in your backlog and are not suitable for real time monitoring.

---

## Links to Salted CX

Source: https://help.salted.cx/en/articles/1781795869-links-to-salted-cx


Article short description

Items in Salted CX have robust deep links that you can use to reference content from 3rd party applications and your documents. You can copy the web address from the URL to reference agents, conversations, and other items within Salted CX.

## [](#new-conversation)New Conversation

To start a new conversation, you just open Salted CX using a link that contains all the necessary information. The user clicking on the link will be taken directly to the conversation, and their engagement time starts.

The format of the link has this format: `https://{account name}.{region}.salted.cx/live/new?channel={channel for the new conversation}&brandId={brand ID from the settings}&contact={contact to the customer}`

![](https://www.notion.so/icons/info-alternate_blue.svg?mode=light)

The parameters must be URL encoded to make sure they do not use special characters.





An example link then looks like this:

`https://yourcompany.eu.salted.cx/live/new?channel=email&brandId=9ed8117d-3a98-4344-97fd-3c2becb5548f&contact=customer%40email.com `

Channel parameter `channel` has these possible values:

- `call`

- `email`

- `sms`

You can find the Brand ID parameter `brandId` in Settings ⏵ Universal Chat.

For contact, you can use any email or phone number of an existing customer in our [Customer Profile](https://help.salted.cx/en/articles/customer-profile), or a new contact and a new customer record will be created on the fly.

The phone numbers should be in ITU-T recommendation E.164 format, including the country code. For example, `+1123456789` (no spaces and special characters, starts with `+` plus sign and contains country code such as `+1` )

---

## Start here with Salted CX

Source: https://help.salted.cx/en/articles/start-here-with-salted-cx


Choose a path through Salted documentation based on your role and the outcome you need, from operating conversations to automation, quality, analytics, and administration.

Start with the customer-service outcome you need, then move from concept to configuration and exact reference. Salted documentation is organized so buyers, operators, human agents, quality teams, analysts, and developers can share one product model without forcing everyone to begin with the same technical detail.

## [](#understand-the-platform)Understand the platform

Use these pages to learn how the main product areas fit together:

- [What is Salted CX?](https://help.salted.cx/en/articles/what-is-salted-cx) explains the complete Salted platform and its adoption models.

- [What are AI Agents in Salted?](https://help.salted.cx/en/articles/what-are-ai-agents-in-salted) explains customer-facing AI Agents.

- [How AI and human agents work together in Salted](https://help.salted.cx/en/articles/how-ai-and-human-agents-work-together-in-salted) explains how AI agents, human agents, and external experts collaborate.

- [Customer conversation lifecycle in Salted](/3a25d3a2a8dc818dbbb1cd7688d35b1b) explains the customer conversation lifecycle.

## [](#operate-customer-conversations)Operate customer conversations

Choose this path when Salted will handle active interactions:

1. Learn what [Live Conversations](https://help.salted.cx/en/collections/1755577083-live-conversations) is.

2. Understand the human workspace in [What is Agent Desktop?](https://help.salted.cx/en/articles/what-is-agent-desktop).

3. Read the human-agent workflow in [Handling Live Conversation](https://help.salted.cx/en/articles/live-conversations-agent).

4. Confirm account, channel, routing, permission, and setup requirements in the linked technical guides.

## [](#build-or-connect-automation)Build or connect automation

Choose this path when you need to control how the conversation responds and acts:

1. Read [How automation logic controls a customer conversation](https://help.salted.cx/en/articles/how-automation-logic-controls-a-customer-conversation) to understand how automation logic controls the conversation.

2. Review the exact [Your Logic Events](https://help.salted.cx/en/articles/your-logic-requests) and [Your Logic Actions](https://help.salted.cx/en/articles/your-logic-actions) contracts.

3. Choose a custom webhook, workflow tool, or [Conversations SDK](/2af5d3a2a8dc80f0a332f9549fc39c79) implementation.

4. Use the implementation, testing, security, and failure-handling guides before production rollout.

In Salted configuration and technical documentation, this automation logic is called Your Logic.

## [](#apply-human-judgment-precisely)Apply human judgment precisely

Choose this path when automation can do most of the work but a person must make or own a consequential decision:

- Start with [How AI and human agents work together in Salted](https://help.salted.cx/en/articles/how-ai-and-human-agents-work-together-in-salted).

- Use [What is Agent Desktop?](https://help.salted.cx/en/articles/what-is-agent-desktop) to understand the human workspace.

- Follow the exact agent-facing question, invitation, routing, and engagement references for implementation.

## [](#improve-service-quality)Improve service quality

Choose this path when you need evaluation, calibration, feedback, or coaching:

- Start with [What is Quality Intelligence?](/3a25d3a2a8dc81ac8576e00cc0c4a5bd).

- Continue into AI-Powered Quality Assurance, manual review, Vitals, Pulse Check, Agent Home, forms, and coaching based on the workflow you need.

- Preserve the conversation evidence behind every score or feedback item.

## [](#investigate-customers-and-operations)Investigate customers and operations

Choose this path when you need to explain a pattern, metric, customer experience, or operational change:

- Start with [What is Conversation Intelligence?](/3a25d3a2a8dc81aea6c2e06ee7946227).

- Use Customer Journey for one customer's history.

- Use Search and Discover to find and quantify patterns.

- Use Ask for natural-language analysis with references.

- Use dashboards, visualizations, and metrics for repeated monitoring and drill-down.

## [](#connect-an-existing-stack)Connect an existing stack

Use the Integrations collection when Salted will ingest conversations, connect channels, receive identity or business data, or operate beside another contact-center platform. Confirm whether each connection supports:

- conversation operation,

- automation events and actions,

- data ingestion only,

- quality and analytics only,

- historical import,

- channel-specific customer delivery.

These are different integration scopes and should not be treated as interchangeable.

## [](#choose-by-role)Choose by role

### [](#cx-or-contact-center-leader)CX or contact-center leader

Start with the platform overview, adoption model, human-AI collaboration, Quality Intelligence, and capability availability.

### [](#automation-owner-or-developer)Automation owner or developer

Start with AI Agents, automation logic, then the exact Your Logic events, actions, SDKs, testing, operational controls, and channel behavior.

### [](#human-agent-or-supervisor)Human agent or supervisor

Start with Live Conversations, Agent Desktop, the agent workflow, queues, help requests, actions, and channel-specific instructions.

### [](#quality-leader-or-team-lead)Quality leader or team lead

Start with Quality Intelligence, AI-Powered QA, Vitals, Pulse Check, Agent Home, forms, and review verification.

### [](#analyst-or-customer-experience-researcher)Analyst or customer-experience researcher

Start with Conversation Intelligence, Customer Journey, Search, Ask, dashboards, visualizations, metrics, and the logical model.

### [](#administrator-or-security-reviewer)Administrator or security reviewer

Start with users, permissions, application settings, identity, data handling, integration setup, and the current capability and maturity scope.

## [](#documentation-depth)Documentation depth

- Concept pages explain what a capability is, why it exists, and how it fits the operating model.

- Configuration guides use the exact labels shown in Salted and explain how to enable or operate a feature.

- Reference pages define exact fields, actions, events, permissions, endpoints, and limits.

Do not substitute a concept page for the technical reference when implementing production behavior.

## [](#availability)Availability

Capabilities and documentation paths vary by account, channel, integration, deployment model, and product maturity. Confirm the current setup and reference pages before making a production commitment.

---