Meetily
Agent APIClients

Python SDK

meetily_agent, a stdlib-only Python client for long-running receivers and wait-loops.

The Python SDK (meetily_agent) is a small, standard-library-only client for the same HTTP API. It is best for long-running receivers and wait-loops: webhook listeners, job-wait scripts, recording-wait scripts.

Install

Not on PyPI

The SDK is not published on PyPI. Put the sdk/python directory on your PYTHONPATH instead. The shipped examples do this with a sys.path line, not with a package install.

Requires Python 3.8 or newer. No third-party dependencies.

from meetily_agent import MeetilyClient

Construct a client

A bare MeetilyClient() auto-discovers the base URL and token the same way the CLI does: base defaults to http://127.0.0.1:8420 (or the MEETILY_PRO_SERVER env var), and the token comes from MEETILY_PRO_TOKEN or the loopback token file.

from meetily_agent import MeetilyClient

client = MeetilyClient()
print(client.system.whoami())

The full constructor is MeetilyClient(base=None, token=..., timeout=10, verbose=False, fingerprint=None). Pass token=None to send no auth header, or fingerprint="..." to pin a self-signed certificate for LAN access.

Resource namespaces

Methods are grouped on resource namespaces, mirroring the HTTP routes:

client.system.whoami()
client.meetings.list()
client.meetings.get(meeting_id)
client.meetings.summary(meeting_id)
client.jobs.list()
client.jobs.wait(job_id)
client.recording.wait()
client.config.get(section)
client.webhooks.create(url, events)
client.webhooks.test(webhook_id)

Not every route has a matching method. There is no client.jobs.get(), no client.jobs.import(...), and no dedicated retranscription method in this SDK; see the honesty note at the end of this page.

Waiting

client.jobs.wait(job_id) and client.recording.wait() long-poll the gateway's wait streams. Each call blocks until the event arrives or the wait times out, so you can write a linear script instead of a poll loop:

from meetily_agent import MeetilyClient

client = MeetilyClient()
client.recording.start(meeting_name="Standup")
# ... recording happens ...
client.recording.stop()
state = client.recording.wait(until="stopped")
print(state)

Receiving webhooks

The SDK ships a small receiver and a signature verifier, not just a way to register a webhook.

Register a public or tunnel URL, never 127.0.0.1

The gateway rejects loopback and private webhook targets with 400 at registration time. Point client.webhooks.create(...) at a public URL or a tunnel (ngrok, Cloudflare Tunnel, etc.), never at http://127.0.0.1.

from meetily_agent import MeetilyClient, get_header, verify_signature

client = MeetilyClient()

# PUBLIC_URL must be reachable from the gateway, e.g. an ngrok/Cloudflare
# tunnel pointed at your local receiver. Loopback and private targets are
# rejected at registration.
webhook = client.webhooks.create("https://your-tunnel.example.com/hook", ["job.completed"])
print("registered", webhook["id"])

# Your receiver (any HTTP server) gets a POST per delivery with headers
# X-Meetily-Signature: sha256=<hex> and X-Meetily-Timestamp: <unix_seconds>.
# Verify every delivery before trusting the body:
def handle_delivery(headers, body):
    sig = get_header(headers, "X-Meetily-Signature")
    ts = get_header(headers, "X-Meetily-Timestamp")
    if not verify_signature(webhook["hmac_secret"], ts, body, sig, max_age_seconds=300):
        raise ValueError("bad or stale signature, rejecting delivery")
    print("verified delivery:", body)

The signature is computed as sha256= plus the lowercase-hex HMAC-SHA256 of "timestamp.body", keyed by the webhook's hmac_secret. verify_signature recomputes it and also rejects deliveries older than max_age_seconds (replay defense); pass max_age_seconds=None to skip that check.

You can trigger a synthetic delivery to confirm your receiver works before waiting on real traffic:

client.webhooks.test(webhook["id"])

Errors

ExceptionWhen
MeetilyErrorA non-2xx response. Has .status, .code, .message.
MeetilyUnreachableErrorThe app is not running or the gateway is unreachable.
MeetilyTLSErrorA pinned certificate fingerprint mismatch.
from meetily_agent import MeetilyClient, MeetilyError, MeetilyUnreachableError

client = MeetilyClient()
try:
    print(client.meetings.list(limit=20))
except MeetilyUnreachableError as e:
    print("app not running:", e)
except MeetilyError as e:
    print("gateway error", e.status, e.code, e.message)

No SDK method for a call? Use curl

Single-job get, audio import, and originating a retranscription are not wrapped by this SDK. Fall back to curl with your bearer token for those. The coverage matrix on the reference index lists exactly which calls each client (CLI, curl, Python SDK) supports.

Last updated on

On this page