charanjit-singh/lovable-skills/payment-webhook-idempotency

Trust tier 3
  • community
Source check pending

Checking that the SKILL.md file is still in the repository.

Use when Stripe or payment webhooks fire twice, need duplicate event handling, stripe_webhook_events table, ordering, or safe retries. Not for first-time webhook setup without idempotency concerns (use stripe-payment-webhooks).

Install

npx vskill@latest install charanjit-singh/lovable-skills/payment-webhook-idempotency

SKILL.md

Payment webhook idempotency

Stripe retries webhooks on non-2xx, slow responses, or network blips. Handlers must be safe to run multiple times for the same event.id.

Rules

  1. Insert `event.id` first (or check existence) before side effects.
  2. On duplicate event.id, return 200 immediately — do not re-grant credits or extend subscription twice.
  3. Side effects (DB upsert, emails, credits) must be upserts keyed by stable IDs (subscription_id, payment_intent_id), not blind inserts.

Table

sql
create table public.stripe_webhook_events (
id text primary key,
type text not null,
livemode boolean,
processed_at timestamptz not null default now()
);
-- RLS: no client access; edge function uses service role only
alter table public.stripe_webhook_events enable row level security;
-- no policies for anon/authenticated

Handler flow

receive event
→ verify signature
→ if event.id exists in stripe_webhook_events → 200 OK (duplicate)
→ begin logical work
→ upsert subscription / order (idempotent on stripe_subscription_id)
→ insert stripe_webhook_events
→ 200 OK

If work fails after partial writes, prefer:

  • Transaction where possible, or
  • Compensating upsert on retry, or
  • Insert event id only after success (accept rare double-work on crash — mitigate with unique constraints on business keys)

Unique constraints (business layer)

sql
alter table public.subscriptions
add constraint subscriptions_stripe_sub_id_unique unique (stripe_subscription_id);
create table public.orders (
id uuid primary key default gen_random_uuid(),
stripe_payment_intent_id text unique,
user_id uuid not null,
amount_cents int not null,
status text not null
);

Ordering

Events may arrive out of order (subscription.updated before checkout.session.completed). Upsert from latest Stripe object via API retrieve when unsure, or handle both paths to the same upsert function.

Avoid

  • insert into credits (amount) values (100) without idempotency key per event.
  • Returning 500 after successfully granting access (causes retry + duplicate grant).
  • Deleting webhook event rows in production.

Checklist

  • [ ] Primary key = Stripe event.id
  • [ ] Duplicate returns 200
  • [ ] Business tables have unique Stripe IDs

Security

  • Security scanPassed, 90 of 100Pattern checks on the skill's files.
  • Model reviewPassed

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
10
Repository forks
9
7-day trend score
12

Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/charanjit-singh/lovable-skills/payment-webhook-idempotency/badge)](https://verified-skill.com/skills/charanjit-singh/lovable-skills/payment-webhook-idempotency)

Something wrong with this skill or its page? Tell us.