Saved views and filter helpers
A saved view stores a filter you use often. The filter helpers read the values your contacts have, like their sources and custom field keys, so you can offer them as filter choices.
# Saved views
A saved view is a named filter for the Contacts page, the Inbox or the Texts log (Reports, Logs). Views are personal: they belong to the user the API key or session is for, not to the whole account. You can save up to 50 views per page. No team permission is needed.
# The saved view object
idinteger The view id, counting up from 1 for each user.
contextstring Where it’s used: contacts, conversations or messages (the text log).
namestring Up to 60 characters.
filtersobject The filter, as the page’s query values, like {"tag": "vip"}.
# List saved views
Your saved views, oldest first.
Parameters
contextstring · query Only views for contacts, conversations or messages. Any other value returns all of them.
Returns a list of saved view objects in data.
Errors
HTTP Code When
503 saved_views_unavailableWe couldn’t read your views. Retry.
curl "https://api.tryready.com/saved-views?context=contacts" \
-H "X-API-Key: $READY_API_KEY"
const res = await fetch('https://api.tryready.com/saved-views?context=contacts', {
headers: {
'X-API-Key': process.env.READY_API_KEY,
},
});
const json = await res.json().catch(() => ({}));
if (!res.ok || json.success === false) {
throw new Error(`${res.status}${json.error_code || json.code ? ' ' + (json.error_code || json.code) : ''}: ${json.error || json.message || res.statusText}`);
}
import os, requests
r = requests.get(
"https://api.tryready.com/saved-views?context=contacts",
headers={"X-API-Key": os.environ["READY_API_KEY"]},
timeout=30,
)
data = r.json() if r.headers.get("content-type", "").startswith("application/json") else {}
if not r.ok or data.get("success") is False:
raise RuntimeError(f'{r.status_code} {data.get("error_code") or data.get("code") or ""}: {data.get("error") or data.get("message") or r.reason}')
Returns:
{
"success": true,
"data": [
{ "id": 1, "context": "contacts", "name": "Texas VIPs", "filters": { "tag": "vip", "state": "TX" } }
]
}
# Create a saved view
Saves a filter under a name. Returns 200. Each call adds a new view, even with the same name.
Parameters
contextstring Required contacts, conversations or messages.
namestring Required Trimmed. Up to 60 characters.
filtersobject Required Up to 4000 characters as JSON.
Returns the new saved view object in data.
Errors
HTTP Code When
400 saved_view_invalidA bad context, no name, a name over 60 characters, filters isn’t an object or is too long, or you already have 50 views for this page.
400 invalid_fieldcontext is a list or an object.
409 saved_views_conflictYour views changed in another request at the same time. Retry.
500 saved_views_write_failedThe view wasn’t saved. Retry.
503 saved_views_unavailableWe couldn’t read your views, so nothing changed. Retry.
curl -X POST "https://api.tryready.com/saved-views" \
-H "X-API-Key: $READY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"context": "contacts",
"name": "Texas VIPs",
"filters": {
"tag": "vip",
"state": "TX"
}
}'
const res = await fetch('https://api.tryready.com/saved-views', {
method: 'POST',
headers: {
'X-API-Key': process.env.READY_API_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"context": "contacts",
"name": "Texas VIPs",
"filters": {
"tag": "vip",
"state": "TX"
}
}),
});
const json = await res.json().catch(() => ({}));
if (!res.ok || json.success === false) {
throw new Error(`${res.status}${json.error_code || json.code ? ' ' + (json.error_code || json.code) : ''}: ${json.error || json.message || res.statusText}`);
}
import os, requests
r = requests.post(
"https://api.tryready.com/saved-views",
headers={"X-API-Key": os.environ["READY_API_KEY"]},
json={
"context": "contacts",
"name": "Texas VIPs",
"filters": {
"tag": "vip",
"state": "TX"
}
},
timeout=30,
)
data = r.json() if r.headers.get("content-type", "").startswith("application/json") else {}
if not r.ok or data.get("success") is False:
raise RuntimeError(f'{r.status_code} {data.get("error_code") or data.get("code") or ""}: {data.get("error") or data.get("message") or r.reason}')
Returns:
{
"success": true,
"data": { "id": 1, "context": "contacts", "name": "Texas VIPs", "filters": { "tag": "vip", "state": "TX" } }
}
# Rename a saved view
Changes a view’s name. The filter stays the same.
Parameters
idinteger · path Required
namestring Required Trimmed. Up to 60 characters.
Returns the saved view object in data.
Errors
HTTP Code When
400 saved_view_invalidNo name, or over 60 characters.
400 invalid_fieldname is a list or an object.
404 saved_view_not_foundYou have no view with this id.
409 saved_views_conflictYour views changed in another request at the same time. Retry.
500 saved_views_write_failedNothing was saved. Retry.
503 saved_views_unavailableWe couldn’t read your views, so nothing changed. Retry.
curl -X PATCH "https://api.tryready.com/saved-views/1" \
-H "X-API-Key: $READY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Texas VIPs (active)"
}'
const res = await fetch('https://api.tryready.com/saved-views/1', {
method: 'PATCH',
headers: {
'X-API-Key': process.env.READY_API_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"name": "Texas VIPs (active)"
}),
});
const json = await res.json().catch(() => ({}));
if (!res.ok || json.success === false) {
throw new Error(`${res.status}${json.error_code || json.code ? ' ' + (json.error_code || json.code) : ''}: ${json.error || json.message || res.statusText}`);
}
import os, requests
r = requests.patch(
"https://api.tryready.com/saved-views/1",
headers={"X-API-Key": os.environ["READY_API_KEY"]},
json={
"name": "Texas VIPs (active)"
},
timeout=30,
)
data = r.json() if r.headers.get("content-type", "").startswith("application/json") else {}
if not r.ok or data.get("success") is False:
raise RuntimeError(f'{r.status_code} {data.get("error_code") or data.get("code") or ""}: {data.get("error") or data.get("message") or r.reason}')
# Delete a saved view
Deletes one of your views. Sending it again returns 404.
Returns { "success": true }.
Errors
HTTP Code When
400 invalid_fieldThe id isn’t a whole number.
400 unknown_fieldYou sent a body. This route takes none.
404 saved_view_not_foundYou have no view with this id.
409 saved_views_conflictYour views changed in another request at the same time. Retry.
500 saved_views_write_failedNothing was deleted. Retry.
503 saved_views_unavailableWe couldn’t read your views, so nothing changed. Retry.
curl -X DELETE "https://api.tryready.com/saved-views/1" \
-H "X-API-Key: $READY_API_KEY"
const res = await fetch('https://api.tryready.com/saved-views/1', {
method: 'DELETE',
headers: {
'X-API-Key': process.env.READY_API_KEY,
},
});
const json = await res.json().catch(() => ({}));
if (!res.ok || json.success === false) {
throw new Error(`${res.status}${json.error_code || json.code ? ' ' + (json.error_code || json.code) : ''}: ${json.error || json.message || res.statusText}`);
}
import os, requests
r = requests.delete(
"https://api.tryready.com/saved-views/1",
headers={"X-API-Key": os.environ["READY_API_KEY"]},
timeout=30,
)
data = r.json() if r.headers.get("content-type", "").startswith("application/json") else {}
if not r.ok or data.get("success") is False:
raise RuntimeError(f'{r.status_code} {data.get("error_code") or data.get("code") or ""}: {data.get("error") or data.get("message") or r.reason}')
# Filter helpers
These read the values your contacts actually have, so you can offer them as filter choices. All need the view_contacts permission.
# List custom field names
Your custom field names, A to Z, up to 200: every custom field , plus keys in custom_fields on your 2,000 newest contacts. Use it to match import columns to fields you already have.
Returns a list of names in data.
Errors
HTTP Code When
503 FACET_READ_UNAVAILABLEWe couldn’t read them. Retry.
curl "https://api.tryready.com/contacts/custom-field-keys" \
-H "X-API-Key: $READY_API_KEY"
const res = await fetch('https://api.tryready.com/contacts/custom-field-keys', {
headers: {
'X-API-Key': process.env.READY_API_KEY,
},
});
const json = await res.json().catch(() => ({}));
if (!res.ok || json.success === false) {
throw new Error(`${res.status}${json.error_code || json.code ? ' ' + (json.error_code || json.code) : ''}: ${json.error || json.message || res.statusText}`);
}
import os, requests
r = requests.get(
"https://api.tryready.com/contacts/custom-field-keys",
headers={"X-API-Key": os.environ["READY_API_KEY"]},
timeout=30,
)
data = r.json() if r.headers.get("content-type", "").startswith("application/json") else {}
if not r.ok or data.get("success") is False:
raise RuntimeError(f'{r.status_code} {data.get("error_code") or data.get("code") or ""}: {data.get("error") or data.get("message") or r.reason}')
Returns:
{
"success": true,
"data": ["plan", "Renewal Date"]
}
# Suggest filter values
The 50 most common values of one field, counted over a sample of up to 5,000 contacts, most common first. Counts are for the sample, not your whole list. Cached for 5 minutes.
Parameters
fieldstring · query Required tags, city, state, source, company_name, first_name or last_name. Any other field returns an empty list.
Returns a list of {value, count} in data.
Errors
HTTP Code When
400 invalid_fieldfield is sent more than once.
503 FACET_READ_UNAVAILABLEWe couldn’t read them. Retry.
curl "https://api.tryready.com/contacts/distinct-values?field=state" \
-H "X-API-Key: $READY_API_KEY"
const res = await fetch('https://api.tryready.com/contacts/distinct-values?field=state', {
headers: {
'X-API-Key': process.env.READY_API_KEY,
},
});
const json = await res.json().catch(() => ({}));
if (!res.ok || json.success === false) {
throw new Error(`${res.status}${json.error_code || json.code ? ' ' + (json.error_code || json.code) : ''}: ${json.error || json.message || res.statusText}`);
}
import os, requests
r = requests.get(
"https://api.tryready.com/contacts/distinct-values?field=state",
headers={"X-API-Key": os.environ["READY_API_KEY"]},
timeout=30,
)
data = r.json() if r.headers.get("content-type", "").startswith("application/json") else {}
if not r.ok or data.get("success") is False:
raise RuntimeError(f'{r.status_code} {data.get("error_code") or data.get("code") or ""}: {data.get("error") or data.get("message") or r.reason}')
Returns:
{
"success": true,
"data": [
{ "value": "TX", "count": 1204 },
{ "value": "CA", "count": 877 }
]
}