nano-api / uniq

The same webhook,
delivered three times

Almost every queue and webhook is at-least-once, so the duplicate is not a bug you can fix upstream. You hand this a key you already have and it tells you whether that key has arrived before.

Take a key Curl walkthrough

Free. Signup is one curl and the key comes back in the response. No form, no card, nobody to ask.

POST /v1/uniq/evt_1JK2nX8s ttl 24h
  1. 02:14:07 201 first_time: true charge card
  2. 02:14:09 200 hits: 2 skipped
  3. 02:19:41 200 hits: 3 skipped

One delivery, three arrivals, one charge.

It does not make the key. You already have one.

A Stripe event id, a delivery id, an order number, a message id. Generating a unique value is a pure function and your language already has it. What it cannot give you is memory that every instance of your app shares and that survives a deploy.

# the key is one you already have: the delivery id
curl -fsS -X POST "https://uniq.nano-api.com/v1/uniq/$DELIVERY_ID?ttl=86400" \
  -H "Authorization: Bearer $NANO_API_KEY"
# 201 {"first_time": true,  "hits": 1}   <- yours, do the work
# 200 {"first_time": false, "hits": 2}   <- somebody already did

The status code carries the answer as well as the body: 201 the first time, 200 after.

What goes wrong without one

A table and a unique index

  • Two deliveries land together, both SELECT, both see nothing
  • Both proceed, and the card is charged twice
  • The fix is to let the insert be the check, which is not what you wrote
  • And now you own a table that grows forever

With NanoUniq

  • One statement decides; the insert is the check
  • Forty simultaneous claims produce exactly one winner
  • Rows expire on their own, so nothing grows forever
  • No migration, no index, no cleanup job

Claim, work, and give it back if the work failed

RESPONSE=$(curl -sf -X POST "https://uniq.nano-api.com/v1/uniq/$DELIVERY_ID" \
  -H "Authorization: Bearer $NANO_API_KEY")

if [ "$(jq -r .first_time <<< "$RESPONSE")" = "true" ]; then
  ./process.sh "$DELIVERY_ID" || curl -sf -X DELETE \
    "https://uniq.nano-api.com/v1/uniq/$DELIVERY_ID" -H "Authorization: Bearer $NANO_API_KEY"
fi

Without the DELETE, a crash between claiming and finishing means the work never happens at all: the key is held and every retry is told it is late. That is the one sharp edge here, and it is the same trade every idempotency layer makes.

Guarantees, and the limits

Exactly one caller is told first_time: true. That is decided by the hit count the write returns, not by comparing timestamps: two arrivals in the same second would both match "first seen now", and both would be told they were first, which is the one answer this must never give twice.

A key claims a window, not eternity. Default 24 hours, 30 days at most, then it expires and the next arrival is new again. Set the ttl above your upstream's retry horizon. Permanent memory would make this a database rather than an operation, and the whole point is that you do not have to run one.

Looking is free and changes nothing: GET /v1/uniq/:key works with a read-only key, so a dashboard or a support script can check without claiming.

Using it with the others

Relay delivers at-least-once and every call carries X-NanoRelay-Run-Id, which is exactly the kind of key this takes. Pass it here and a retried run stops being a second run.

How to, in curl What this is