← Blog/Developer

Understanding Idempotency Keys in Payment APIs

Mar 15, 2026 · 4 min read

Network retries can create duplicate payments. Idempotency keys prevent this. This guide explains how to use them in the Bekena API correctly.

When you make an API request to create a payment, your network call might fail mid-flight. Your code retries. Did the first request succeed and create a payment, or did it fail? Without idempotency keys, you might create two identical payments for the same order.

What is an Idempotency Key?

An idempotency key is a unique string you include in your API request. If you make the same request twice with the same idempotency key, the API treats it as a single request and returns the same response. The second call doesn't create a second payment — it returns the result of the first call.

How to Use Idempotency Keys with Bekena

typescript
// Generate a deterministic idempotency key for this order // Using order ID ensures retries for the same order are safe const idempotencyKey = `payment_${orderId}_${userId}`; const response = await fetch('https://api.bekena.com/v1/payments', { method: 'POST', headers: { 'x-api-key': process.env.BEKENA_KEY!, 'Idempotency-Key': idempotencyKey, 'Content-Type': 'application/json', }, body: JSON.stringify({ amount: '99.00', currency: 'USDT_TRC20', order_id: orderId, }), }); // Safe to retry this exact call — same key returns same payment

Rules for Idempotency Keys

  • ✓Must be unique per operation — not per API key or per session
  • ✓Use a deterministic key based on your business data (order ID + user ID)
  • ✓Keys are valid for 24 hours — after that, the same key may create a new resource
  • ✓Never reuse a key for a different operation (e.g., don't use the same key for two different orders)
  • ✓Keys are case-sensitive strings up to 255 characters

Idempotency in Webhook Handlers

Bekena may deliver the same webhook event multiple times due to network issues or retries. Your webhook handler must also be idempotent. Use the payment ID from the event as a key to check if you've already processed this specific payment.

typescript
app.post('/webhook', async (req, res) => { const { event, data } = parseWebhook(req); if (event === 'payment.confirmed') { // Check if we already processed this payment const alreadyProcessed = await db.processedPayments.exists(data.id); if (alreadyProcessed) { return res.json({ received: true }); // idempotent: no-op } // First time seeing this payment — process it await db.orders.markAsPaid(data.order_id); await db.processedPayments.insert(data.id); } res.json({ received: true }); });

Testing Idempotency

In the Bekena sandbox, you can test idempotency by making the same API call twice with the same Idempotency-Key header and verifying you receive the same payment object both times. Check that only one payment record was created in the Bekena dashboard — you should see one entry, not two.

Ready to accept crypto payments?

Start with a free sandbox account

Create Free Account →

Related articles

Developer

How to Properly Verify Bekena Webhooks (With Code Examples)

Developer

Building a Telegram Bot That Accepts Crypto Payments

Guide

Complete Guide to Accepting USDT Payments for Your Business