Cart Verification
After an agent has an approved Intent Mandate, it can build a shopping cart with a merchant. Before payment, the cart must be verified against the intent and policy to ensure compliance.
Overview
Cart verification is the second step in the payment flow:
Intent Approved → Cart Verified → Payment Executed
During verification, AutopayOS checks:
- Amount ≤ Intent maximum
- Merchant matches intent
- Categories allowed by policy
- No duplicate submission
- Velocity limits OK
Verify a cart
<tabs> <tab title="TypeScript">const verification = await client.verifyCart({
intentVc: permission.intentVc,
cartVc: merchantCartVc,
});
if (verification.allowed) {
console.log('Cart verified!');
console.log('Approval token:', verification.approvalToken);
console.log('Payment rail:', verification.railDecision.rail);
} else {
console.log('Cart rejected:', verification.reasonCodes);
}curl https://api.autopayos.com/ap2/carts/validate \
-H "Authorization: Bearer $AUTOPAYOS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"intentVc": {
"type": ["VerifiableCredential", "IntentMandate"],
"credentialSubject": {
"mandateId": "intent_abc123",
"maxAmount": 100.00,
"currency": "USD",
"merchantDomain": "amazon.com"
},
"proof": { ... }
},
"cartVc": {
"type": ["VerifiableCredential", "CartMandate"],
"credentialSubject": {
"merchant": "amazon.com",
"items": [
{ "name": "USB-C Cable", "sku": "USB001", "price": 12.99, "quantity": 2 },
{ "name": "Phone Stand", "sku": "PHN002", "price": 9.99, "quantity": 1 }
],
"subtotal": 35.97,
"tax": 2.88,
"total": 38.85,
"currency": "USD"
},
"proof": { ... }
}
}'Request parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
intentVc | object | Yes | The Intent Mandate VC from permission request |
cartVc | object | Yes | The Cart VC from the merchant |
hpProof | object | No | Human Presence proof (if required) |
idempotencyKey | string | No | Prevent duplicate verifications |
Cart VC structure
Merchants create Cart VCs with this structure:
{
"@context": ["https://www.w3.org/2018/credentials/v1"],
"type": ["VerifiableCredential", "CartMandate"],
"issuer": "did:web:amazon.com",
"issuanceDate": "2025-12-17T10:30:00Z",
"credentialSubject": {
"cartId": "cart_xyz789",
"merchant": "amazon.com",
"items": [
{
"name": "USB-C Cable 6ft",
"sku": "B08USB6FT",
"price": 12.99,
"quantity": 2,
"category": "electronics"
},
{
"name": "Phone Stand",
"sku": "B09STAND1",
"price": 9.99,
"quantity": 1,
"category": "electronics"
}
],
"subtotal": 35.97,
"tax": 2.88,
"shipping": 0.00,
"total": 38.85,
"currency": "USD"
},
"proof": {
"type": "Ed25519Signature2020",
"created": "2025-12-17T10:30:00Z",
"verificationMethod": "did:web:amazon.com#key-1",
"jws": "eyJhbGciOiJFZERTQSJ9..."
}
}Response
Approved
{
"allowed": true,
"approvalToken": "apt_abc123xyz789...",
"approvalTokenExpiresAt": "2025-12-17T10:35:00Z",
"railDecision": {
"rail": "STRIPE",
"reason": "Optimal for merchant capabilities",
"merchantConnected": true,
"expiresAt": "2025-12-17T10:35:00Z"
},
"cartHash": "sha256:abc123def456...",
"verifiedAt": "2025-12-17T10:30:05Z"
}Rejected
{
"allowed": false,
"reasonCodes": [
"CART_EXCEEDS_INTENT",
"CATEGORY_NOT_ALLOWED"
],
"details": {
"CART_EXCEEDS_INTENT": {
"cartTotal": 150.00,
"intentMax": 100.00
},
"CATEGORY_NOT_ALLOWED": {
"item": "Premium Subscription",
"category": "digital_goods",
"allowedCategories": ["electronics", "groceries"]
}
}
}Verification checks
| Check | Description | Reason Code |
|---|---|---|
| Amount | Cart total ≤ intent max amount | CART_EXCEEDS_INTENT |
| Merchant | Cart merchant matches intent | MERCHANT_MISMATCH |
| Categories | All items in allowed categories | CATEGORY_NOT_ALLOWED |
| MCC | Merchant Category Code allowed | MCC_DENIED |
| Duplicates | Cart not submitted before | DUPLICATE_CART |
| Intent valid | Intent not expired or used | INTENT_EXPIRED, INTENT_ALREADY_USED |
| Signature | Cart VC signature valid | INVALID_SIGNATURE |
| Velocity | Within transaction limits | VELOCITY_EXCEEDED |
| Anomaly | No unusual patterns detected | ANOMALY_DETECTED |
Rail selection
AutopayOS automatically selects the best payment rail based on:
| Factor | Consideration |
|---|---|
| Merchant capabilities | Which rails the merchant supports |
| Cost | Transaction fees for each rail |
| Speed | Settlement time |
| Policy preference | Rails allowed by policy |
| Amount | Some rails have limits |
{
"railDecision": {
"rail": "STRIPE",
"reason": "Optimal for merchant capabilities",
"alternatives": [
{ "rail": "VISA_IC", "reason": "Not configured for merchant" }
]
}
}Rail priorities
Configure rail preferences in your policy:
{
"rails": {
"allow": ["STRIPE", "VISA_IC"],
"priorities": ["STRIPE", "VISA_IC"],
"fail_over": true
}
}Approval token
The approvalToken is a short-lived, single-use token for executing the payment:
| Property | Value |
|---|---|
| Lifetime | 2-5 minutes (configurable) |
| Usage | Single use only |
| Scope | Specific cart and amount |
| Revocable | Yes, before use |
// Use the approval token to execute payment
const payment = await client.executePayment({
approvalToken: verification.approvalToken,
});Important: Approval tokens expire quickly. Execute payment immediately after verification.
Duplicate detection
AutopayOS prevents duplicate cart submissions using cart hashing:
Cart items + merchant + amount → SHA-256 hash → Dedup check
If the same cart is submitted twice within 60 seconds, you'll receive:
{
"allowed": false,
"reasonCodes": ["DUPLICATE_CART"],
"existingApprovalToken": "apt_existing..."
}Use the existing approval token instead of creating a new one.
Human Presence for carts
If Human Presence was required at intent creation, include the HP proof:
const verification = await client.verifyCart({
intentVc: permission.intentVc,
cartVc: merchantCartVc,
hpProof: {
type: 'WebAuthn',
challengeId: 'hp_xyz789',
credential: webAuthnCredential,
timestamp: new Date().toISOString(),
},
});Category validation
AutopayOS validates cart item categories against your policy:
// Policy
{
"spend": {
"categories": ["groceries", "household", "electronics"]
}
}// Cart item
{
"name": "Premium Subscription",
"category": "digital_goods" // Not in allowed list
}Result: CATEGORY_NOT_ALLOWED
Category synonyms
AutopayOS recognizes category synonyms:
| Policy Category | Also Matches |
|---|---|
groceries | food, supermarket, grocery_stores |
electronics | tech, computers, consumer_electronics |
household | home, home_goods, housewares |
Best practices
1. Verify immediately
Don't delay between building the cart and verifying:
// Good: Verify right away
const cart = await merchant.buildCart(items);
const verification = await client.verifyCart({ intentVc, cartVc: cart });
await client.executePayment({ approvalToken: verification.approvalToken });
// Bad: Long delay
const cart = await merchant.buildCart(items);
await sleep(300000); // 5 minutes
const verification = await client.verifyCart({ intentVc, cartVc: cart }); // Intent may expire2. Handle rejections
const verification = await client.verifyCart({ intentVc, cartVc });
if (!verification.allowed) {
for (const code of verification.reasonCodes) {
switch (code) {
case 'CART_EXCEEDS_INTENT':
// Remove items or request new intent
break;
case 'CATEGORY_NOT_ALLOWED':
// Remove disallowed items
break;
case 'DUPLICATE_CART':
// Use existing approval token
break;
case 'INTENT_EXPIRED':
// Request new intent
break;
}
}
}3. Include all cart details
Provide complete cart information for accurate verification:
const cartVc = {
credentialSubject: {
merchant: 'amazon.com',
items: [
{
name: 'USB-C Cable',
sku: 'B08USB6FT',
price: 12.99,
quantity: 2,
category: 'electronics', // Include category
}
],
subtotal: 25.98,
tax: 2.08,
shipping: 5.99,
total: 34.05, // Include all fees
currency: 'USD',
}
};Evidence events
Cart verification produces these evidence events:
| Event | Description |
|---|---|
CART_VALIDATED | Cart was verified successfully |
CART_REJECTED | Cart failed verification |
CART_DUPLICATE | Duplicate cart detected |
Query cart events:
curl "https://api.autopayos.com/ap2/evidence/search?eventType=CART_VALIDATED" \
-H "Authorization: Bearer $AUTOPAYOS_API_KEY"Next steps
- Payment execution — Execute the payment
- Policy configuration — Define cart rules
- Evidence chain — Query verification history