payment-idempotency — Claude Code skill: stop duplicate charges
A skill for payment connector code that keeps Gateway retries from hitting the acquirer twice and charging the customer again.
npx skills add vtex/skills --skill payment-idempotency -a claude-codeWhat payment-idempotency does
The skill applies when you write Create Payment, Cancel, Capture or Refund handlers in a payment connector, or when duplicate payment requests show up in your logs. It sets the idempotency rules: paymentId is the key for Create Payment, requestId for cancel, capture and refund. A repeat call with the same paymentId returns the stored response instead of calling the acquirer again.
Inside are the payment state transitions (undefined → approved → settled, undefined → denied, approved → cancelled) and TypeScript examples: query the store before processing, then return the exact stored response. Async methods such as Boleto and Pix must stay at status: "undefined" until the acquirer confirms — approving them synchronously is wrong.
Responses belong in a persistent store: PostgreSQL, DynamoDB or VBase for VTEX IO. In-memory storage loses records on restart, and the Gateway retries Create Payment with undefined status for up to 7 days, so each retry reaches the acquirer again. When two retries overlap, last-write-wins can drop a status update, so persist with an etag or ifMatch. Worth checking your storage layer before release.
The skill leaves PPP response shapes and HTTP methods, async callback notifications, PCI compliance and POS terminal payments to their own skills.
What it helps with
- return the stored response on a repeated Create Payment instead of a new charge
- look up
paymentIdin the store before calling the acquirer - block invalid payment state transitions
- keep Boleto and Pix at
undefineduntil the acquirer confirms - protect status updates from being overwritten by overlapping retries
Example prompts for the agent
- check my Create Payment handler for idempotency on
paymentId - why does a Gateway retry create a second charge, and how do I fix it
- add
requestIdhandling to my Refund handler
How to install payment-idempotency
1Skills CLI (Vercel)
npx skills add vtex/skills --skill payment-idempotency -a claude-code2Manually: put the files in place
~/.claude/skills/payment-idempotency/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/payment-idempotency/
1Skills CLI (Vercel)
npx skills add vtex/skills --skill payment-idempotency -a codex2Manually: put the files in place
.agents/skills/payment-idempotency/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add vtex/skills --skill payment-idempotency -a cursor2Manually: put the files in place
.cursor/skills/payment-idempotency/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install vtex/skills payment-idempotency2Manually: put the files in place
.github/skills/payment-idempotency/SKILL.md1Skills CLI (Vercel)
npx skills add vtex/skills --skill payment-idempotency -a gemini-cli2Platform CLI
gemini skills install https://github.com/vtex/skills --path skills/payment-idempotencyManually: put the files in place
.devin/skills/payment-idempotency/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add vtex/skills --skill payment-idempotency -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
Step by step, with commands for each platform: How to install skills in Claude Code: five ways
Questions about payment-idempotency
How do I install payment-idempotency in Claude?
Run npx skills add vtex/skills --skill payment-idempotency -a claude-code. The skill lands at ~/.claude/skills/payment-idempotency/SKILL.md.
What does payment-idempotency do?
It lays out idempotency rules for a payment connector: paymentId and requestId as keys, valid state transitions, and retry semantics for cancel and refund. The goal is no duplicate charges when the Gateway retries.
Which skills does it work with?
For POS terminal payments, pair it with payment-ppp-pos. PPP response shapes, async callback notifications and PCI compliance live in separate skills.