## Install ```bash pip install ravi-sdk ``` ## Create A Client ```python 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=` taken from the identity object. For long-running processes, use the context manager so the underlying HTTP pool is closed: ```python 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`. ```python 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. ```python # 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. ```python 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. ```python 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. ```python 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: ```python 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`. ```python 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`. ```python 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`. ## Next Steps - [SDK Overview](/sdk/overview/) - [TypeScript SDK](/sdk/typescript/) - [API Reference](/api/reference/)