Skip to contentSkip to navigationSkip to topbar
Page tools
Useful for sharing or LLM
Accelerate development with AI

On this page
Looking for more inspiration?Visit the

Conversation metadata


Metadata lets you store your own key-value data on a conversation, where it stays for the life of that conversation and is available to anything that reads the conversation.

A conversation rarely carries everything you need to act on it. The account it belongs to might live only in your CRM. The intent a Conversation Intelligence operator resolves isn't known until partway through the conversation. The escalation tier you want this conversation to follow is a decision you make, not a fact Twilio knows. Metadata is where you put any of it.

Metadata is a field on the Conversation resource. Set it when you create a conversation, update it as the conversation progresses, or both.

(information)

Metadata on capture rules is a different field

Capture rules also take a metadata field, which holds channel-specific filters such as voice callType. That field controls which traffic a rule matches and is unrelated to the conversation metadata described on this page. See Ingestion modes.


What to store in Conversation metadata

what-to-store-in-conversation-metadata page anchor

Metadata suits three kinds of data.

Use caseWhat you storeExamplesWhat it unlocks
External referencesYour foreign keys into other systemsA CRM contact ID, a billing account, an agent IDReporting that lines up conversations with the records you already maintain
Derived stateA conclusion reached during the conversation, such as a real-time language operator result your application writes backA resolved intent, a qualification status, a risk flag
  • Tiered intelligence, where one operator's result decides whether and how another operator runs on the next communication
  • A human agent who inherits the case context from the AI
Per-conversation configurationA toggle that changes behavior for one conversation without a code changeAn escalation tier, a prompt versionOne set of logic that adapts per conversation, instead of one deployment per variant

Metadata isn't a general-purpose datastore. Values are short strings, and each conversation holds at most eight keys, so store identifiers and small pieces of state rather than records or transcripts. If you need more room, keep the record in your own system and store its identifier in metadata. For the exact caps, see Limits.

(warning)

Don't store sensitive information in metadata

Never put payment card details, credentials, government identifiers, or protected health information in metadata. Store an identifier that points to that data in a system built to hold it, and keep the data itself out of the conversation.


Set metadata when you create a conversation

set-metadata-when-you-create-a-conversation page anchor

Include a metadata object when you create the conversation. Record what you already know at that point, such as which of your records the conversation concerns:

Create conversation with metadataLink to code sample: Create conversation with metadata
1
// Download the helper library from https://www.twilio.com/docs/node/install
2
const twilio = require("twilio"); // Or, for ESM: import twilio from "twilio";
3
4
// Find your Account SID at twilio.com/console
5
// Provision API Keys at twilio.com/console/runtime/api-keys
6
// and set the environment variables. See http://twil.io/secure
7
// For local testing, you can use your Account SID and Auth token
8
const accountSid = process.env.TWILIO_ACCOUNT_SID;
9
const apiKey = process.env.TWILIO_API_KEY;
10
const apiSecret = process.env.TWILIO_API_SECRET;
11
const client = twilio(apiKey, apiSecret, { accountSid: accountSid });
12
13
async function createConversationWithConfig() {
14
const conversation = await client.conversations.v2.conversations.create({
15
configurationId: "YOUR_CONFIGURATION_ID",
16
name: "Leasing inquiry",
17
metadata: {
18
property_id: "prop_8842",
19
campaign_id: "spring_2026",
20
},
21
});
22
23
console.log(conversation.id);
24
}
25
26
createConversationWithConfig();

Response

Note about this response
1
{
2
"id": "conv_conversation_00000000000000000000000001",
3
"accountId": "ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
4
"configurationId": "conv_configuration_00000000000000000000000001",
5
"status": "ACTIVE",
6
"name": "Leasing inquiry",
7
"createdAt": "2023-07-01T12:00:00Z",
8
"updatedAt": "2023-07-01T12:30:00Z",
9
"metadata": {
10
"property_id": "prop_8842",
11
"campaign_id": "spring_2026"
12
}
13
}

The conversation now carries the metadata you provided when creating it.

For the full conversation creation flow, including participants, see Create conversations programmatically.


A GET request returns metadata along with everything else about the conversation:

1
// Download the helper library from https://www.twilio.com/docs/node/install
2
const twilio = require("twilio"); // Or, for ESM: import twilio from "twilio";
3
4
// Find your Account SID at twilio.com/console
5
// Provision API Keys at twilio.com/console/runtime/api-keys
6
// and set the environment variables. See http://twil.io/secure
7
// For local testing, you can use your Account SID and Auth token
8
const accountSid = process.env.TWILIO_ACCOUNT_SID;
9
const apiKey = process.env.TWILIO_API_KEY;
10
const apiSecret = process.env.TWILIO_API_SECRET;
11
const client = twilio(apiKey, apiSecret, { accountSid: accountSid });
12
13
async function fetchConversation() {
14
const conversation = await client.conversations.v2
15
.conversations("YOUR_CONVERSATION_ID")
16
.fetch();
17
18
console.log(conversation.id);
19
}
20
21
fetchConversation();

The following response is abbreviated to the fields most relevant to metadata:

1
{
2
"id": "conv_conversation_01k1etk2y5f1y9fpe2epfdtvv2",
3
"configurationId": "conv_configuration_01k1etk2y5f1y9fpe2epfdtvv2",
4
"name": "Leasing inquiry",
5
"status": "ACTIVE",
6
"createdAt": "2026-09-18T14:30:00Z",
7
"updatedAt": "2026-09-18T14:32:11Z",
8
"metadata": {
9
"property_id": "prop_8842",
10
"campaign_id": "spring_2026"
11
}
12
}

Update metadata during a conversation

update-metadata-during-a-conversation page anchor

To change metadata on an existing conversation, make a PATCH request with only the keys you want to change:

1
// Download the helper library from https://www.twilio.com/docs/node/install
2
const twilio = require("twilio"); // Or, for ESM: import twilio from "twilio";
3
4
// Find your Account SID at twilio.com/console
5
// Provision API Keys at twilio.com/console/runtime/api-keys
6
// and set the environment variables. See http://twil.io/secure
7
// For local testing, you can use your Account SID and Auth token
8
const accountSid = process.env.TWILIO_ACCOUNT_SID;
9
const apiKey = process.env.TWILIO_API_KEY;
10
const apiSecret = process.env.TWILIO_API_SECRET;
11
const client = twilio(apiKey, apiSecret, { accountSid: accountSid });
12
13
async function patchConversationById() {
14
const conversation = await client.conversations.v2
15
.conversations("YOUR_CONVERSATION_ID")
16
.patch({
17
metadata: {
18
resolved_intent: "schedule_tour",
19
},
20
});
21
22
console.log(conversation.id);
23
}
24
25
patchConversationById();

PATCH merges your changes into the metadata already on the conversation:

  • Include a key to add it, or to update it if it already exists.
  • Set a key to null to remove it.
  • Leave a key out to keep its current value.
(warning)

PUT replaces metadata instead of merging it

A PUT request replaces the conversation's metadata with exactly what you send, so every key you leave out is removed. Use PATCH to change individual keys and leave the rest in place.

The request above sends one key, and the conversation keeps the two it already had:

1
{
2
"metadata": {
3
"property_id": "prop_8842",
4
"campaign_id": "spring_2026",
5
"resolved_intent": "schedule_tour"
6
}
7
}

Because unmentioned keys are preserved, sending an empty metadata object changes nothing. To clear metadata, set each key you want to remove to null.

A conversation only accepts metadata changes while it is open. Once it reaches the CLOSED state, a PATCH request returns a 400 response, so write any value you need before the conversation ends. For when that happens, see Conversation lifecycle.

Remove a key

remove-a-key page anchor

To free a slot, set the key to null:

1
// Download the helper library from https://www.twilio.com/docs/node/install
2
const twilio = require("twilio"); // Or, for ESM: import twilio from "twilio";
3
4
// Find your Account SID at twilio.com/console
5
// Provision API Keys at twilio.com/console/runtime/api-keys
6
// and set the environment variables. See http://twil.io/secure
7
// For local testing, you can use your Account SID and Auth token
8
const accountSid = process.env.TWILIO_ACCOUNT_SID;
9
const apiKey = process.env.TWILIO_API_KEY;
10
const apiSecret = process.env.TWILIO_API_SECRET;
11
const client = twilio(apiKey, apiSecret, { accountSid: accountSid });
12
13
async function patchConversationById() {
14
const conversation = await client.conversations.v2
15
.conversations("YOUR_CONVERSATION_ID")
16
.patch({
17
metadata: {
18
campaign_id: null,
19
},
20
});
21
22
console.log(conversation.id);
23
}
24
25
patchConversationById();

You can't rename keys in place. Remove the old key and set the new one in the same request, so the value is never missing between requests:

1
// Download the helper library from https://www.twilio.com/docs/node/install
2
const twilio = require("twilio"); // Or, for ESM: import twilio from "twilio";
3
4
// Find your Account SID at twilio.com/console
5
// Provision API Keys at twilio.com/console/runtime/api-keys
6
// and set the environment variables. See http://twil.io/secure
7
// For local testing, you can use your Account SID and Auth token
8
const accountSid = process.env.TWILIO_ACCOUNT_SID;
9
const apiKey = process.env.TWILIO_API_KEY;
10
const apiSecret = process.env.TWILIO_API_SECRET;
11
const client = twilio(apiKey, apiSecret, { accountSid: accountSid });
12
13
async function patchConversationById() {
14
const conversation = await client.conversations.v2
15
.conversations("YOUR_CONVERSATION_ID")
16
.patch({
17
metadata: {
18
campaign_id: null,
19
campaign_ref: "spring_2026",
20
},
21
});
22
23
console.log(conversation.id);
24
}
25
26
patchConversationById();

Receive metadata changes in webhooks

receive-metadata-changes-in-webhooks page anchor

Every metadata change emits a CONVERSATION_UPDATED webhook event. Your other systems can react to a write instead of polling for one.

The event carries the full conversation, metadata included, so a handler reads the new values directly off the payload without fetching the conversation first:

1
{
2
"eventType": "CONVERSATION_UPDATED",
3
"timestamp": "2026-09-18T14:32:11.254049339Z",
4
"data": {
5
"id": "conv_conversation_01k1etk2y5f1y9fpe2epfdtvv2",
6
"metadata": {
7
"property_id": "prop_8842",
8
"resolved_intent": "schedule_tour"
9
},
10
"status": "ACTIVE"
11
}
12
}

Note the contrast with PATCH. A request sends only the keys you want to change, but the event carries the whole metadata object, so a handler always sees current state. To work out what changed, compare against the values you held before.

Metadata is also included on CONVERSATION_CREATED, so values you set at creation reach your handler in the first event about that conversation. For the full payload structure, see Webhooks.


  • A conversation holds at most eight metadata keys.
  • Keys can be up to 128 characters and must match the regular expression ^[a-zA-Z0-9._-]+$, which allows letters, numbers, periods, underscores, and hyphens. The API rejects any other character, including spaces.
  • Values must be strings of up to 512 characters. To store a number, such as a loan amount, write it as a string.
  • Keys cannot be renamed in place. To change a key, remove it and set the new one in the same request.
  • Twilio encrypts metadata values at rest. Even so, do not store sensitive information in metadata.
  • Metadata cannot change after a conversation reaches the CLOSED state. A PATCH request to a closed conversation returns a 400 response.
  • Metadata belongs to a single conversation. Twilio does not share it between conversations or copy it to a new conversation when one ends.