Skip to main content

Python SDK for the Sesame human-in-the-loop approval API

Project description

sesame-sdk

Python SDK for the Sesame human-in-the-loop approval API.

Drop an approval gate in front of any sensitive operation in your backend. Sesame triggers a request that a human approves (via Telegram + push), and your code blocks until the decision lands — or reacts asynchronously via a webhook.

pip install sesame-sdk

Requires Python 3.12+. Runtime deps: httpx, pydantic.

Configuration

The client reads credentials from the environment, or you can pass them explicitly:

Env var Default Purpose
SESAME_API_KEY (required) sk_live_... API key
SESAME_BROKER_URL https://getsesame.dev Broker base URL — override only to self-host or point at local dev
from sesame_sdk import Sesame

client = Sesame()                                  # hosted broker; reads SESAME_API_KEY
client = Sesame(api_key="sk_live_...")             # default base_url is https://getsesame.dev
client = Sesame(api_key="sk_live_...", base_url="http://localhost:8000")  # self-host / local

Gate a function with @require_approval

The wrapped function only runs if a human approves. Denied/expired raises ApprovalDenied; no decision before timeout raises ApprovalTimeout.

from sesame_sdk import require_approval, ApprovalDenied

@require_approval(
    "payments.refund",
    summary=lambda amount, **_: f"Refund ${amount/100:.2f} to customer",
    timeout=300,
)
def issue_refund(amount: int, customer_id: str) -> None:
    stripe.Refund.create(amount=amount, customer=customer_id)

try:
    issue_refund(4200, customer_id="cus_123")
except ApprovalDenied:
    log.warning("refund rejected by operator")

summary may be a static string or a callable receiving the wrapped function's arguments. Omit it for a sensible default built from the action and function name. Pass client=Sesame(...) to use a specific client; otherwise a module-level default is built lazily from the environment.

Trigger and wait explicitly

from sesame_sdk import Sesame

client = Sesame()
approval = client.approvals.trigger(
    action="db.delete",
    summary="Delete 1,204 rows from prod.orders",
    reason="GDPR erasure request #882",
    context={"table": "orders", "rows": 1204},
)

approval.wait(timeout=300)   # blocks on the broker's long-poll until decided
if approval.approved:
    run_deletion()
else:
    print("decision:", approval.status)  # "denied" or "expired"

Receive decisions via webhook

When you pass a callback_url, the broker POSTs to it on every terminal decision. Verify the signature before trusting the body — verify_webhook recomputes the HMAC-SHA256 over the raw request body and rejects stale timestamps.

Flask

from flask import Flask, request, abort
from sesame_sdk import verify_webhook, WebhookVerificationError

app = Flask(__name__)
WEBHOOK_SECRET = os.environ["SESAME_WEBHOOK_SECRET"]

@app.post("/sesame/webhook")
def sesame_webhook():
    try:
        payload = verify_webhook(request.headers, request.get_data(), WEBHOOK_SECRET)
    except WebhookVerificationError:
        abort(400)
    # payload: {"approval_id", "action", "status", "decided_at", "requester_label", "dedup_key"?}
    handle_decision(payload["approval_id"], payload["status"])
    return "", 204

FastAPI

from fastapi import FastAPI, Request, Response, HTTPException
from sesame_sdk import verify_webhook, WebhookVerificationError

app = FastAPI()

@app.post("/sesame/webhook")
async def sesame_webhook(request: Request):
    raw = await request.body()  # must be the exact bytes the broker signed
    try:
        payload = verify_webhook(request.headers, raw, WEBHOOK_SECRET)
    except WebhookVerificationError:
        raise HTTPException(status_code=400, detail="bad signature")
    handle_decision(payload["approval_id"], payload["status"])
    return Response(status_code=204)

Exceptions

All inherit from ApprovalError:

  • ApprovalDenied — terminal denied/expired (carries .approval_id, .status)
  • ApprovalTimeout — no decision before the caller's timeout
  • SesameAuthError — broker rejected the API key (HTTP 401)
  • NotFoundError — unknown approval id (HTTP 404)
  • WebhookVerificationError — bad/missing signature, stale timestamp, or bad JSON

Notes

This SDK is synchronous for v1. An async client may be added later; until then, run approval.wait() in a worker thread if you need to avoid blocking an event loop.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sesame_sdk-0.1.1.tar.gz (8.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

sesame_sdk-0.1.1-py3-none-any.whl (11.1 kB view details)

Uploaded Python 3

File details

Details for the file sesame_sdk-0.1.1.tar.gz.

File metadata

  • Download URL: sesame_sdk-0.1.1.tar.gz
  • Upload date:
  • Size: 8.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.1 {"installer":{"name":"uv","version":"0.11.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for sesame_sdk-0.1.1.tar.gz
Algorithm Hash digest
SHA256 71f37c3b6a21f1d6027951a3ab2a4679ec88c26d5774438a296f6f3941c6f93a
MD5 219d9953bea6530f7ed55b2d76eeedf9
BLAKE2b-256 954b04b42868f5de64f754bebe7b77b030675ac25291b32d90acb8a51a8e7f89

See more details on using hashes here.

File details

Details for the file sesame_sdk-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: sesame_sdk-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 11.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.1 {"installer":{"name":"uv","version":"0.11.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for sesame_sdk-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 b4b5713e17613a66e05d93a2bb9d3ed23ebc240f49ab21ee593030963e0955a6
MD5 669d83e85b20aace667ddd106d98c9a4
BLAKE2b-256 5f4f965a7a67bbca2c33aa50fc4837a087bd5f6fcb7d14821d0e9d523f61ff7c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page