curl --request POST \
--url https://partner-api.getoliver.com/services/core/open_api/v1/messages \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'X-Client-Id: <x-client-id>' \
--data '
{
"recipient": {
"client_id": "0b0e5a54-7c1f-4a43-9d4e-2f3c7d0d1a11",
"phone_number": "+15125551234"
},
"fallback_text": "Hi! Millie has preventive care due October 21-22. Book here: https://vet.example.com/book or call us at (512) 555-0100.",
"channel": "auto",
"reference_id": "inv-reminder-88412",
"callback_url": "<string>"
}
'import requests
url = "https://partner-api.getoliver.com/services/core/open_api/v1/messages"
payload = {
"recipient": {
"client_id": "0b0e5a54-7c1f-4a43-9d4e-2f3c7d0d1a11",
"phone_number": "+15125551234"
},
"fallback_text": "Hi! Millie has preventive care due October 21-22. Book here: https://vet.example.com/book or call us at (512) 555-0100.",
"channel": "auto",
"reference_id": "inv-reminder-88412",
"callback_url": "<string>"
}
headers = {
"X-Client-Id": "<x-client-id>",
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'X-Client-Id': '<x-client-id>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
recipient: {
client_id: '0b0e5a54-7c1f-4a43-9d4e-2f3c7d0d1a11',
phone_number: '+15125551234'
},
fallback_text: 'Hi! Millie has preventive care due October 21-22. Book here: https://vet.example.com/book or call us at (512) 555-0100.',
channel: 'auto',
reference_id: 'inv-reminder-88412',
callback_url: '<string>'
})
};
fetch('https://partner-api.getoliver.com/services/core/open_api/v1/messages', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://partner-api.getoliver.com/services/core/open_api/v1/messages",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'recipient' => [
'client_id' => '0b0e5a54-7c1f-4a43-9d4e-2f3c7d0d1a11',
'phone_number' => '+15125551234'
],
'fallback_text' => 'Hi! Millie has preventive care due October 21-22. Book here: https://vet.example.com/book or call us at (512) 555-0100.',
'channel' => 'auto',
'reference_id' => 'inv-reminder-88412',
'callback_url' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json",
"X-Client-Id: <x-client-id>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://partner-api.getoliver.com/services/core/open_api/v1/messages"
payload := strings.NewReader("{\n \"recipient\": {\n \"client_id\": \"0b0e5a54-7c1f-4a43-9d4e-2f3c7d0d1a11\",\n \"phone_number\": \"+15125551234\"\n },\n \"fallback_text\": \"Hi! Millie has preventive care due October 21-22. Book here: https://vet.example.com/book or call us at (512) 555-0100.\",\n \"channel\": \"auto\",\n \"reference_id\": \"inv-reminder-88412\",\n \"callback_url\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-Client-Id", "<x-client-id>")
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://partner-api.getoliver.com/services/core/open_api/v1/messages")
.header("X-Client-Id", "<x-client-id>")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"recipient\": {\n \"client_id\": \"0b0e5a54-7c1f-4a43-9d4e-2f3c7d0d1a11\",\n \"phone_number\": \"+15125551234\"\n },\n \"fallback_text\": \"Hi! Millie has preventive care due October 21-22. Book here: https://vet.example.com/book or call us at (512) 555-0100.\",\n \"channel\": \"auto\",\n \"reference_id\": \"inv-reminder-88412\",\n \"callback_url\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://partner-api.getoliver.com/services/core/open_api/v1/messages")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-Client-Id"] = '<x-client-id>'
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"recipient\": {\n \"client_id\": \"0b0e5a54-7c1f-4a43-9d4e-2f3c7d0d1a11\",\n \"phone_number\": \"+15125551234\"\n },\n \"fallback_text\": \"Hi! Millie has preventive care due October 21-22. Book here: https://vet.example.com/book or call us at (512) 555-0100.\",\n \"channel\": \"auto\",\n \"reference_id\": \"inv-reminder-88412\",\n \"callback_url\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"data": {
"id": "<string>",
"reference_id": "<string>",
"status": "sent",
"status_reason": "<string>",
"channel_requested": "auto",
"channel_used": "rcs",
"client_id": "<string>",
"error_code": "<string>",
"error_message": "<string>",
"sent_at": "2023-11-07T05:31:56Z",
"delivered_at": "2023-11-07T05:31:56Z",
"read_at": "2023-11-07T05:31:56Z",
"failed_at": "2023-11-07T05:31:56Z",
"created_at": "2023-11-07T05:31:56Z"
},
"message": "<string>"
}{
"success": true,
"data": {
"id": "<string>",
"reference_id": "<string>",
"status": "sent",
"status_reason": "<string>",
"channel_requested": "auto",
"channel_used": "rcs",
"client_id": "<string>",
"error_code": "<string>",
"error_message": "<string>",
"sent_at": "2023-11-07T05:31:56Z",
"delivered_at": "2023-11-07T05:31:56Z",
"read_at": "2023-11-07T05:31:56Z",
"failed_at": "2023-11-07T05:31:56Z",
"created_at": "2023-11-07T05:31:56Z"
},
"message": "<string>"
}{
"success": false,
"message": "content.card.buttons must have at most 4 items",
"data": {
"message": "<string>",
"errors": [
{
"field": "content.card.buttons",
"message": "must have at most 4 items"
}
]
}
}{
"success": true,
"message": "<string>",
"data": {}
}{
"success": true,
"message": "<string>",
"data": {}
}{
"success": true,
"message": "<string>",
"data": {}
}{
"success": true,
"message": "<string>",
"data": {}
}Send a Message
Send one message to a client: rich RCS content (a card, carousel, image, or text with suggested replies and actions) with SMS fallback text, which is required. The message appears in the practice’s Oliver inbox like any other text, and clients who opted out are never texted.
Messages are sent immediately, never queued. Send only during the practice’s sending hours, 8am to 9pm clinic time; outside them the request returns 400 and nothing is sent.
An opted-out recipient is not an error: it returns 200 with status: "suppressed". Invalid input returns 400 with every problem in data.errors. If the messaging provider is briefly unavailable you get 502; retry with the same reference_id.
curl --request POST \
--url https://partner-api.getoliver.com/services/core/open_api/v1/messages \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'X-Client-Id: <x-client-id>' \
--data '
{
"recipient": {
"client_id": "0b0e5a54-7c1f-4a43-9d4e-2f3c7d0d1a11",
"phone_number": "+15125551234"
},
"fallback_text": "Hi! Millie has preventive care due October 21-22. Book here: https://vet.example.com/book or call us at (512) 555-0100.",
"channel": "auto",
"reference_id": "inv-reminder-88412",
"callback_url": "<string>"
}
'import requests
url = "https://partner-api.getoliver.com/services/core/open_api/v1/messages"
payload = {
"recipient": {
"client_id": "0b0e5a54-7c1f-4a43-9d4e-2f3c7d0d1a11",
"phone_number": "+15125551234"
},
"fallback_text": "Hi! Millie has preventive care due October 21-22. Book here: https://vet.example.com/book or call us at (512) 555-0100.",
"channel": "auto",
"reference_id": "inv-reminder-88412",
"callback_url": "<string>"
}
headers = {
"X-Client-Id": "<x-client-id>",
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'X-Client-Id': '<x-client-id>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
recipient: {
client_id: '0b0e5a54-7c1f-4a43-9d4e-2f3c7d0d1a11',
phone_number: '+15125551234'
},
fallback_text: 'Hi! Millie has preventive care due October 21-22. Book here: https://vet.example.com/book or call us at (512) 555-0100.',
channel: 'auto',
reference_id: 'inv-reminder-88412',
callback_url: '<string>'
})
};
fetch('https://partner-api.getoliver.com/services/core/open_api/v1/messages', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://partner-api.getoliver.com/services/core/open_api/v1/messages",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'recipient' => [
'client_id' => '0b0e5a54-7c1f-4a43-9d4e-2f3c7d0d1a11',
'phone_number' => '+15125551234'
],
'fallback_text' => 'Hi! Millie has preventive care due October 21-22. Book here: https://vet.example.com/book or call us at (512) 555-0100.',
'channel' => 'auto',
'reference_id' => 'inv-reminder-88412',
'callback_url' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json",
"X-Client-Id: <x-client-id>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://partner-api.getoliver.com/services/core/open_api/v1/messages"
payload := strings.NewReader("{\n \"recipient\": {\n \"client_id\": \"0b0e5a54-7c1f-4a43-9d4e-2f3c7d0d1a11\",\n \"phone_number\": \"+15125551234\"\n },\n \"fallback_text\": \"Hi! Millie has preventive care due October 21-22. Book here: https://vet.example.com/book or call us at (512) 555-0100.\",\n \"channel\": \"auto\",\n \"reference_id\": \"inv-reminder-88412\",\n \"callback_url\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-Client-Id", "<x-client-id>")
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://partner-api.getoliver.com/services/core/open_api/v1/messages")
.header("X-Client-Id", "<x-client-id>")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"recipient\": {\n \"client_id\": \"0b0e5a54-7c1f-4a43-9d4e-2f3c7d0d1a11\",\n \"phone_number\": \"+15125551234\"\n },\n \"fallback_text\": \"Hi! Millie has preventive care due October 21-22. Book here: https://vet.example.com/book or call us at (512) 555-0100.\",\n \"channel\": \"auto\",\n \"reference_id\": \"inv-reminder-88412\",\n \"callback_url\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://partner-api.getoliver.com/services/core/open_api/v1/messages")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-Client-Id"] = '<x-client-id>'
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"recipient\": {\n \"client_id\": \"0b0e5a54-7c1f-4a43-9d4e-2f3c7d0d1a11\",\n \"phone_number\": \"+15125551234\"\n },\n \"fallback_text\": \"Hi! Millie has preventive care due October 21-22. Book here: https://vet.example.com/book or call us at (512) 555-0100.\",\n \"channel\": \"auto\",\n \"reference_id\": \"inv-reminder-88412\",\n \"callback_url\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"data": {
"id": "<string>",
"reference_id": "<string>",
"status": "sent",
"status_reason": "<string>",
"channel_requested": "auto",
"channel_used": "rcs",
"client_id": "<string>",
"error_code": "<string>",
"error_message": "<string>",
"sent_at": "2023-11-07T05:31:56Z",
"delivered_at": "2023-11-07T05:31:56Z",
"read_at": "2023-11-07T05:31:56Z",
"failed_at": "2023-11-07T05:31:56Z",
"created_at": "2023-11-07T05:31:56Z"
},
"message": "<string>"
}{
"success": true,
"data": {
"id": "<string>",
"reference_id": "<string>",
"status": "sent",
"status_reason": "<string>",
"channel_requested": "auto",
"channel_used": "rcs",
"client_id": "<string>",
"error_code": "<string>",
"error_message": "<string>",
"sent_at": "2023-11-07T05:31:56Z",
"delivered_at": "2023-11-07T05:31:56Z",
"read_at": "2023-11-07T05:31:56Z",
"failed_at": "2023-11-07T05:31:56Z",
"created_at": "2023-11-07T05:31:56Z"
},
"message": "<string>"
}{
"success": false,
"message": "content.card.buttons must have at most 4 items",
"data": {
"message": "<string>",
"errors": [
{
"field": "content.card.buttons",
"message": "must have at most 4 items"
}
]
}
}{
"success": true,
"message": "<string>",
"data": {}
}{
"success": true,
"message": "<string>",
"data": {}
}{
"success": true,
"message": "<string>",
"data": {}
}{
"success": true,
"message": "<string>",
"data": {}
}Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Headers
The location id of the practice
Body
Who to text: an Oliver client_id (sent to the client's primary phone) or a phone_number.
Show child attributes
Show child attributes
Required. The SMS sent when RCS isn't available, and the copy the clinic sees in its inbox. Make it stand on its own: include any link the buttons carry.
1600"Hi! Millie has preventive care due October 21-22. Book here: https://vet.example.com/book or call us at (512) 555-0100."
auto: RCS when the practice's RCS sender is live and the handset supports it, otherwise fallback_text as SMS. rcs: RCS only, never SMS. sms: fallback_text alone.
auto, rcs, sms What the client sees over RCS. One message is either a text bubble or a card, never both, so put any intro sentence in the card's description.
text: the text isfallback_text; addsuggestionsfor reply chips.media: an image or video (media_url), with optionalsuggestions.card: one rich card (card), with optionalsuggestions.carousel: 2 to 10 cards (cards) the client swipes through. Nosuggestions; put buttons on the cards.
Show child attributes
Show child attributes
Your id for this message. Echoed in every response and webhook, and unique per practice: re-sending the same reference_id returns the existing message instead of texting again, so retries are safe. A refused request (400) stores nothing, so you can fix it and reuse the reference_id.
"inv-reminder-88412"
An https URL that receives a status webhook on each status change.

