How to check if a Stamped Mandate (and its JWTs) has been revoked
JWTs issued by the have expiry times, but a user can also revoke a before its expiry. When a mandate is revoked, all JWTs issued against it are invalidated. As a verifier, you should check revocation status to avoid accepting credentials that the user has withdrawn.A Stamped Mandate is delivered over the API as a PINT (header x-sumvin-pint-token), so the status endpoint, the pint_uri claim, and the PINT-4xx error codes below all use the PINT identifier on the wire.
Authentication: API key via Authorization: Bearer header. This endpoint is deliberately permissive — any authenticated third-party caller with a valid SIS API key can check the status of any Stamped Mandate they’ve been presented with. No specific scope is required.
The SRI contains colons that must be URL-encoded as %3A in the path. Most HTTP libraries handle this automatically with encodeURIComponent() or urllib.parse.quote().
true if the mandate is active and not expired; false if revoked or expired
reason
string or null
null when valid; "revoked" or "expired" when invalid
revoked_at
integer (epoch milliseconds) or null
Timestamp of when the mandate was revoked. null when the mandate is valid or has only expired without explicit revocation
_links.self
object
Link back to this status endpoint
_links.pint
object
Link to the full Stamped Mandate resource
Timestamps default to epoch milliseconds. To receive ISO 8601 strings instead (e.g., "2026-02-13T11:30:00Z"), send the header X-Timestamp-Format: iso8601. This applies to revoked_at and any other _at fields in the response.
The revocation check endpoint is designed for low latency (< 100ms p99) and responses are already cached server-side for 30 seconds. You should still cache on your side to avoid excessive calls:Recommended approach: Cache the valid: true response for 30 seconds. This matches the server-side cache TTL and balances freshness (revocations propagate within 30s) with throughput.Do not cache indefinitely. A Stamped Mandate that was valid at verification time may be revoked seconds later. The 30-second TTL provides a reasonable window.Cache valid: false longer. Once a Stamped Mandate is revoked or expired, it doesn’t come back. You can cache negative results for the duration of the JWT’s remaining lifetime.
import { LRUCache } from "lru-cache";const revocationCache = new LRUCache<string, boolean>({ max: 10000, ttl: 30 * 1000, // 30 seconds for valid results});async function checkRevocationCached(pintUri: string): Promise<boolean> { const cached = revocationCache.get(pintUri); if (cached !== undefined) return cached; const isValid = await checkRevocation(pintUri); revocationCache.set(pintUri, isValid, { ttl: isValid ? 30 * 1000 : 300 * 1000, // 30s for valid, 5min for revoked }); return isValid;}
Always check on the first request for a given Stamped Mandate in a session. After that, your cache handles subsequent checks within the TTL.Skip the check if you don’t have an SIS API key. JWT signature verification and expiry checking are still valid without revocation checking — you just won’t catch mandates that were revoked before their natural expiry.