curl --request GET \
--url https://api.usesimple.ai/api/v1/contacts/{phoneNumber}/data \
--header 'Authorization: <api-key>'import requests
url = "https://api.usesimple.ai/api/v1/contacts/{phoneNumber}/data"
headers = {"Authorization": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: '<api-key>'}};
fetch('https://api.usesimple.ai/api/v1/contacts/{phoneNumber}/data', 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://api.usesimple.ai/api/v1/contacts/{phoneNumber}/data",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.usesimple.ai/api/v1/contacts/{phoneNumber}/data"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.usesimple.ai/api/v1/contacts/{phoneNumber}/data")
.header("Authorization", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.usesimple.ai/api/v1/contacts/{phoneNumber}/data")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"phoneNumber": "<string>"
}{
"status": "error",
"success": false,
"error": "<string>",
"errors": [
"<string>"
]
}{
"status": "error",
"success": false,
"error": "<string>",
"errors": [
"<string>"
]
}{
"status": "error",
"success": false,
"error": "<string>",
"errors": [
"<string>"
]
}Read Stored Contact Data with the API
Retrieve the state stored for a contact phone number so a connected workflow can use current customer context during an interaction.
curl --request GET \
--url https://api.usesimple.ai/api/v1/contacts/{phoneNumber}/data \
--header 'Authorization: <api-key>'import requests
url = "https://api.usesimple.ai/api/v1/contacts/{phoneNumber}/data"
headers = {"Authorization": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: '<api-key>'}};
fetch('https://api.usesimple.ai/api/v1/contacts/{phoneNumber}/data', 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://api.usesimple.ai/api/v1/contacts/{phoneNumber}/data",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.usesimple.ai/api/v1/contacts/{phoneNumber}/data"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.usesimple.ai/api/v1/contacts/{phoneNumber}/data")
.header("Authorization", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.usesimple.ai/api/v1/contacts/{phoneNumber}/data")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"phoneNumber": "<string>"
}{
"status": "error",
"success": false,
"error": "<string>",
"errors": [
"<string>"
]
}{
"status": "error",
"success": false,
"error": "<string>",
"errors": [
"<string>"
]
}{
"status": "error",
"success": false,
"error": "<string>",
"errors": [
"<string>"
]
}+ country code. URL-encode the + when it appears in the path.
Callers that do not have a phone number can be keyed by any other identifier, such as a chat or SIP identifier, of up to 128 characters. Simple stores those identifiers as provided and returns them unchanged in phoneNumber.
curl 'https://api.usesimple.ai/api/v1/contacts/%2B14155550100/data' \
-H 'Authorization: Bearer YOUR_API_KEY'
phoneNumber, the identifier shadows the stored value in this response:
{
"phoneNumber": "+14155550100",
"five9ConversationId": "conv-48291",
"routingStatus": "awaiting_follow_up"
}
STRING: Alphanumeric, maximum 250 characters; a longer value overruns the variable, and the truncated JSON that results fails the IVR’s parse entirely rather than dropping just the long field.
To keep the payload parseable:
- values longer than 250 characters are cut at the last sentence boundary that fits; a value with no usable boundary is truncated at 250 characters
- numbers and booleans are serialized as strings (
3becomes"3") - null and absent values are serialized as an empty string, not
"null" - nested objects and arrays are serialized as JSON text, so a caller that wants the structure back can parse the value a second time
PUT, PATCH, and DELETE responses still return revision, ttlSeconds, and expiresAt.
The entire response body is also kept within 250 characters, not just each value, because IVR scripts commonly assign the whole body to a single string variable before parsing it. When the combined payload would overrun the budget, the longest field is shortened until it fits, longest first — so a prose field such as a call summary absorbs the loss.
Values of 64 characters or fewer are never shortened, nor is the caller identifier. A routing value, status, or identifier carries its meaning in full: truncating place_order to place_or does not degrade it, it changes it, and an IVR comparing against that value silently takes the wrong branch. Long values are prose, which loses detail but stays correct when cut.
If a contact holds so many short values that the body cannot fit, the response is returned over budget rather than corrupting them. An oversized response that the IVR fails to parse leaves its variable empty, which is recoverable; a corrupted routing value is not. Store only what the IVR actually reads.
Records have no expiry by default. A record with an expired TTL, or a record that has been deleted, is treated as missing and returns 404.
The endpoint returns 401 when authentication fails, 404 when no current data exists for the caller identifier, and 422 when the identifier is invalid.Authorizations
Path Parameters
The caller's phone number or other caller identifier. US numbers may be formatted or sent as digits; non-US numbers must include the + country code. Non-phone identifiers (for example chat or SIP identifiers) are accepted verbatim, up to 128 characters.
Response
Current contact data.
Your stored fields at the top level, keyed alongside the caller identifier. Every value is a string, no value exceeds 250 characters, and the entire serialized body is kept within 250 characters as well — when the combined payload would overrun that, the longest field is shortened until it fits, longest first, so a prose field absorbs the loss. Values of 64 characters or fewer are never shortened, nor is the caller identifier, because truncating a routing value or status changes its meaning rather than degrading it; a body of only short values is returned over budget instead. IVR platforms consume this response as a flat key-value list and hold each value in a fixed-width string variable (Five9 caps script strings at 250 characters), so stored values longer than that are cut at the last sentence boundary that fits, or truncated at 250 characters when there is no usable boundary. Numbers and booleans are serialized as strings, null and absent values as an empty string, and nested objects and arrays as JSON text. Revision and expiry metadata is not returned here so it does not consume the IVR's character budget; the write endpoints return it.