Skip to content
Back to News
Changelog

A blank Idempotency-Key is now refused instead of ignored

apibugfix

If you sent Idempotency-Key with a blank value — an empty string, or one made only of spaces — the gateway ignored it. Not rejected: ignored. HTTP strips the whitespace at the edges of a header value, so the header reached us empty, and an empty key looked exactly like no key at all. Every retry was executed as a brand-new request.

Measured on 26 August, before the fix: two identical POST /v1/contacts calls carrying three spaces as the key returned two 201s and created two different contacts. No warning, no header, nothing in the response to tell the two cases apart. A key that cannot protect anything is worse than no key, because you believe you are covered.

It now returns 400 with the code idempotency_key_blank.

What this changes for you

If your integration derives keys from your own data — a padded reference, a field that can be empty, a String(x).padStart(...) — a request that used to return 201 will now return 400. That request was never protected; the difference is that you now find out.

If you do not need idempotency for a request, omit the header rather than sending it empty. Omitting it remains perfectly legal and is unchanged.

Users of @getpeppr/sdk 4.8.1 and later were already covered: the SDK refuses a blank key locally and sends nothing. This closes the same hole for anyone calling the API over plain HTTP, which includes several of our platform customers.

The three bounds of the refusal

Worth stating, because "a blank key is always refused" would be too strong:

If you use our n8n template

The published send-invoice workflow passed {{ $json.idempotencyKey }} straight through, which renders as an empty string when the field is absent. It now falls back to the n8n execution id, which is a better key than an empty one. Re-import the template if you built on it.