Session: stripe-webhook-idempotency — 2026-09-01

ledger-api · Codex · branch feat/stripe-webhooks · gpt-5-codex · 2026-09-01 14:00 · 1 msgs · 3 tools · 1 min read · updated 2 months ago

tools: Bash, Edit, Write
← ledger-api Download .md .txt .json
Tool calls
Bash Bash: 1 call (33.3%) 1 Edit Edit: 1 call (33.3%) 1 Write Write: 1 call (33.3%) 1
Token usage100.8K total
Input10.8K
Cache creation21.6K
Cache read64.8K
Output3.6K
Cache hit ratio67%· warming up

Project: ledger-api · Branch: feat/stripe-webhooks · Mode: default · Model: gpt-5-codex

Summary

Made Stripe webhook handling idempotent: every event id is recorded in a processed_events table inside the same transaction as the side effect, so retries from Stripe can never double-credit an invoice.

Conversation

Turn 1 — User

Stripe retries webhooks. Make sure we never apply the same event twice.

Turn 1 — Assistant

Insert the event id into processed_events (unique) in the same transaction as the invoice update; on a unique-violation, return 200 and skip. Signature verification stays first.

@router.post("/webhooks/stripe")
async def stripe_webhook(request: Request, db: Session = Depends(get_db)):
    event = verify_signature(await request.body(), request.headers)
    try:
        with db.begin():
            db.add(ProcessedEvent(id=event.id))
            apply_event(db, event)
    except IntegrityError:
        return {"status": "duplicate"}   # already handled
    return {"status": "ok"}

Tools used in this turn:

  • Edit: ledger/webhooks.py
  • Write: migrations/versions/0004_processed_events.py
  • Bash: pytest tests/test_webhooks.py -q — 6 passed

Connections

  • [[ledger-api]]
  • [[Stripe]]
  • [[Idempotency]]
  • [[PostgreSQL]]

Keyboard shortcuts

⌘K / Ctrl+KOpen command palette
/Focus search
g hGo to home
g pGo to projects
g sGo to sessions
j / kNext / prev row (tables)
?Show this help
EscClose dialogs

Structured queries

Mix key:value filters with free text in the palette:

type:sessionOnly session pages
project:llm-wikiFilter by project name (substring)
model:claudeFilter by model name (substring)
date:>2026-03-01Sessions after a date
date:<2026-04-01Sessions before a date
tags:rustPages mentioning a tag/topic
sort:dateSort results by date (newest first)

Example: type:session project:llm-wiki date:>2026-04 sort:date