Quickstart

Python / FastAPI

Integrate Seshn into a FastAPI application using httpx for direct REST calls.

Prerequisites

  • Python 3.9+
  • A Seshn account with an API key (sign up)

1. Set up the project

terminal
1mkdir seshn-fastapi && cd seshn-fastapi
2python -m venv .venv && source .venv/bin/activate
3pip install fastapi uvicorn httpx

2. Create a Seshn HTTP client

There is no Python SDK yet, so use httpx to call the REST API directly. This thin wrapper handles authentication and error checking.

seshn_client.py
1import os
2import httpx
3
4BASE_URL = "https://api.seshn.net"
5API_KEY = os.environ["SESHN_API_KEY"]
6
7client = httpx.AsyncClient(
8 base_url=BASE_URL,
9 headers={
10 "Authorization": f"Bearer {API_KEY}",
11 "Content-Type": "application/json",
12 },
13)
14
15
16async def get_availability(service_id: str, from_date: str, to_date: str) -> list[dict]:
17 """Query available slots for a service within a date range."""
18 resp = await client.get(
19 "/v1/availability",
20 params={"serviceId": service_id, "from": from_date, "to": to_date},
21 )
22 resp.raise_for_status()
23 return resp.json()["data"]
24
25
26async def create_booking(slot_id: str, contact_id: str, seats: int = 1) -> dict:
27 """Create a new booking for a slot."""
28 resp = await client.post(
29 "/v1/bookings",
30 json={"slotId": slot_id, "contactId": contact_id, "seats": seats},
31 )
32 resp.raise_for_status()
33 return resp.json()["booking"]
34
35
36async def confirm_booking(booking_id: str) -> dict:
37 """Confirm a pending or held booking."""
38 resp = await client.post(f"/v1/bookings/{booking_id}/confirm", json={})
39 resp.raise_for_status()
40 return resp.json()["booking"]

3. Build the FastAPI app

Three endpoints: check availability, book a slot, and receive webhooks.

main.py
1import hashlib
2import hmac
3import os
4
5from fastapi import FastAPI, Request, HTTPException
6from pydantic import BaseModel
7
8from seshn_client import get_availability, create_booking, confirm_booking
9
10app = FastAPI()
11
12WEBHOOK_SECRET = os.environ.get("SESHN_WEBHOOK_SECRET", "")
13
14
15# ── Schemas ──────────────────────────────────────────────────
16
17class BookRequest(BaseModel):
18 slot_id: str
19 contact_id: str
20 seats: int = 1
21
22
23# ── GET /availability ────────────────────────────────────────
24
25@app.get("/availability")
26async def availability(service_id: str, from_date: str, to_date: str):
27 slots = await get_availability(service_id, from_date, to_date)
28 return {"slots": slots, "count": len(slots)}
29
30
31# ── POST /book ───────────────────────────────────────────────
32
33@app.post("/book")
34async def book(body: BookRequest):
35 booking = await create_booking(body.slot_id, body.contact_id, body.seats)
36 confirmed = await confirm_booking(booking["id"])
37 return confirmed
38
39
40# ── POST /webhooks ───────────────────────────────────────────
41
42@app.post("/webhooks")
43async def webhooks(request: Request):
44 signature = request.headers.get("x-webhook-signature", "")
45 event = request.headers.get("x-webhook-event", "")
46 payload = await request.body()
47
48 if not verify_signature(payload, signature, WEBHOOK_SECRET):
49 raise HTTPException(status_code=401, detail="Invalid signature")
50
51 data = await request.json()
52
53 match event:
54 case "booking.confirmed":
55 # Send confirmation email, sync calendar, etc.
56 pass
57 case "booking.cancelled":
58 # Process refund, notify staff, etc.
59 pass
60 case "payment.succeeded":
61 # Update your records
62 pass
63
64 return {"received": True}
65
66
67# ── Signature verification ───────────────────────────────────
68
69def verify_signature(payload: bytes, header: str, secret: str) -> bool:
70 """Verify the HMAC-SHA256 signature from Seshn webhooks."""
71 expected = "sha256=" + hmac.new(
72 secret.encode(),
73 payload,
74 hashlib.sha256,
75 ).hexdigest()
76
77 return hmac.compare_digest(header, expected)

4. Run it

terminal
1SESHN_API_KEY=sk_test_... uvicorn main:app --reload --port 3001

5. Test the endpoints

terminal
1# Check availability
2curl "http://localhost:3001/availability?service_id=svc_yoga_class&from_date=2026-03-20&to_date=2026-03-27"
3
4# Create a booking
5curl -X POST http://localhost:3001/book \
6 -H "Content-Type: application/json" \
7 -d '{"slot_id": "slot_...", "contact_id": "ct_jane_doe", "seats": 1}'

Adding type safety

For stronger type guarantees, define Pydantic models that match the Seshn API responses. You can generate these from the OpenAPI spec using tools like datamodel-code-generator.

terminal
1pip install datamodel-code-generator
2datamodel-codegen --url https://api.seshn.net/openapi.json --output models.py

What's next