Signed Attribution Tokens (SLAT)

A SLAT (Syndicate Links Attribution Token) is a cryptographically signed, short-lived token that binds a single conversion event to a specific agent identity. SLATs replace cookies as the attribution mechanism in agent commerce — they are minted by the referring agent, submitted with the attribution event, and validated server-side to confirm the referral is legitimate.

Token Structure

A SLAT token is a base64url-encoded JSON payload with an appended HMAC-SHA256 signature. The decoded structure:

{
  "v": "slat_v1",
  "agent_key": "aff_agent_abc123",
  "nonce": "550e8400-e29b-41d4-a716-446655440000",
  "ts": 1712234400,
  "order_ref": "order_001",
  "merchant_id": "merch_xyz"
}

Field Definitions

FieldTypeDescription
vstringToken version. Current: slat_v1
agent_keystringThe aff_agent_ key that is claiming attribution
noncestringUUID v4 — unique per token, used for replay protection
tsintegerUnix timestamp (seconds) when the token was minted
order_refstringOrder or session identifier linking to the conversion
merchant_idstringThe merchant program the referral targets

Signature

The signature is computed as:

HMAC-SHA256(agent_secret, base64url(payload))

Where agent_secret is the secret component of the aff_agent_ key pair. The full token is:

slat_v1_<base64url(payload)>.<base64url(signature)>

Minting a Token

Tokens are minted client-side by the agent at the moment of recommendation. The agent holds the aff_agent_ key and its associated secret.

Python example:

import json
import hmac
import hashlib
import base64
import uuid
import time

def mint_slat(agent_key, agent_secret, merchant_id, order_ref=None):
    payload = {
        "v": "slat_v1",
        "agent_key": agent_key,
        "nonce": str(uuid.uuid4()),
        "ts": int(time.time()),
        "order_ref": order_ref or "",
        "merchant_id": merchant_id
    }

    payload_b64 = base64.urlsafe_b64encode(
        json.dumps(payload).encode()
    ).decode().rstrip("=")

    signature = hmac.new(
        agent_secret.encode(),
        payload_b64.encode(),
        hashlib.sha256
    ).digest()

    sig_b64 = base64.urlsafe_b64encode(signature).decode().rstrip("=")

    return f"slat_v1_{payload_b64}.{sig_b64}"

Node.js example:

import crypto from "crypto";
import { v4 as uuidv4 } from "uuid";

function mintSlat(agentKey, agentSecret, merchantId, orderRef = "") {
  const payload = {
    v: "slat_v1",
    agent_key: agentKey,
    nonce: uuidv4(),
    ts: Math.floor(Date.now() / 1000),
    order_ref: orderRef,
    merchant_id: merchantId,
  };

  const payloadB64 = Buffer.from(JSON.stringify(payload))
    .toString("base64url");

  const signature = crypto
    .createHmac("sha256", agentSecret)
    .update(payloadB64)
    .digest("base64url");

  return `slat_v1_${payloadB64}.${signature}`;
}

Validation Flow

Server-side validation follows these steps in order:

  1. Parse — split the token into payload and signature components
  2. Verify signature — recompute HMAC-SHA256 using the agent's registered secret and compare against the submitted signature
  3. Check version — confirm v is slat_v1 (or a supported version)
  4. Check timestamp — confirm ts is within the attribution window (default: 24 hours)
  5. Check nonce — confirm the nonce has not been used before (replay protection)
  6. Match agent key — confirm the agent_key is registered and active
  7. Record nonce — store the nonce to prevent future replay

If any step fails, the token is rejected with a specific error code (invalid_signature, token_expired, nonce_replay, agent_key_inactive).

Replay Protection

The UUID v4 nonce ensures each SLAT token can only be used once. After successful validation, the nonce is stored in a server-side set. Any subsequent submission of the same nonce is rejected as a replay.

Nonce storage is time-bounded — nonces older than the maximum attribution window (default: 7 days) are automatically pruned, keeping the storage set manageable even at high volume.

Attribution Window

The ts field determines when the token was minted. The server rejects tokens where current_time - ts exceeds the attribution window. Default windows:

WindowDurationUse Case
Standard24 hoursProduct recommendations, shopping agents
Extended7 daysSaaS evaluations, B2B purchasing cycles
Immediate1 hourx402 payment flows (attribution and payment are near-simultaneous)

Merchants can configure custom attribution windows per program.

x402 Integration

In x402 payment flows, the SLAT token is not submitted as a separate API call. Instead, the atxp_reference — a protocol-level attribution identifier — is carried in the X-SL-Attribution HTTP header:

X-SL-Attribution: atxp_reference=slat_v1_...<token>...;agent_key=aff_agent_abc123

The server extracts the SLAT from the header and validates it alongside the payment processing. Attribution and payment settlement happen atomically.