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 SDK needs one thing — your API key. Create one in the Sesame dashboard (API Keys), then set SESAME_API_KEY (or pass api_key=) and you're done; it reaches the hosted Sesame broker automatically.

from sesame_sdk import Sesame

client = Sesame()                       # reads SESAME_API_KEY
client = Sesame(api_key="sk_live_...")  # ...or pass it explicitly
Self-hosting / local dev — ignore unless you run your own broker

Only if you host Sesame yourself do you need a URL. Override the default (https://getsesame.dev) via the SESAME_BROKER_URL env var or the base_url= argument:

client = Sesame(api_key="sk_live_...", base_url="http://localhost:8000")

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.2.tar.gz (8.8 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.2-py3-none-any.whl (11.2 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: sesame_sdk-0.1.2.tar.gz
  • Upload date:
  • Size: 8.8 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.2.tar.gz
Algorithm Hash digest
SHA256 96e855396f293d97234593692b4d26ec47a2eb01727b4a7291eea637ac26b9ae
MD5 7b7bd81fbdd5f1225ce5db01b71332ac
BLAKE2b-256 a88c79fd4af3b1044f26902bd42d7a2bb6bcc7c6cd39c4ce310a7fe095084d2a

See more details on using hashes here.

File details

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

File metadata

  • Download URL: sesame_sdk-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 11.2 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.2-py3-none-any.whl
Algorithm Hash digest
SHA256 05bce34423acf226aa0eed21fb96ab5debddf695217eaac4f0e7181c5fb8c396
MD5 13db41742cb754cef4150767aef52b68
BLAKE2b-256 349d058c4782c11ddbd0b17ab319654c0fb2e60b8cdaa86febe072c040bf6f8a

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