This package is abandoned and no longer maintained. The author suggests using the mohamedhekal/oncegate package instead.

Stripe-style Idempotency-Key middleware for Laravel APIs with response replay and concurrent locks

Maintainers

Package info

github.com/mohamedhekal/oncegate

pkg:composer/mohamedmohamedhekal/oncegate

Transparency log

Statistics

Installs: 0

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v0.1.0 2026-07-16 14:23 UTC

This package is auto-updated.

Last update: 2026-07-16 14:40:23 UTC


README

Stripe-style Idempotency-Key middleware for Laravel APIs. Store the first response, replay safe retries, reject payload mismatches, and return 409 while a request with the same key is still in flight.

Tests License: MIT

Update badge URLs after publishing the GitHub repository.

Problem

Mobile apps, payment clients, and flaky networks retry POST/PUT requests. Without idempotency keys, those retries create duplicate orders, charges, or shipments.

Features

  • Idempotency-Key header handling (name configurable)
  • Request fingerprinting (method + path + body hash, optional user scope)
  • Response replay with Idempotent-Replayed: true
  • Fingerprint mismatch → 422
  • In-flight conflict → 409
  • Cache driver (default) and database driver
  • Optional required-key mode
  • oncegate:purge for expired database records

Requirements

  • PHP 8.2+
  • Laravel 11 or 12

Installation

composer require mohamedhekal/oncegate
php artisan vendor:publish --tag=oncegate-config
php artisan migrate

Quick start

use Illuminate\Support\Facades\Route;

Route::middleware(['api', 'oncegate'])->group(function () {
    Route::post('/orders', [OrderController::class, 'store']);
});

Client:

POST /orders HTTP/1.1
Idempotency-Key: 8e2f1a6c-9b0d-4c3e-a1f2-7d6c5b4a3210
Content-Type: application/json

{"sku":"SKU-1","qty":1}

First response is executed normally. Retries with the same key and body receive the stored response and header Idempotent-Replayed: true.

Alias middleware name: idempotency (same class).

Configuration

Key Default Meaning
header Idempotency-Key Incoming header name
methods POST, PUT, PATCH, DELETE Methods that participate
required false Abort 400 when header missing
driver cache cache or database
ttl 86400 Stored response lifetime (seconds)
lock_ttl 60 Processing marker TTL (cache)
fingerprint.include_user true Scope keys per authenticated user

Architecture

See docs/architecture.md.

Testing

composer install
composer test

Security notes

  • Keys are scoped by user when fingerprint.include_user is enabled.
  • Do not log raw idempotency payloads if they contain secrets—pair with a redaction package if needed.
  • Prefer Redis cache in production for atomic add semantics under load.

License

MIT — see LICENSE.

Credits

Mohamed Hekal.