How to send a text or email to customer
This endpoint allows you to send both text messages and emails to customers. The same API endpoint is used for both communication types - you simply change the protocol field and provide the appropriate contact information.
To use this endpoint, you first need your credentials. If you don't already have one, please head over to the Authentication and Authorization page to see how you can request for credentials from us.
- For text messages: Set
protocoltoTEXTand provide a phone number incommunicationValueOfCustomer - For emails: Set
protocoltoEMAILand provide an email address incommunicationValueOfCustomer
Need to find or create a customer first? See how to search and create a customer
Request
HTTP request
POST https://api.mykaarma.com/communications/department/{departmentUUID}/user/{userUuid}/customer/{customerUuid}/message
Parameters
Required path parameters:
| Parameter Name | Value | Description |
|---|---|---|
departmentUUID | string | Unique identifier of dealer department |
userUuid | string | Unique identifier of user ( To prevent delegation of the customer conversation thread from any existing Dealer Associate, use the userUuid of the Default DealerAssociate). If you don't use the Default DealerAssociate userUuid, then the thread will be delegated to the DealerAssociate for which the userUuid has been provided. |
customerUuid | string | Unique identifier of customer |
Authorization
This request requires the following authorization scopes:
| Scope | Level | Description |
|---|---|---|
message.create | DealerDepartment | Authorizes client to send text to customers for the provided user's dealer department |
Request Body
The request body contains two main objects with nested properties:
messageAttributes (Required)
All properties within this object are required.
| Property Name | Type | Description |
|---|---|---|
body | string | Message body of the text/email to be sent out |
isManual | boolean | Whether the message is being sent out manually by a user's action (true) or automatically by a system (false) |
protocol | string | Communication protocol: TEXT for texts or EMAIL for email messages |
type | string | Message direction. Set to OUTGOING for customer communications and INCOMING for dealership communications |
messageSendingAttributes (Optional)
All properties within this object are optional.
| Property Name | Type | Description |
|---|---|---|
communicationValueOfCustomer | string | For TEXT: Phone number in E.164 format (e.g., +11234567890) or 10-digit US format (e.g., 1234567890). Must be a valid phone number registered for the customer in myKaarma.For EMAIL: Valid email address of the customer. If not provided, the system will use the customer's preferred contact method from myKaarma records. |
sendSynchronously | boolean | Default: falseWhen to use true: Set to true when you need immediate confirmation of message delivery and must know right away whether the message was successfully delivered or failed. The API will wait for the third-party service (Twilio/email provider) to respond before returning the result.When to use false: Set to false (recommended for most cases) when immediate delivery confirmation is not required, such as automated messages, bulk communications, or scheduled notifications. The message is queued with automatic retries for better performance, and status updates are sent to your callbackURL if provided. |
callbackURL | string | Your webhook URL to receive delivery status updates when using asynchronous sending (sendSynchronously: false). Required if you need delivery confirmation for async messages. |
callbackMetaData | object | Custom key-value pairs that will be included in the callback payload. Useful for tracking or correlating messages in your system. |
addTCPAFooter | boolean | Default: trueAppends opt-out text (e.g., "Text STOP to opt-out") as configured for the dealership. Applies only to TEXT messages. |
addSignature | boolean | Default: falseAppends the sending user's name (e.g., "-- John Doe") to the message. |
addFooter | boolean | Default: falseAppends the dealership footer configured in myKaarma records. |
sendVCard | boolean | Default: falseSends a vCard (contact card) with the department's phone number. Applies only to TEXT messages. |
queueIfOptedOut | boolean | Default: falseIf set to true, and the phone number is "not explicitly opted-in/opted-out" yet, the message will be queued for delivery and sent when the customer opts in within the configured timeout period (default is 1 day, can be configured in the dealership's settings for myKaarma). |
Examples
Example 1: Sending a Text Message
This example demonstrates sending a text message to a customer with common options enabled.
curl --location --request POST 'https://api.mykaarma.com/communications/department/{{departmentUUID}}/user/{{userUuid}}/customer/{{customerUuid}}/message' \
--header 'accept: application/json' \
-u "{{username}}:{{password}}" \
--header 'Content-Type: application/json' \
--data-raw '{
"messageAttributes": {
"body": "Hi John, your vehicle service appointment is confirmed for tomorrow at 10 AM. See you then!",
"isManual": true,
"protocol": "TEXT",
"type": "OUTGOING"
},
"messageSendingAttributes": {
"communicationValueOfCustomer": "1234567890",
"sendSynchronously": false,
"callbackURL": "https://your-domain.com/webhook/message-status",
"callbackMetaData": {
"appointmentId": "12345",
"source": "appointment-reminder"
},
"addTCPAFooter": true,
"addSignature": true,
"addFooter": false,
"sendVCard": false
}
}'
Expected Result: Customer receives text message:
Hi John, your vehicle service appointment is confirmed for tomorrow at 10 AM. See you then!
-- Sarah Johnson
Text STOP to opt-out
Example 2: Sending an Email
This example demonstrates sending an email to a customer.
curl --location --request POST 'https://api.mykaarma.com/communications/department/{{departmentUUID}}/user/{{userUuid}}/customer/{{customerUuid}}/message' \
--header 'accept: application/json' \
-u "{{username}}:{{password}}" \
--header 'Content-Type: application/json' \
--data-raw '{
"messageAttributes": {
"body": "Dear John,\n\nThank you for choosing our service center. Your vehicle service has been completed.\n\nService Details:\n- Oil Change\n- Tire Rotation\n- Multi-point Inspection\n\nTotal: $89.99\n\nPlease feel free to contact us if you have any questions.\n\nBest regards,\nService Team",
"isManual": false,
"protocol": "EMAIL",
"type": "OUTGOING"
},
"messageSendingAttributes": {
"communicationValueOfCustomer": "customer@example.com",
"sendSynchronously": false,
"callbackURL": "https://your-domain.com/webhook/email-status",
"callbackMetaData": {
"serviceOrderId": "SO-67890",
"communicationType": "service-completion"
},
"addTCPAFooter": false,
"addSignature": true,
"addFooter": true,
"sendVCard": false
}
}'
Example 3: Synchronous Sending (with immediate delivery confirmation)
Use this when you need to know immediately whether the message was successfully delivered or failed, and must display or act on that delivery status right away.
curl --location --request POST 'https://api.mykaarma.com/communications/department/{{departmentUUID}}/user/{{userUuid}}/customer/{{customerUuid}}/message' \
--header 'accept: application/json' \
-u "{{username}}:{{password}}" \
--header 'Content-Type: application/json' \
--data-raw '{
"messageAttributes": {
"body": "Your verification code is: 123456. This code will expire in 5 minutes.",
"isManual": false,
"protocol": "TEXT",
"type": "OUTGOING"
},
"messageSendingAttributes": {
"communicationValueOfCustomer": "+11234567890",
"sendSynchronously": true,
"addTCPAFooter": false,
"addSignature": false,
"addFooter": false,
"sendVCard": false
}
}'
- Phone Number Format: Accepts E.164 format (
+11234567890) or 10-digit US format (1234567890) - Email Validation: Email addresses must be valid and registered for the customer in myKaarma
- Asynchronous vs Synchronous Sending:
- Use
sendSynchronously: false(default, recommended) when immediate delivery confirmation is not needed - provides better performance with automatic retries and background processing. Ideal for automated messages, bulk communications, and scheduled notifications - Use
sendSynchronously: trueonly when you must know immediately if the message was delivered or failed, and need to display or act on that status right away
- Use
- TCPA Compliance:
addTCPAFooterdefaults totruefor TEXT messages to ensure compliance with telemarketing regulations - Opt out related notes (For TEXT messages):
- We have an opt-out feature where customers can opt out of receiving TEXT messages from myKaarma.
- When a customer's new phone number is added from APIs (i.e. didn't come from DMS), that phone number is considered as not opted in of texting by default.
- In the above mentioned case, if
queueIfOptedOutis set totrue, the message will be queued for delivery and sent when the customer opts in within the configured timeout period (default is 1 day, can be configured in the dealership's settings for myKaarma). - If a customer explicitly opts out of receiving TEXT messages on a phone number, that phone number will not receive any TEXT messages from myKaarma.
- The message sent/failed status will be sent in the callback when attempted later from the queue.
- In case of expiry of a message request from queue, there's no callback to notify about it at the moment.
Response
{
"customerUUID": "string",
"errors": [
{
"errorCode": "string",
"errorDescription": "string",
"errorUID": "string"
}
],
"messageUUID": "string",
"metaData": {
"additionalProp1": "string"
},
"requestUUID": "string",
"status": "SUCCESS",
"warnings": [
{
"warningCode": "string",
"warningDescription": "string"
}
]
}
Callbacks
When sendSynchronously is set to false (default), the API processes the message asynchronously. You will receive a callback notification at your provided callbackURL when the message status changes (e.g., sent, failed), with the same messageUUID that was returned in the initial API request.
Callback Triggers
Callbacks are sent in the following scenarios:
- Success: When asynchronous message was submitted to provider and later (for both synchronous and asynchronous) when we receive confirmation the message was successfully delivered by the provider (Twilio/Postmark).
- Opt-Out: The customer has opted out (and queuing is not applicable).
- Rate Limit: Sending limits have been exceeded.
- Provider Error: The downstream provider (Twilio/Postmark/Cellular Carrier/IMAP Server) rejected the message.
- Internal Error: An unexpected server error occurred.
Callbacks are NOT sent for:
- Validation Errors: If the request fails initial validation (e.g., missing required fields), the API returns a
400 Bad Requestresponse synchronously. - Synchronous Requests: If
sendSynchronouslyistrue, the final status is returned in the API response. And only carrier delivery updates are published later via callback.
Callback Payload
The callback sends a JSON payload identical to the SendMessageResponse structure:
{
"customerUUID": "string",
"messageUUID": "string",
"status": "SUCCESS" | "FAILURE",
"errors": [
{
"errorCode": "string",
"errorDescription": "string",
"errorUID": "string"
}
],
"warnings": [
{
"warningCode": "string",
"warningDescription": "string"
}
],
"metaData": {
// Key-value pairs from your request's 'callbackMetaData'
"your_custom_key": "your_custom_value"
}
}
Error Codes
The following error codes may be returned in the errors array of the response or callback.
Common Errors
| Error Code | Description |
|---|---|
MISSING_MESSAGE_ATTRIBUTES | Request body is missing messageAttributes. |
INVALID_USER | The userUuid is invalid. |
MISSING_MESSAGE_TYPE | messageAttributes.type is missing. |
MISSING_MESSAGE_PROTOCOL | messageAttributes.protocol is missing. |
MISSING_IS_MANUAL | messageAttributes.isManual is missing. |
MISSING_MESSAGE_BODY | Message body is missing (and no attachments provided). |
INVALID_COMMUNICATION_VALUE | Phone number/email is invalid, not found for customer, or mismatches the label. |
OPTED_OUT_COMMUNICATION_VALUE | Customer has opted out of communication. |
COMMUNICATION_VALUE_MARKED_AS_NOT_OK_TO_COMMUNICATE | Specific phone/email is marked as "not ok to communicate". |
USER_DOES_NOT_HAVE_AUTHORITY | User lacks permission to send this message type. |
CUSTOMER_LOCKED | Customer is currently locked by another user. |
RATE_LIMIT_REACHED | Sending limit exceeded for this recipient. |
INTERNAL_SERVER_ERROR | Unexpected server error. |
INVALID_CUSTOMER | The customerUuid is invalid. |
Text-Specific Errors
| Error Code | Description |
|---|---|
TWILIO_SENDING_FAILURE | Provider failed to send Text (e.g., invalid number, unreachable). |
MISSING_VOICE_CREDENTIALS | No valid sender number found for the dealership. |
MESSAGE_SEND_LOCK_NOT_OBTAINED | Could not lock the message for processing. |
Email-Specific Errors
| Error Code | Description |
|---|---|
MISSING_DEALER_EMAIL | Dealer has no configured sender email. |
INVALID_EMAIL_ADDRESS | Recipient email is malformed or rejected. |
BLACKLISTED_EMAIL_ADDRESS_OR_DOMAIN | Recipient email/domain is blacklisted. |
Warning Codes
Warnings indicate non-critical issues where the message may still be processed.
| Warning Code | Description |
|---|---|
INVALID_EMAIL | Invalid email in CC/BCC list (skipped). |
DO_NOT_CC_ENABLED | Email skipped from CC list because "Do Not CC" is enabled. |
BLACKLISTED_EMAIL_DOMAIN | Email skipped from CC/BCC list due to blacklisted domain. |
CANT_OVERRIDE_OPTOUT | Cannot override opt-out rules (insufficient privileges). |
CANT_QUEUE_MESSAGE_IF_OPTED_OUT | Queuing not supported for this message type. |