> ## Documentation Index
> Fetch the complete documentation index at: https://learn.orbexa.io/llms.txt
> Use this file to discover all available pages before exploring further.

# UCP endpoint testing and compliance validation

> UCP endpoint testing methods — Profile compliance validation, checkout flow testing, signature verification, security checks, and performance benchmarks

# Testing and Validation

## 9.1 UCP Profile Validation

The Profile is the entry point for every AI agent connection and must pass rigorous validation.

### Basic Checks

```bash theme={null}
# 1. Verify HTTPS and no redirects
curl -sI "https://mystore.com/.well-known/ucp" | head -5
# Expected: HTTP/2 200 (must not be 3xx)

# 2. Check Cache-Control
curl -sI "https://mystore.com/.well-known/ucp" | grep -i cache-control
# Expected: cache-control: public, max-age=N (N >= 60)

# 3. Check Content-Type
curl -sI "https://mystore.com/.well-known/ucp" | grep -i content-type
# Expected: content-type: application/json

# 4. Fetch and validate JSON
curl -s "https://mystore.com/.well-known/ucp" | jq .
```

### Profile Field Validation Checklist

| Field                    | Validation Rule                                                           | Required |
| ------------------------ | ------------------------------------------------------------------------- | -------- |
| `supported_versions`     | Non-empty array containing valid date-formatted version strings           | Yes      |
| `services`               | At least one service; `base_url` must be HTTPS                            | Yes      |
| `capabilities`           | At least one capability; namespace format must be correct                 | Yes      |
| `capabilities.*.version` | Valid date format; within the `supported_versions` range                  | Yes      |
| `payment_handlers`       | Array with reverse-DNS naming format                                      | No       |
| `signing_keys`           | JWK array; each key must have `kid`, `kty`, `crv`, `x`, `y`, `use`, `alg` | No       |

### Automated Profile Validation Script

```bash theme={null}
#!/bin/bash
URL="https://mystore.com/.well-known/ucp"

echo "=== UCP Profile Validation ==="

# Check HTTP status code (do not follow redirects)
STATUS=$(curl -so /dev/null -w "%{http_code}" --max-redirs 0 "$URL")
if [ "$STATUS" = "200" ]; then
  echo "PASS: HTTP 200 (no redirect)"
else
  echo "FAIL: HTTP $STATUS (expected 200, no redirects allowed)"
fi

# Check HTTPS
if [[ "$URL" == https://* ]]; then
  echo "PASS: HTTPS"
else
  echo "FAIL: Must be HTTPS"
fi

# Check Cache-Control
CACHE=$(curl -sI "$URL" | grep -i "cache-control" | tr -d '\r')
if echo "$CACHE" | grep -qi "public"; then
  echo "PASS: Cache-Control includes public"
else
  echo "FAIL: Cache-Control must include 'public'"
fi

# Check JSON validity
BODY=$(curl -s "$URL")
if echo "$BODY" | jq . > /dev/null 2>&1; then
  echo "PASS: Valid JSON"
else
  echo "FAIL: Invalid JSON"
fi

# Check required fields
if echo "$BODY" | jq -e '.supported_versions | length > 0' > /dev/null 2>&1; then
  echo "PASS: supported_versions present"
else
  echo "FAIL: supported_versions missing or empty"
fi

if echo "$BODY" | jq -e '.services | keys | length > 0' > /dev/null 2>&1; then
  echo "PASS: services present"
else
  echo "FAIL: services missing or empty"
fi

if echo "$BODY" | jq -e '.capabilities | keys | length > 0' > /dev/null 2>&1; then
  echo "PASS: capabilities present"
else
  echo "FAIL: capabilities missing or empty"
fi

# Check signing key format
KEYS=$(echo "$BODY" | jq -r '.signing_keys | length')
if [ "$KEYS" -gt 0 ]; then
  echo "INFO: $KEYS signing key(s) found"
  echo "$BODY" | jq -r '.signing_keys[] | "  kid=\(.kid) alg=\(.alg) crv=\(.crv)"'
else
  echo "INFO: No signing keys (Webhook signing not configured)"
fi

echo "=== Validation Complete ==="
```

## 9.2 Checkout Flow Testing

### Complete Checkout Flow

```bash theme={null}
BASE="https://mystore.com/ucp"
TOKEN="Bearer ucp_pk_test_xxxx"

# Step 1: Create a checkout session
SESSION=$(curl -s -X POST "$BASE/checkout/sessions" \
  -H "Content-Type: application/json" \
  -H "Authorization: $TOKEN" \
  -d '{
    "line_items": [{"product_id": "prod_001", "quantity": 1}],
    "buyer": {"email": "test@example.com"}
  }')
echo "Create: $(echo $SESSION | jq -r '.checkout_session.status')"
# Expected: incomplete

SESSION_ID=$(echo $SESSION | jq -r '.checkout_session.id')

# Step 2: Update buyer information and shipping
curl -s -X PATCH "$BASE/checkout/sessions/$SESSION_ID" \
  -H "Content-Type: application/json" \
  -H "Authorization: $TOKEN" \
  -d '{
    "buyer": {
      "name": "Test User",
      "shipping_address": {
        "line1": "123 Main St",
        "city": "San Francisco",
        "state": "CA",
        "postal_code": "94102",
        "country_code": "US"
      }
    },
    "fulfillment": {"method": "standard_shipping"}
  }' | jq '.checkout_session.status'

# Step 3: Query session status
STATUS=$(curl -s "$BASE/checkout/sessions/$SESSION_ID" \
  -H "Authorization: $TOKEN" | jq -r '.checkout_session.status')
echo "After update: $STATUS"
# Expected: incomplete or ready_for_complete

# Step 4: Cancel the session (recommended in test environments instead of completing)
curl -s -X POST "$BASE/checkout/sessions/$SESSION_ID/cancel" \
  -H "Content-Type: application/json" \
  -H "Authorization: $TOKEN" \
  -d '{"reason": "test_cancellation"}' | jq '.checkout_session.status'
# Expected: canceled
```

### State Machine Validation

Test all six status transition paths for correctness:

| Test Scenario                 | Initial Status       | Operation          | Expected Result        |
| ----------------------------- | -------------------- | ------------------ | ---------------------- |
| Create empty session          | -                    | Create             | `incomplete`           |
| Provide complete information  | `incomplete`         | Update             | `ready_for_complete`   |
| Submit for completion         | `ready_for_complete` | Complete           | `complete_in_progress` |
| Cancel an in-progress session | `incomplete`         | Cancel             | `canceled`             |
| Cancel a completed session    | `completed`          | Cancel             | 400 error              |
| Update a canceled session     | `canceled`           | Update             | 400 error              |
| Trigger human escalation      | `incomplete`         | Specific condition | `requires_escalation`  |

## 9.3 Product Data Validation

Every product record must pass the following validation:

```text theme={null}
Required field checks:
  [x] id: Non-empty and unique
  [x] name: Non-empty string
  [x] price.amount: Positive integer (minor currency units)
  [x] price.currency_code: Valid ISO 4217 code (e.g., USD, EUR, JPY)
  [x] availability: One of in_stock / out_of_stock / preorder
  [x] images: At least one item; URL must be accessible via HTTPS

Optional field format checks:
  [x] variants[].sku: If present, must be unique
  [x] variants[].price.amount: Positive integer
  [x] gtin: If present, must conform to GTIN-13 or GTIN-14 format
  [x] compare_at_price.amount: If present, must be greater than price.amount

Amount consistency:
  [x] All price objects use the same currency_code
  [x] Amount values are consistent with the currency's minor unit (USD uses cents, JPY uses yen)
```

## 9.4 Signature Verification Testing

If Webhook signing is configured, test both signature creation and verification:

```bash theme={null}
# Simulate a merchant sending a signed Webhook
# 1. Create a test request body
BODY='{"event_type":"order.created","order_id":"ord_test_001"}'

# 2. Compute Content-Digest
DIGEST=$(echo -n "$BODY" | openssl dgst -sha256 -binary | base64)
echo "Content-Digest: sha-256=:$DIGEST:"

# 3. Verify signing keys in the merchant Profile
curl -s "https://mystore.com/.well-known/ucp" | jq '.signing_keys'
# Confirm kid, alg (ES256), crv (P-256) and other fields are correct
```

## 9.5 OAuth Flow Testing

```bash theme={null}
# 1. Verify authorization server discovery
curl -s "https://mystore.com/.well-known/oauth-authorization-server" | jq .
# Check: authorization_endpoint, token_endpoint, revocation_endpoint

# 2. Verify PKCE support
# Check that code_challenge_methods_supported includes "S256"

# 3. Verify scope support
# Check that scopes_supported includes "ucp:scopes:checkout_session"

# 4. Test the token revocation endpoint (RFC 7009)
curl -s -X POST "https://mystore.com/oauth/revoke" \
  -d "token=expired_test_token&token_type_hint=access_token&client_id=test" \
  -w "\nHTTP Status: %{http_code}\n"
# Expected: 200 (should return 200 even for invalid tokens)
```

## 9.6 Performance Benchmarks

UCP endpoints should respond within reasonable timeframes:

| Endpoint Type              | Response Time Target | Concurrency Requirement |
| -------------------------- | -------------------- | ----------------------- |
| `/.well-known/ucp` Profile | Under 100ms          | 100+ QPS                |
| Product search             | Under 500ms          | 50+ QPS                 |
| Product details            | Under 200ms          | 100+ QPS                |
| Checkout operations        | Under 1s             | 20+ QPS                 |
| OAuth token endpoint       | Under 300ms          | 50+ QPS                 |

```bash theme={null}
# Simple performance test
# Profile endpoint latency
for i in $(seq 1 10); do
  curl -so /dev/null -w "%{time_total}\n" "https://mystore.com/.well-known/ucp"
done

# Product search concurrency test (requires ab or wrk)
ab -n 100 -c 10 "https://mystore.com/ucp/catalog/products?query=test&limit=10"
```

## 9.7 Common Issues and Troubleshooting

| Issue                                | Cause                           | Solution                                                        |
| ------------------------------------ | ------------------------------- | --------------------------------------------------------------- |
| AI agent cannot discover Profile     | 3xx redirect or non-HTTPS       | Ensure a direct 200 response with no redirects                  |
| Cache-Control validation fails       | max-age below 60 seconds        | Set `public, max-age=3600`                                      |
| Prices display incorrectly           | Not using minor currency units  | Confirm that amount is an integer (cents), not a decimal        |
| Signature verification fails         | kid mismatch or expired key     | Check that the kid in signing\_keys matches the Signature-Input |
| OAuth flow breaks                    | Missing PKCE support            | Implement S256 code\_challenge verification                     |
| Capability negotiation returns empty | Version mismatch                | Ensure both parties have overlapping supported\_versions        |
| Webhooks not received                | Signature verification rejected | Verify Content-Digest and Signature are correct                 |

***

**Next chapter**: [Case Studies and Extensions](/en/book-3/ch10-case-studies) — Buyer Consent extension, AP2 Mandate, and real-world integration paths
