Z2 ZI2 Verify
Start free
Docs

Reliability

Idempotency keys

Include an Idempotency-Key header on any POST or PATCH. If we've seen the same key + same body from your account in the last 24 hours, we replay the cached response instead of re-executing.

Rules

  • Same key, same body → cached response, same HTTP status, plus Idempotent-Replay: true header.
  • Same key, DIFFERENT body → 409 CONFLICT. This is your bug; we won't quietly overwrite.
  • New key → normal execution, response cached for 24h.
  • Missing header → normal execution, no caching.
  • Key length: 8–128 chars.
  • 5xx responses are never cached — you can safely retry.

Recommended: UUID v7

Time-ordered UUIDs give you a natural key + retry-safe uniqueness. In a retry loop, keep the SAME key across all attempts — that's what makes retries safe.

Node.js
import { v7 as uuid } from 'uuid';

async function validateWithRetry(email) {
  const key = uuid();  // ← generated ONCE, reused across attempts
  for (let attempt = 0; attempt < 5; attempt++) {
    try {
      return await fetch('/v1/validate', {
        method: 'POST',
        headers: {
          'authorization': `Bearer ${process.env.API_KEY}`,
          'content-type': 'application/json',
          'idempotency-key': key,   // ← SAME key on every retry
        },
        body: JSON.stringify({ email }),
      });
    } catch (err) {
      await sleep(Math.min(2 ** attempt * 1000, 30_000));
    }
  }
}

What's cached

The full JSON response body + status code + Idempotent-Replay: true header. The receipt sig is deterministic (signed once at first request), so a replay returns the identical bytes — verify-able against the same canonical form.

Not cached

  • GET requests (already idempotent by contract).
  • 5xx responses.
  • Auth endpoints — login/register handle their own idempotency semantics (unique email constraint + magic-token single-use).