File DA-039 View as Markdown

Stripe

Put Double Agent's verdict on each Stripe payment, so Radar rules can review or challenge payments made by bots and AI agents. The browser fetches a signed token, your server verifies it and writes the verdict into the PaymentIntent's metadata.

Before you start: a public key on the snippet (tokens don't work keyless, see Capabilities), and token verification on your server (Verify tokens on your server).

1. Get a token in the browser

const daToken = await doubleagent.stripeToken().catch(() => '');

stripeToken() is getToken('payment'). Send daToken to your server with the payment request.

2. Attach the verdict on your server

Before you confirm the payment, verify daToken as on Verify tokens on your server, then write seven metadata keys:

const claims = await verifyDaToken(daToken).catch(() => null);   // your step 2 code
if (claims) {
  await stripe.paymentIntents.update(paymentIntentId, {
    metadata: {
      da_class: claims.cls,
      da_score: String(Math.round((1 - claims.p.human) * 100)),
      da_agent: claims.agent?.family ?? 'none',
      da_behavior: claims.behavior?.label ?? 'neutral',
      da_behavior_risk: String(claims.behavior?.risk ?? 0),
      da_authorization: claims.authorization?.decision ?? 'unknown',
      da_sid: claims.sid,
    },
  });
}

These are the same keys Double Agent's own Stripe relabel writes, so Radar rules work either way. With Stripe Checkout, pass the same keys in payment_intent_data.metadata when you create the session.

A missing or bad token means "unknown", not "bot". Let the payment go on without metadata.

3. Write Radar rules

These need Radar for Fraud Teams. In the Stripe Dashboard, go to Radar › Rules and add:

Review if ::da_class:: = 'bot'
Request 3D Secure if ::da_class:: = 'agent' and :amount_in_usd: > 500

Radar reads metadata as text or as a number, so a score rule works too, for example Review if ::da_score:: >= 80. Text values are case-sensitive, and ours are lowercase. A payment without the keys matches none of these rules.

Check it worked

Make a test payment on your site, then open it in the Stripe Dashboard. Under Metadata you should see da_class and da_sid.

When the verdict changes later

The metadata is not updated by itself yet. Server relabel for Stripe is built, and you can save a Stripe key in Sites › your site › Settings › Server relabel credentials, but it needs the PaymentIntent id from the browser, and no part of the script sends it today. So the Stripe key does nothing for now.

To update a payment after a change, listen to the Debrief webhook and write the keys again from data.verdict. When relabel does run, it only touches a PaymentIntent whose metadata.da_sid matches the session. Your server sets that key, so a browser can never point a relabel at someone else's payment.

Next: Verify tokens on your server for other routes, or Relabel.