Skip to main content

Ricky Python SDK

The official Python client for the Ricky REST API: contacts, conversations, messages, templates and webhooks of one organization.

Python 3.9 or later. Its only dependencies are httpx and typing-extensions.

pip install getricky

Quick start

Create a key in Ricky under Settings → API and keep it on your server. Ricky() reads it from RICKY_API_KEY when you pass none.

import time

from getricky import Ricky

ricky = Ricky()  # or Ricky("rky_live_…")

# The channels the organization can send from.
channels = ricky.list_channels()["data"]
whatsapp = next(channel for channel in channels if channel["type"] == "whatsapp")

# Send an approved WhatsApp template to a phone number. Ricky finds or creates
# the contact and its conversation, and answers with the send it queued.
send = ricky.start_conversation(
    {
        "channel_id": whatsapp["id"],
        "phone": "+50760001234",
        "template": {
            "id": "1234567890",
            "components": [{"type": "body", "parameters": [{"type": "text", "text": "Ana"}]}],
        },
    },
    idempotency_key="order-10482-ready",
)["data"]

# Follow it until the provider accepts it.
while send["status"] == "queued":
    time.sleep(2)
    send = ricky.get_send(send["id"])["data"]
print(send["status"], send["failure_reason"])

Every operation of the API is a method named after its operationId in snake case (listContacts is list_contacts). Path parameters come first, then the request body as a dict, then query parameters as keywords. Methods return the response body as the API sends it: {"data": ...} for one resource and {"data": [...], "next_cursor": ...} for a list. Requests and responses are typed with TypedDicts from getricky.types, so your editor and type checker know every field, and fields the API adds later reach you without an upgrade.

AsyncRicky has the same methods for asyncio:

from getricky import AsyncRicky

async with AsyncRicky() as ricky:
    contact = (await ricky.get_contact(contact_id))["data"]

Pagination

paginate walks every page of a list method and yields its items; .pages() yields whole pages:

for contact in ricky.paginate(ricky.list_contacts, tag_id=tag_id):
    print(contact["id"], contact["first_name"])

for page in ricky.paginate(ricky.list_messages, conversation_id).pages():
    print(len(page["data"]))

With AsyncRicky, use async for.

Errors

A failed request raises RickyError with the API's code, the HTTP status, the param that caused it when known, and the request_id to quote to support. A request that never got an answer raises RickyConnectionError.

from getricky import RickyError

try:
    ricky.send_message(conversation_id, {"type": "text", "text": "Hola"})
except RickyError as error:
    if error.code == "outside_messaging_window":
        ...  # send an approved template instead
    else:
        raise

Retries and idempotency

Writes that accept an Idempotency-Key get a random one unless you pass idempotency_key=. Pass your own, derived from your data, to make a retry from your side safe too: the same key and body replay the first response instead of repeating the write.

Reads, and writes that carry a key, are retried twice on connection errors, 429 and 5xx, waiting as Retry-After says or backing off exponentially. Change it with Ricky(max_retries=…). A write the API may have applied before failing answers request_processing on retry: read the resource before trying again.

Webhooks

verify_webhook checks the X-Ricky-Signature and X-Ricky-Timestamp headers against the raw body, rejects deliveries more than five minutes old, and returns the event. With Flask:

from flask import Flask, request
from getricky import WebhookVerificationError, verify_webhook

app = Flask(__name__)


@app.post("/ricky/webhooks")
def ricky_webhook():
    try:
        event = verify_webhook(request.get_data(), request.headers, WEBHOOK_SECRET)
    except WebhookVerificationError:
        return "", 401
    if event["type"] == "message.received":
        ...  # queue the work; deduplicate by event["id"]
    return "", 204

Answer within 10 seconds. Deliveries can repeat, so deduplicate by event["id"]. New event types ship without a new API version: handle the ones you know and ignore the rest.

Configuration

Ricky(
    "rky_live_…",
    base_url="https://getricky.ai/api/v1",
    max_retries=2,
    timeout=120.0,  # seconds per attempt; a file send downloads the file before it answers
    http_client=None,  # or your own httpx.Client
)

License

MIT

Metadata

Release files for getricky 0.1.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for getricky 0.1.3
File Size Uploaded Provenance
getricky-0.1.3.tar.gz 29.2 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for getricky 0.1.3
File Interpreter ABI Platform
getricky-0.1.3-py3-none-any.whl Python 3 none any Details

Total release size: 57.7 kB

Release files / getricky-0.1.3.tar.gz

Download URL getricky-0.1.3.tar.gz
Size 29.2 kB
Tags Source
SHA-256 checksum
How to use checksums
ba10576b5c6fc26b0a65de7472aef78a6d55daea18f3a63b5e3162a059a55657
BLAKE2b-256 checksum
How to use checksums
63905a19664c5392bc1b7851b1780b014be8fda9eb2552cd44d6469c3be1ffda
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.

Transparency log

Release files / getricky-0.1.3-py3-none-any.whl

Download URL getricky-0.1.3-py3-none-any.whl
Size 28.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e6a67c12eadc332facb9b4bf0ca4cdfaf608181d1260bb935a0f37ad89e896fe
BLAKE2b-256 checksum
How to use checksums
46d9e2e1475e4714627f52d4d59a37170b1cbb1d2b715b71a4fa9b64147eff97
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.

Transparency log

Security for getricky 0.1.3

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for getricky-0.1.3.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page