Python SDK
Install
pip install ravi-sdk
Create A Client
import os
from ravi import Ravi
ravi = Ravi(api_key=os.environ["RAVI_API_KEY"])
api_key is required. Use a ravi_id_... identity key for agent runtime work, or a ravi_mgmt_... management key for account-level operations. The key is an auth fence only — the caller chooses the identity, and every per-identity call sends ?identity=<uuid> taken from the identity object.
For long-running processes, use the context manager so the underlying HTTP pool is closed:
with Ravi(api_key=os.environ["RAVI_API_KEY"]) as ravi:
identities = ravi.identities.list()
Choose An Identity
The caller chooses the identity, then calls channels and resources on it. Create
one, fetch one by uuid, or — with an identity-scoped key — resolve the single
fenced identity with ravi.me.
identity = ravi.identities.create(
name="shopping-agent",
email_identifier="shopping", # email local part; omit to auto-generate
provision_phone=True, # also give it a phone number
)
# `email` and `phone` are channel objects — the identifiers are `.address` / `.number`.
print(identity.email.address, identity.phone.number)
# With an identity-scoped key you don't have the uuid handy:
me = ravi.me # the single identity the key is fenced to
Identity methods:
| Method | Purpose |
|---|---|
ravi.identities.create(...) | Create an identity, optionally with email local part and phone provisioning |
ravi.identities.list() | List identities visible to the key |
ravi.identities.get(identity_uuid) | Fetch one identity |
ravi.identities.update(identity_uuid, name=...) | Update identity metadata |
ravi.identities.provision_phone(identity_uuid) | Add a phone number to an existing identity |
Wait For A Verification Code
The killer use case: send a request, then block until the OTP or verification
message lands. wait_for polls the channel’s inbox and returns the first
matching message.
# Email verification: trigger a signup, then wait for the confirmation email.
identity.email.send(to="signup@service.com", subject="Sign me up", body="…")
msg = identity.email.wait_for(lambda m: "verify" in m.subject, timeout=120)
msg.reply(body="got it") # messages carry behaviour: reply/forward/mark_read
# SMS OTP: wait for the 6-digit code on the identity's number.
identity.phone.send(to="+15551234567", body="START")
otp = identity.phone.wait_for(lambda m: "code" in m.body, timeout=120)
print(otp.body)
Email Channel
identity.email is the identity’s inbox as a channel. Send from it, list the
flat inbox or the grouped threads, and act on returned EmailMessage objects.
msg = identity.email.send(to="user@example.com", subject="Hello", body="Greetings from my AI agent")
inbox = identity.email.inbox(unread=True) # flat list of EmailMessage
threads = identity.email.threads() # grouped view
msg.reply(body="Thanks!")
msg.forward(to="ops@acme.com")
msg.mark_read()
Phone Channel
identity.phone is the identity’s number as a channel (or None if no number
is provisioned). Send SMS, list conversations, or place voice calls.
sms = identity.phone.send(to="+15551234567", body="Your code is 482910")
inbox = identity.phone.inbox(unread=True) # flat list of SmsMessage
conversations = identity.phone.conversations()
# Place an outbound voice call from the identity's number.
call = identity.phone.call(to="+15551234567")
print(call.uuid, call.status)
transcript = call.transcript()
Vault And Contacts
Credentials and the contact directory live under the identity.
identity.vault.passwords.create(domain="acme.com", username="agent", password="…")
identity.vault.secrets.create(key="OPENAI_API_KEY", value="sk-…")
contact = identity.contacts.find("user@example.com")
Events
Replay durable events after your last processed cursor:
events = ravi.events.list(
since=last_seq,
limit=100,
event_types=["call.ended", "email.message.received"],
)
API Keys
Management keys and identity keys are available through ravi.api_keys.
management_key = ravi.api_keys.management.create("ci")
print(management_key.key) # full value is returned once
identity_key = ravi.api_keys.identity.create("shopping-agent", identity.uuid)
print(identity_key.key) # full value is returned once
Webhook Verification
Ravi signs deliveries with X-Ravi-Timestamp and X-Ravi-Signature.
from ravi import verify_webhook_signature, WebhookSignatureError
try:
verify_webhook_signature(
raw_body,
request.headers["X-Ravi-Timestamp"],
request.headers["X-Ravi-Signature"],
signing_secret,
)
except WebhookSignatureError:
return Response(status_code=401)
Public Exports
The PyPI package is ravi-sdk. The Python import module is ravi.
The module exports the Ravi client, resource classes, Pydantic models, typed errors, event payload models, and webhook verification helpers from ravi.
Top-level exports include Ravi, RaviError subclasses, resource classes, Pydantic API models, verify_webhook_signature, and WebhookSignatureError.