Skip to content
Developer API · v1

Build on your RingReady data

A simple REST API to read your call & web-chat activity and manage your AI receptionists — designed for your own scripts and for AI agents like Claude acting on your behalf.

Bearer-token auth · JSON · stable /api/v1

Quickstart

1. Create an API key in Profile → API keys. Copy it — the full key is shown only once.

2. Call the API with the key as a bearer token. This first request confirms your key works:

import requests

BASE = "https://www.ring-ready.com"
API_KEY = "rr_live_xxxxxxxx"          # from Profile → API keys
headers = {"Authorization": f"Bearer {API_KEY}"}

r = requests.get(f"{BASE}/api/v1/whoami", headers=headers)
print(r.json())
# {'user_id': 142, 'email': 'you@example.com', 'auth_method': 'api_key',
#  'api_key_prefix': 'rr_live_8f3a', 'scopes': ['read', 'write']}

Authentication

Every request is authenticated with an API key sent as a bearer token:

Authorization: Bearer rr_live_xxxxxxxx

Create and revoke keys in Profile → API keys. Each key only ever sees your own data. The full key is shown once at creation — we store only a hash, so if you lose it, revoke it and create a new one.

Scopes

Keys carry coarse scopes. Read endpoints need read; updating an agent needs write.

ScopeGrants
readList and read conversations and agents.
writeUpdate agent metadata (PATCH /agents/{id}).

Conventions

  • Base URL: https://www.ring-ready.com — all paths under /api/v1.
  • Format: JSON request and response bodies.
  • Timestamps: UTC, ISO-8601 with a trailing Z.
  • Scoping: every response is limited to the key owner's data.

Errors

Errors return {"detail": "..."} with an HTTP status:

StatusMeaning
401Missing, invalid, or revoked key.
403Valid key, but missing the required scope.
404Resource not found or not yours.
422Invalid request body (e.g. a blank required field).

Rate limits

None are enforced during the experimental phase. Per-key limits will be added before general availability.

Conversations

Phone calls and website chats live in one place, told apart by channel (phone or web_chat).

GET/api/v1/conversationsread

List conversations, newest first.

Query paramTypeNotes
channelstringphone or web_chat
agent_idintFilter to one receptionist
sincestringISO-8601; conversations at/after this time
before_idintPagination cursor (the previous page's next_before_id)
limitint1–200, default 50
r = requests.get(f"{BASE}/api/v1/conversations",
                 headers=headers,
                 params={"channel": "web_chat", "limit": 20})

data = r.json()
for c in data["conversations"]:
    print(c["started_at"], "·", c["label"], "·", c["summary"])

# next page:
if data["next_before_id"]:
    more = requests.get(f"{BASE}/api/v1/conversations", headers=headers,
                        params={"before_id": data["next_before_id"]}).json()

Response:

{
  "conversations": [
    {
      "id": 184, "channel": "web_chat", "agent_id": 7,
      "from": null, "to": null,
      "caller_name": "Sam", "label": "Demo Request",
      "summary": "Visitor asked for a demo and pricing.",
      "started_at": "2026-06-09T14:03:00Z",
      "ended_at": "2026-06-09T14:07:11Z",
      "duration_seconds": 251, "end_reason": "visitor_ended",
      "is_archived": false, "is_viewed": false,
      "web_chat": {"device_type": "desktop", "origin_url": "https://acme.com/pricing"}
    }
  ],
  "next_before_id": 184,
  "limit": 20
}
GET/api/v1/conversations/{id}read

A single conversation with its full transcript. Adds transcript (an array of {role, content, elapsed_s}), recording_url, and — for web chats — web_chat.visitor_ip.

convo = requests.get(f"{BASE}/api/v1/conversations/184", headers=headers).json()
for turn in convo["transcript"]:
    print(f"{turn['role']}: {turn['content']}")

Agents (receptionists)

GET/api/v1/agentsread

List your receptionists.

agents = requests.get(f"{BASE}/api/v1/agents", headers=headers).json()["agents"]
# [{"id": 7, "phone_number": "+15551234567", "agent_name": "Ava",
#   "business_name": "Acme Plumbing", "subscription_type": "growth",
#   "created_at": "2026-01-12T09:30:00Z"}]
GET/api/v1/agents/{id}read

Read one receptionist's full configuration.

{
  "id": 7, "phone_number": "+15551234567", "subscription_type": "growth",
  "agent_name": "Ava", "voice": "friendly",
  "greeting_message": "Thanks for calling Acme — how can I help?",
  "agent_goal": "Qualify leads and book consultations.",
  "business_name": "Acme Plumbing", "business_website": "https://acme.com",
  "business_services": "Emergency plumbing, water heaters, drain cleaning.",
  "faq": {"Do you offer emergency service?": "Yes, 24/7.",
          "Do you give free estimates?": "Yes, on every job."},
  "appointment_booking": {"sms_enabled": true, "sms_url": "https://book.acme.com", "sms_purpose": "booking"},
  "features": {"web_chat_enabled": true, "live_context_enabled": false,
               "webhook_enabled": false, "webhook_url": null},
  "is_suspended": false, "created_at": "2026-01-12T09:30:00Z"
}
PATCH/api/v1/agents/{id}write

Partial update — only the fields you send change. Writable fields:

FieldMax lengthNotes
agent_goal10,000 charsRequired — can't be blanked
greeting_message500 charsOptional
business_name100 charsRequired — can't be blanked
business_services30,000 charsRequired — can't be blanked
business_website400 charsOptional
faq50 entries · question 200 · answer 500A {question: answer} map

Voice, agent name, tier flags, webhooks, Conversion API and SMS settings are managed in the dashboard, not the API.

r = requests.patch(f"{BASE}/api/v1/agents/7",
                   headers=headers,
                   json={
                       "agent_goal": "Qualify the caller, then book a consultation.",
                       "greeting_message": "Thanks for calling Acme Plumbing — how can I help?",
                       "faq": {
                           "Do you offer free estimates?": "Yes — free, no-obligation estimates on every job.",
                           "What are your hours?": "We answer 24/7, including weekends and holidays.",
                           "Do you handle emergencies?": "Yes — we dispatch same-day for emergencies.",
                       },
                   })

print(r.json())
# {'id': 7, 'updated': ['agent_goal', 'greeting_message', 'faq']}

Full example: improve a receptionist from its conversations

The pattern this API is built for — read what callers actually asked, have an LLM find the gaps, and feed the answers back into the agent's FAQ:

import requests, json
from anthropic import Anthropic

BASE = "https://www.ring-ready.com"
RR = {"Authorization": "Bearer rr_live_xxxxxxxx"}
claude = Anthropic()
AGENT_ID = 7

# 1. Pull the last 50 conversations for this agent
convos = requests.get(f"{BASE}/api/v1/conversations", headers=RR,
                      params={"agent_id": AGENT_ID, "limit": 50}).json()["conversations"]

# 2. Fetch each transcript
transcripts = []
for c in convos:
    full = requests.get(f"{BASE}/api/v1/conversations/{c['id']}", headers=RR).json()
    transcripts.append(full["transcript"])

# 3. Ask Claude for recurring questions the agent answered poorly,
#    with a drafted FAQ answer for each
prompt = (
    f"Here are {len(transcripts)} receptionist transcripts. "
    "Find the 5 most common questions callers asked that the agent did NOT answer well. "
    'Return JSON: [{"question": ..., "answer": ...}].\n\n'
    + json.dumps(transcripts)[:50000]
)
reply = claude.messages.create(
    model="claude-sonnet-4-6", max_tokens=1500,
    messages=[{"role": "user", "content": prompt}],
)
additions = json.loads(reply.content[0].text)

# 4. Merge into the agent's FAQ and write it back
agent = requests.get(f"{BASE}/api/v1/agents/{AGENT_ID}", headers=RR).json()
faq = agent.get("faq") or {}
for item in additions:
    faq[item["question"]] = item["answer"]

requests.patch(f"{BASE}/api/v1/agents/{AGENT_ID}", headers=RR, json={"faq": faq})
print(f"Added {len(additions)} answers to the FAQ.")

Run it on a schedule and your receptionist keeps getting better at the questions it actually gets.

For AI agents & tools

Machine-readable spec: the whole API is described in OpenAPI at /api/v1/openapi.json — import it as tools in the Anthropic or OpenAI SDKs, a ChatGPT custom GPT (Actions), LangChain or n8n, or generate an MCP server from it.

Site overview for LLMs: llms.txt.

Hand an agent a key and the spec, and it can read conversations and tune receptionists on its own. Because every key is scoped to one account, an agent only ever touches that customer's data.

Ready to build?

Create a key and make your first call in two minutes.