Accept a signed approval

You sell to agents. Before you deliver, check the buyer's approval yourself — no Saifuro account needed.

The seller's side of the deal. An agent presents an approval and asks you to deliver; the three-step check tells you whether the approval is real, unaltered, and for this exact transaction. This guide is the operational wrapper around that check — the parts that bite in production.

The short version: verify the signature against the key set, compare the claims against the deal, and never accept a nonce twice.

Cache the key set properly

verdicts.saifuro.com/.well-known/jwks.json allows five minutes of caching, and that number is load-bearing: it is how fast a key rotation propagates. A JOSE library's remote-JWKS helper (jose's createRemoteJWKSet, PyJWT's PyJWKClient, jwx's jwk.Cache) respects it out of the box. A hand-rolled fetch that caches for a day will reject valid verdicts on the first rotation.

During rotation both keys are listed side by side, so verification never has a gap — but only if you re-fetch on schedule.

Check the environment

Sandbox verdicts verify against the same endpoint — deliberately, so integrations can be tested end to end. The kid tells them apart: sandbox keys start with sandbox-. If you deliver real goods, reject sandbox-signed approvals:

import { decodeProtectedHeader } from 'jose';

const { kid } = decodeProtectedHeader(token);
if (kid.startsWith('sandbox-')) {
  throw new Error('sandbox approval presented for a real delivery');
}

Store nonces at least as long as the expiry

An approval expires five minutes after issue, so a replayed nonce only matters inside that window — a store with a ten-minute TTL is enough:

# after a successful verification
added = redis.set(f"nonce:{payload['nonce']}", 1, nx=True, ex=600)
if not added:
    raise ValueError("replay: this approval was already used")

Set it atomically

The nx=True matters: check-then-set as two calls is a race, and two deliveries against one approval is exactly what the nonce exists to prevent.

Compare amounts exactly

request.amount in the claims is the number that was authorized. Compare it against what you are about to charge — not "close enough", not "at most". An approval for 340.00 presented against a 340.50 invoice is a mismatch, and the right response is to decline and say why. The buyer can come back with a fresh approval in seconds.

Keep what you verified

Store the raw verdict_token next to your delivery record. If the deal is ever disputed, the token is your evidence: independently verifiable, bound to amount and recipient, carrying the policy version it was approved under. This is what turns a he-said-she-said into a signature check — but only if you kept the token.

When verification fails

Reject and say which check failed — signature, expiry, environment, nonce, or claims mismatch. The buyer's side can fix four of those five instantly with a fresh request. The one they cannot fix is a bad signature, and that one you especially want to have rejected.

On this page