OpenAPI Spec
Machine-readable spec for the Conversations API: stable/categories/conversations.json
Before you begin
Check out our general API overview to make sure you're ready to get started with specific endpoints.
Access required
The Conversations API is available to approved accounts and apps only. To request access, submit this form. Access is granted either at the account level (for customers using a private API key) or at the OAuth app level (for approved partners whose app is allow-listed across their install base).
For a walkthrough of authentication, scopes, and sending your first message, see Get started with the Conversations API.
The Conversations API allows approved partners and businesses to send and retrieve conversation messages programmatically within the Klaviyo platform. It supports SMS and WhatsApp channels ā the channel is determined automatically based on the conversation. This enables help desk and customer support integrations to participate in two-way conversations on behalf of Klaviyo accounts, using the account's existing Klaviyo sending number.
Use cases
Here are example use cases supported by the Conversations API:
- Integrate a helpdesk platform (e.g., Kustomer, Zowie, Crisp) so that support agents can reply to inbound SMS and WhatsApp messages from within their existing tooling.
- Build a custom support workflow that routes inbound messages to an internal queue and sends outbound replies via API.
- Retrieve a profile's full conversation history for context before responding.
Required scopes
To use Conversations API endpoints, your OAuth app will need the following scopes:
conversations:writeā required to send conversation messagesconversations:readā required to retrieve conversation historyprofiles:readā required to retrieve conversation history via the Profiles API
Data model
Conversation message
The conversation-message resource represents a single message sent within a conversation thread. It has the following fields:
body(attribute, required) ā the text content of the message.conversation(relationship, required) ā the conversation thread to send the message to.
Conversation
The conversation resource identifies a single SMS or WhatsApp conversation thread between a Klaviyo account and a profile ā it has the following fields, but not the messages themselves:
channel(attribute) āsmsorwhatsapp.profile(relationship) ā the profile this conversation belongs to.
A profile can have more than one conversation ā one per channel. Conversations can be retrieved directly via Get Conversations for Profile or included inline on a profile response using ?include=conversations. To read the messages exchanged in a conversation, use the Events API (Sent SMS/Received SMS or Sent WhatsApp/Received WhatsApp events).
Endpoint change
Earlier API revisions exposed a singular
GET /api/profiles/{id}/conversation, which returned a single conversation for a profile. As of revision2026-07-15, use the pluralGET /api/profiles/{id}/conversationsdocumented below ā it returns all of a profile's conversations across channels, each with achannelattribute.
How conversations are created
Conversations are created automatically by Klaviyo when a profile sends an inbound message ā a customer texting your Klaviyo SMS number, or a customer messaging your WhatsApp Business number. There is no public API endpoint to create a conversation; one must already exist before you can send a reply.
This means:
- SMS: A conversation exists once a customer has texted your Klaviyo sending number.
- WhatsApp: A conversation exists once a customer has messaged your WhatsApp Business number. You cannot initiate a new WhatsApp conversation via API ā the customer must message first.
Before calling Create Conversation Message, retrieve the conversation_id for the profile using Get Conversations for Profile and select the entry for the channel you're replying on. The conversation_id determines the channel ā no channel field is needed in the request body.
Send a conversation message
Use Create Conversation Message to send an outbound message to a profile. The channel (SMS or WhatsApp) is determined automatically from the conversation_id ā you do not specify the channel in the request.
Required fields
-
conversation (relationship, required)
The conversation to reply to. Use Get Conversations for Profile to retrieve the
conversation_idfor a profile. The channel (SMS or WhatsApp) is determined automatically from the conversation. -
body (required)
The text content of the message. Maximum length is 1,600 characters for SMS and 1,024 characters for WhatsApp.
Example request
{
"data": {
"type": "conversation-message",
"attributes": {
"body": "Hi! Thanks for reaching out. How can we help you today?"
},
"relationships": {
"conversation": {
"data": {
"type": "conversation",
"id": "CONVERSATION_ID"
}
}
}
}
}
A successful response returns 202 Accepted with the created conversation-message object, including the message id.
Retrieve conversation IDs
Use Get Conversations for Profile to retrieve the conversation ID for each of a profile's channels. This returns conversation objects ā id, channel, and a relationship to the profile ā not the messages exchanged in the conversation. To read message content, use the Events API (Sent SMS/Received SMS or Sent WhatsApp/Received WhatsApp events).
curl --request GET \
'https://a.klaviyo.com/api/profiles/PROFILE_ID/conversations' \
--header 'Authorization: Bearer YOUR_OAUTH_ACCESS_TOKEN' \
--header 'revision: 2026-07-15'
You can also include conversations inline when retrieving a profile using the include query parameter:
curl --request GET \
'https://a.klaviyo.com/api/profiles/PROFILE_ID?include=conversations' \
--header 'Authorization: Bearer YOUR_OAUTH_ACCESS_TOKEN' \
--header 'revision: 2026-07-15'
Using webhooks to detect inbound messages
To reply to inbound messages in real time, subscribe to the event:klaviyo.sent_sms webhook topic using the Webhooks API. Despite the name, this event fires when a customer sends an SMS to your Klaviyo sending number ā i.e., an inbound message that creates or continues a conversation. (The naming reflects the customer's action of sending, not Klaviyo's.)
There is currently no equivalent webhook topic for inbound WhatsApp messages. If you are building a WhatsApp integration, you will need to poll Get Conversations for Profile to detect new inbound messages.
When an event:klaviyo.sent_sms webhook fires, the payload includes the Klaviyo profile ID of the sender:
{
"data": {
"type": "event",
"attributes": {
"event_properties": {
"From Number": "+18108675309",
"Message Body": "Hello, I need help with my order!"
}
},
"relationships": {
"profile": {
"data": {
"type": "profile",
"id": "PROFILE_ID"
}
}
}
},
"topic": "event:klaviyo.sent_sms"
}
The webhook payload does not include the conversation_id. Use the profile ID to retrieve it:
curl --request GET \
'https://a.klaviyo.com/api/profiles/PROFILE_ID/conversations' \
--header 'Authorization: Bearer YOUR_OAUTH_ACCESS_TOKEN' \
--header 'revision: 2026-07-15'
Then use the returned conversation_id to send your reply with Create Conversation Message.
Full integration flow
- Subscribe to
event:klaviyo.sent_smsvia the Webhooks API. - When a webhook fires, extract
relationships.profile.data.idfrom the payload. - Call
GET /api/profiles/{id}/conversationsto retrieve theconversation_idfor the relevant channel. - Call
POST /api/conversation-messageswith theconversation_idand your replybody.
Rate limits
Conversations API endpoints use the SMALL rate limit tier: 3 requests/second burst and 60 requests/minute steady. See rate limits for more information.
Limitations
- Only outbound messages can be sent via this API. Inbound messages (received from a profile) are accessible in the conversation history but cannot be created via API.
- Maximum message body length: 1,600 characters for SMS, 1,024 characters for WhatsApp.
- The profile must have a valid, consented phone number on the relevant channel. Attempting to send to a profile without consent will return a 400 error.
- The Klaviyo account must have the relevant channel (SMS or WhatsApp) configured and an active sending number.
- Access is gated at the OAuth app level or account level. See Before you begin for details on requesting access.
Troubleshooting
| Status code | Reasons |
|---|---|
| 400 | Missing or empty body. Missing conversation relationship. Conversation not found or blocked. Customer does not exist. Profile does not have consent on the relevant channel. |
| 401 | Missing or invalid API key or OAuth access token. |
| 403 | OAuth app is not on the allow-list, or the account has been blocked from the Conversations API. Account not configured to send SMS. Insufficient funds. WhatsApp not enabled for the account. |
| 413 | Message body exceeds the maximum length (1,600 characters for SMS, 1,024 characters for WhatsApp). |
| 429 | Rate limit exceeded. See rate limits. |