Why agents as customers?
Autonomous agents can purchase goods, book services, or call APIs on behalf of users. Your product can treat them as first-class customers by verifying that each request comes from a LetsPing-verified agent and that the handoff is cryptographically signed. No custom auth needed—use the same webhook and escrow envelope your agents already get.
What you need
- A LetsPing project and a webhook URL that receives
request.approved(and optionallyrequest.rejected). - Your project's
WEBHOOK_SIGNING_SECRET(from Settings → Webhooks). - The
@letsping/sdkhelperverifyEscrow(secret, eventBody)to verify thehandoff_signatureand optional x402/AP2 mandates. - Optional but recommended: a simple policy that looks at LetsPing's
/api/agents/trust-scoreand/api/agents/attestationbefore you fulfill high-value requests.
Verify the escrow envelope
When an agent chain hands off to your service, LetsPing includes an escrow block in the webhook payload: handoff_signature, upstream_agent_id, downstream_agent_id, and optionally x402_mandate / ap2_mandate. Verify the signature with your webhook secret before fulfilling the request.
// Your webhook endpoint receives LetsPing events (e.g. request.approved with escrow).
import { verifyEscrow } from "@letsping/sdk";
const webhookSecret = process.env.WEBHOOK_SIGNING_SECRET; // From your LetsPing project
export async function POST(req: Request) {
const body = await req.json();
if (!verifyEscrow(webhookSecret, body)) {
return new Response("Invalid signature", { status: 401 });
}
const { event, data, escrow } = body;
const upstreamAgentId = escrow?.upstream_agent_id;
const x402Mandate = escrow?.x402_mandate;
const ap2Mandate = escrow?.ap2_mandate;
// Trust the handoff: the request was approved and signed by LetsPing.
// Optional: enforce payment via x402/AP2 mandate before fulfilling.
await fulfillOrder(data.payload, { upstreamAgentId, x402Mandate, ap2Mandate });
return new Response(JSON.stringify({ ok: true }), { headers: { "Content-Type": "application/json" } });
}Copy-paste examples
Two minimal examples you can drop into your storefront today. Both verify the escrow envelope, then call a local fulfillOrder helper.
Next.js App Router
// app/api/letsping/webhook/route.ts
import { NextRequest, NextResponse } from "next/server";
import { verifyEscrow } from "@letsping/sdk";
const WEBHOOK_SIGNING_SECRET = process.env.WEBHOOK_SIGNING_SECRET!;
export async function POST(req: NextRequest) {
const body = await req.json();
if (!verifyEscrow(WEBHOOK_SIGNING_SECRET, body)) {
return NextResponse.json({ error: "invalid_signature" }, { status: 401 });
}
const { event, data, escrow } = body;
const upstreamAgentId = escrow?.upstream_agent_id;
// Optional: read x402/AP2 mandates for payment.
const x402Mandate = escrow?.x402_mandate;
const ap2Mandate = escrow?.ap2_mandate;
// TODO: call your own billing system or mandate validator here if needed.
await fulfillOrder(data.payload, { upstreamAgentId, x402Mandate, ap2Mandate });
return NextResponse.json({ ok: true });
}Express
// server.js (Express)
const express = require("express");
const bodyParser = require("body-parser");
const { verifyEscrow } = require("@letsping/sdk");
const app = express();
app.use(bodyParser.json());
const WEBHOOK_SIGNING_SECRET = process.env.WEBHOOK_SIGNING_SECRET;
app.post("/letsping/webhook", async (req, res) => {
const eventBody = req.body;
if (!verifyEscrow(WEBHOOK_SIGNING_SECRET, eventBody)) {
return res.status(401).json({ error: "invalid_signature" });
}
const { event, data, escrow } = eventBody;
const upstreamAgentId = escrow?.upstream_agent_id;
const x402Mandate = escrow?.x402_mandate;
const ap2Mandate = escrow?.ap2_mandate;
try {
await fulfillOrder(data.payload, { upstreamAgentId, x402Mandate, ap2Mandate });
return res.json({ ok: true });
} catch (err) {
console.error("Order fulfillment failed:", err);
return res.status(500).json({ error: "fulfillment_failed" });
}
});
app.listen(3000, () => {
console.log("Storefront listening on port 3000");
});Add a simple trust policy
Most storefronts want one place to decide "Do we trust this agent for this request?" You can call LetsPing's trust APIs from the same backend that verifies escrow:
GET /api/agents/trust-score?agent_id=...— returns a 0–999 score plus transparent components (volume, disputes, outcomes) so you can gate risky actions.GET /api/agents/attestation?agent_id=...— returns a signed claim withsigned_callsandescrow_handoffsin the window so you can see if this agent is new or has history.
A common pattern is: (1) verify the escrow envelope; (2) fetch the agent's trust score; (3) only fulfill high-value or sensitive orders when the score is above a threshold or the attestation shows enough history.
Payment mandates (x402 / AP2)
If the agent chain attaches a payment mandate (x402 or AP2), it will appear in escrow.x402_mandate or escrow.ap2_mandate. Your backend can validate the mandate with the relevant provider and fulfill the order only after payment is authorized. LetsPing does not process payments—it carries the signed envelope so you can trust who initiated the handoff and what they authorized.
Next steps
Agent-to-Agent Escrow Spec · SaaS Verifies an Agent Escrow Envelope (examples) · Full API reference