Versioning

January 6, 2026 - v1.3.0

Mandatory idempotency key requirement for refund and payout operations
Security Enhancement
Breaking change requiring immediate action for refund and payout integrations

Overview

This release introduces a mandatory idempotency key requirement for refund and payout operations to enhance transaction safety and prevent accidental duplicate processing. This is a breaking change for merchants using refund or payout endpoints.

Action Required: All integrations using refund or payout APIs must be updated to include the X-Idempotent-Key header before January 20, 2026. After this date, requests without this header will be rejected with 400 Bad Request.

Breaking Changes

1. Mandatory Idempotency Key for Refunds

Breaking ChangeImpact: Critical

What's Changed

The X-Idempotent-Key header is now required for all refund operations:

Endpoint Affected:

POST /api/v1/payment-gateway/order/refund

New Required Header:

HeaderTypeRequiredDescription
X-Idempotent-KeystringYesUnique key to prevent duplicate refunds (UUID recommended)

Example Request:

curl -X POST https://merchant.dv.vai247.pro/api/v1/payment-gateway/order/refund \
  -H "X-App-Id: your-app-id" \
  -H "X-Api-Key: your-api-key" \
  -H "X-Timestamp: 1704542400" \
  -H "X-Idempotent-Key: 550e8400-e29b-41d4-a716-446655440000" \
  -H "Content-Type: application/json" \
  -d '{
    "order_id": "ord_abc123xyz",
    "amount": 50.00,
    "reason": "Customer request"
  }'

Impact of Change

  • Prevents duplicate refunds caused by network retries, user error, or system failures
  • Protects merchants from financial loss due to accidental duplicate refund processing
  • Industry standard practice for financial operations
  • 24-hour idempotency window: Same key returns cached result if retried within 24 hours

What Will Break

Requests without X-Idempotent-Key will fail with:

{
  "error": {
    "code": "missing_idempotent_key",
    "message": "X-Idempotent-Key header is required for refund operations",
    "request_id": "req_xyz789"
  }
}

Migration Steps

Install UUID Library

# Node.js
npm install uuid

# Golang
go get github.com/google/uuid

Update Refund Function

Add idempotent key generation to your refund code

Test Integration

Verify refunds work with the new header in sandbox

Deploy to Production

Roll out changes before January 20, 2026

Code Examples

import "github.com/google/uuid"

func refundOrder(orderID string, amount float64, reason string) error {
    // Generate unique idempotent key
    idempotentKey := uuid.New().String()

    req.Header.Set("X-App-Id", os.Getenv("DVPAY_APP_ID"))
    req.Header.Set("X-Api-Key", os.Getenv("DVPAY_API_KEY"))
    req.Header.Set("X-Timestamp", fmt.Sprintf("%d", time.Now().Unix()))
    req.Header.Set("X-Idempotent-Key", idempotentKey)

    // Make API call...
}

Implementation Reference

Refund Order API Documentation


2. Mandatory Idempotency Key for Payouts

Breaking ChangeImpact: Critical

What's Changed

The X-Idempotent-Key header is now required for all payout operations:

Endpoint Affected:

POST /api/v1/payment-gateway/order/payout

New Required Header:

HeaderTypeRequiredDescription
X-Idempotent-KeystringYesUnique key to prevent duplicate payouts (UUID recommended)

Example Request:

curl -X POST https://merchant.dv.vai247.pro/api/v1/payment-gateway/order/payout \
  -H "X-App-Id: your-app-id" \
  -H "X-Api-Key: your-api-key" \
  -H "X-Timestamp: 1704542400" \
  -H "X-Idempotent-Key: 660f9500-f39c-51e5-b827-557766551111" \
  -H "Content-Type: application/json" \
  -d '{
    "account_id": "acc_123",
    "amount": 200.00,
    "currency": "USD",
    "description": "Monthly commission"
  }'

Impact of Change

  • Prevents duplicate payouts caused by network issues, retries, or user error
  • Protects merchant balance from unintended double payments
  • Critical for financial accuracy in marketplace and platform businesses
  • Safe retry mechanism: Same key returns original response without duplicate processing

What Will Break

Requests without X-Idempotent-Key will fail with:

{
  "error": {
    "code": "missing_idempotent_key",
    "message": "X-Idempotent-Key header is required for payout operations",
    "request_id": "req_abc456"
  }
}

Migration Steps

Install UUID Library

Same as refund migration above

Update Payout Function

Add idempotent key generation to your payout code

Test Integration

Verify payouts work with the new header in sandbox

Deploy to Production

Roll out changes before January 20, 2026

Code Examples

import "github.com/google/uuid"

func processPayout(accountID string, amount float64, currency string) error {
    // Generate unique idempotent key
    idempotentKey := uuid.New().String()

    req.Header.Set("X-App-Id", os.Getenv("DVPAY_APP_ID"))
    req.Header.Set("X-Api-Key", os.Getenv("DVPAY_API_KEY"))
    req.Header.Set("X-Timestamp", fmt.Sprintf("%d", time.Now().Unix()))
    req.Header.Set("X-Idempotent-Key", idempotentKey)

    // Make API call...
}

Implementation Reference

Payout API Documentation


New Features

1. Idempotency Protection Window

AdditionImpact: Medium

What's New

DVPay now caches idempotent request results for 24 hours, enabling safe retries:

How It Works:

  1. First request with X-Idempotent-Key: abc-123 → Processes refund/payout
  2. Retry with same X-Idempotent-Key: abc-123 → Returns cached result (no duplicate processing)
  3. After 24 hours → Key expires, can be reused

Benefits:

  • Safe network retry logic: Retry failed requests without fear of duplicates
  • Handles timeouts gracefully: If client times out but server processes, retry returns the result
  • Automatic deduplication: Server-side protection against duplicate submissions
  • Prevents user double-click issues: Multiple submissions with same key are handled safely

Example Scenario:

// Request times out due to network issue
try {
  await refundOrder('ord_123', 50.00, 'refund', 'key-abc-123');
} catch (error) {
  // Network timeout, but refund may have processed
}

// Safe to retry with same idempotent key
try {
  // If refund processed: returns original result
  // If refund didn't process: processes now
  await refundOrder('ord_123', 50.00, 'refund', 'key-abc-123');
} catch (error) {
  // Handle actual error
}

Implementation Reference

Error Handling - Idempotency


2. New Error Code: missing_idempotent_key

AdditionImpact: Medium

What's New

New error code returned when X-Idempotent-Key header is missing:

Error Response:

{
  "error": {
    "code": "missing_idempotent_key",
    "message": "X-Idempotent-Key header is required for this operation",
    "details": {
      "endpoint": "/api/v1/payment-gateway/order/refund",
      "required_header": "X-Idempotent-Key",
      "documentation": "https://docs.dvpay.com/api-reference/refund-order"
    },
    "request_id": "req_xyz789",
    "timestamp": 1704542400
  }
}

HTTP Status Code: 400 Bad Request

Affected Endpoints:

  • POST /api/v1/payment-gateway/order/refund
  • POST /api/v1/payment-gateway/order/payout

Impact of Feature

  • Clear error messaging for missing headers
  • Includes documentation link for quick fix
  • Helps developers quickly identify and fix integration issues

Implementation Reference

Error Handling Documentation


Documentation Updates

All relevant documentation has been updated to reflect the idempotency key requirement:

Authentication

Added idempotency key documentation

Refund Order

Updated with required header and code examples

Payout

Updated with required header and code examples

Error Handling

Added missing_idempotent_key error code

Security Best Practices

Added idempotency implementation guide

Key Features

Updated to highlight idempotency protection


Migration Timeline

January 6, 2026 (Today)

Grace period begins. Both with and without X-Idempotent-Key accepted, but warnings logged.

January 13, 2026

Deprecation warnings in response headers. All responses include X-DVPay-Deprecation-Warning header.

January 20, 2026

Enforcement begins. Requests without X-Idempotent-Key rejected with 400 Bad Request.

January 27, 2026

Full enforcement. All merchants must have updated integrations.


Migration Checklist

Before January 20, 2026, complete these steps:

Review Integration

Identify all code calling refund or payout APIs

Install UUID Library

Add UUID generation capability to your project

Update Refund Functions

Add X-Idempotent-Key header with unique UUID

Update Payout Functions

Add X-Idempotent-Key header with unique UUID

Test in Sandbox

Verify both endpoints work with new header

Update Error Handling

Add handling for missing_idempotent_key error

Deploy to Production

Roll out changes before January 20, 2026

Monitor Logs

Check for deprecation warnings and fix any missed instances


Testing Guide

Sandbox Testing

Test your updated integration in the sandbox environment:

# Test Refund with Idempotent Key
curl -X POST https://sandbox.merchant.dv.vai247.pro/api/v1/payment-gateway/order/refund \
  -H "X-App-Id: sandbox-app-id" \
  -H "X-Api-Key: sandbox-api-key" \
  -H "X-Timestamp: $(date +%s)" \
  -H "X-Idempotent-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"order_id": "test_order_123", "amount": 10.00}'

Test Idempotency Behavior

Verify that duplicate requests return the same result:

# First request - processes refund
IDEMPOTENT_KEY="550e8400-e29b-41d4-a716-446655440000"
curl -X POST $URL -H "X-Idempotent-Key: $IDEMPOTENT_KEY" -d '{...}'

# Second request - returns cached result, no duplicate
curl -X POST $URL -H "X-Idempotent-Key: $IDEMPOTENT_KEY" -d '{...}'

Test Error Handling

Verify proper error when header is missing:

# Request without idempotent key (should fail after Jan 20)
curl -X POST $URL -d '{...}'
# Expected: 400 Bad Request with missing_idempotent_key error

Frequently Asked Questions

Q: Why is this change necessary?

A: Idempotency keys prevent duplicate refunds and payouts caused by network retries, timeouts, or user error. This protects both merchants and customers from financial losses due to duplicate transactions.

Q: Can I reuse the same idempotent key?

A: After 24 hours, keys expire and can be reused. However, we recommend generating a unique UUID for each operation.

Q: What happens if I retry with the same key?

A: The API returns the original response without processing a duplicate transaction. This is safe and expected behavior.

Q: Do I need idempotent keys for other endpoints?

A: No, only refund and payout operations require idempotency keys. Other endpoints (create order, generate QR, etc.) do not require this header.

Q: What UUID version should I use?

A: UUID v4 (random) is recommended. Most UUID libraries default to v4.

Q: What if my language doesn't have a UUID library?

A: Any unique string works. Common alternatives:

  • Timestamp + random string: ${Date.now()}-${Math.random()}
  • Hash of request data: sha256(orderid + amount + timestamp)
  • Database-generated unique ID

Technical Details

Idempotency Key Requirements

  • Format: Any string up to 255 characters
  • Recommended: UUID v4 format
  • Validation: Must be non-empty
  • Storage: Cached server-side for 24 hours
  • Scope: Per merchant account

Performance Impact

  • Latency: No measurable increase (<1ms overhead)
  • Storage: Minimal (keys cached in Redis)
  • Rate Limits: Unchanged

Backward Compatibility

During grace period (Jan 6-20, 2026):

  • Requests without header: ✅ Accepted (with warning)
  • Requests with header: ✅ Accepted

After enforcement (Jan 20+, 2026):

  • Requests without header: ❌ Rejected (400 Bad Request)
  • Requests with header: ✅ Accepted

Support

If you need assistance migrating your integration:

Need extra time? Contact support@dvpay.com before January 15, 2026 to discuss your migration timeline.

Summary

This release introduces mandatory idempotency key protection for refund and payout operations—a critical security enhancement that prevents duplicate transactions. All merchants must update their integrations before January 20, 2026 to avoid service disruption.

Action Required: Add X-Idempotent-Key header to all refund and payout API calls.