AP2 Mandates Extension: Cryptographic Consent for UCP Checkout Flows

The AP2 Mandates extension adds a cryptographically-bound consent layer to the Universal Commerce Protocol (UCP), requiring businesses to embed signed merchant authorizations and platforms to supply SD-JWT credentials that prove explicit user approval for purchases and fund transfers.

The AP2 Mandates extension in the Universal-Commerce-Protocol/ucp repository transforms standard checkout flows into tamper-evident, legally auditable transactions. When activated, this extension mandates that all session data carries cryptographic proof of consent, preventing plaintext checkout flows and ensuring that every party in the transaction can verify authorization through detached JWS signatures and Selective Disclosure JWT (SD-JWT) credentials.

How AP2 Mandates Fits Into the UCP Architecture

The extension integrates into UCP through capability negotiation and strict namespace isolation, fundamentally altering the security posture of the checkout session once activated.

Capability Negotiation and Security Locking

Activation occurs only when both the business and platform advertise the dev.ucp.shopping.ap2_mandate capability in their respective /.well-known/ucp profiles. Once negotiated, the session becomes Security Locked, prohibiting any plain (unprotected) checkout flow. According to the specification in docs/specification/ap2-mandates.md, this binding ensures that cryptographic verification is mandatory for the entire session lifecycle.

Namespace Design and Data Structure

All AP2-specific fields reside under a top-level ap2 object in both requests and responses. This design keeps the base checkout schema clean while allowing simultaneous operation with other security extensions. As defined in source/schemas/shopping/ap2_mandate.json, this namespace contains:

  • merchant_authorization: The business's detached JWS signature
  • checkout_mandate: The platform's SD-JWT credential bound to the checkout
  • payment_mandate: The SD-JWT credential bound to the payment instrument

Cryptographic Primitives and Canonicalization

The extension enforces strict cryptographic standards per docs/specification/signatures.md. All JSON data undergoing signature or mandate insertion must be canonicalized using the JSON Canonicalization Scheme (JCS) (RFC 8785) to ensure reproducible byte streams. Supported signature algorithms are limited to ES256, ES384, and ES512 (ECDSA with P-256, P-384, and P-521 curves), using JWS detached content and JWK key formats.

The AP2 Mandates extension is designed for scenarios requiring immutable proof of consent and cross-party verification.

  • High-value or regulated commerce: When transactions require legally-recognizable proof of user consent and immutable audit trails, the SD-JWT mandates provide tamper-evident evidence that the user approved exact checkout terms and fund transfers.
  • Multi-party payment flows: For platforms, PSPs, and card networks exchanging consent artifacts across trust boundaries, mandates travel with the checkout object and payment tokens, allowing each party to verify identical signed data.
  • Digital wallet integrations: When integrating with wallets issuing Verifiable Digital Credentials (VDCs), the Key-Binding (+kb) feature binds mandates to user-controlled credentials, satisfying wallet-centric security models.
  • Platform-as-a-Service environments: When platforms must cryptographically prove to downstream businesses that users gave explicit authorization, the platform can generate or forward user-signed mandates that businesses can independently verify.

Implementation Examples

The following examples demonstrate the practical implementation of merchant authorizations and mandate verification as specified in the AP2 Mandates extension.

Merchant Authorization in Checkout Response

Businesses must sign the checkout payload and embed the detached JWS in the response. The payload excludes the ap2 object to prevent circular references.

{
  "id": "chk_abc123",
  "status": "ready_for_complete",
  "currency": "USD",
  "line_items": [],
  "totals": [],
  "ap2": {
    "merchant_authorization": "eyJhbGciOiJFUzI1NiIsImtpZCI6Im1yY2hhbnRfMjAyNSJ9..eyJz... (detached JWS)"
  }
}

The ap2.merchant_authorization field contains a detached JWS where the payload is the canonicalized checkout object without the ap2 block. The kid parameter must reference a public key listed in the business's signing_keys, and the algorithm must be one of ES256, ES384, or ES512.

Checkout Mandate in Complete Request

The platform supplies verifiable mandates in the complete request, binding the checkout to cryptographic proof of user consent.

{
  "payment": {
    "instruments": [
      {
        "id": "instr_1",
        "handler_id": "gpay_1234",
        "type": "card",
        "selected": true,
        "credential": {
          "type": "PAYMENT_GATEWAY",
          "token": "examplePaymentMethodToken"
        }
      }
    ]
  },
  "ap2": {
    "checkout_mandate": "eyJhbGciOiJFUzI1NiIsInR5cCI6InZjK3NkLWp3dCJ9…"
  }
}

The ap2.checkout_mandate field carries an SD-JWT (+kb) credential embedding the full checkout object, including the merchant's signature. The business validates this credential, extracts the embedded checkout, and verifies the merchant authorization against its signing_keys.

Verification Flow

The following pseudocode illustrates the verification algorithm businesses implement according to docs/specification/ap2-mandates.md:

function verifyComplete(request, businessProfile):
    // 1️⃣ Ensure AP2 was negotiated
    if "dev.ucp.shopping.ap2_mandate" not in intersection:
        reject("mandate_required")

    // 2️⃣ Verify checkout mandate (SD‑JWT)
    mandate = decodeSDJWT(request.ap2.checkout_mandate)
    if !mandate.validSignature() or mandate.expired:
        reject("mandate_invalid_signature")

    // 3️⃣ Extract embedded checkout and verify merchant signature
    checkout = mandate.claims.checkout
    jws = checkout.ap2.merchant_authorization
    header, _, signature = splitDetachedJWS(jws)
    payload = checkout without "ap2"
    signingInput = base64url(header) + "." + base64url(jcsCanonicalize(payload))
    pubKey = findKey(businessProfile.signing_keys, header.kid)
    if !verifySignature(signingInput, signature, pubKey, header.alg):
        reject("merchant_authorization_invalid")

This flow ensures that both the platform's mandate and the business's authorization signature are cryptographically valid before processing the transaction.

Key Files and Schema References

Implementation of the AP2 Mandates extension relies on these critical source files:

Summary

  • The AP2 Mandates extension requires the dev.ucp.shopping.ap2_mandate capability to activate Security Locked sessions.
  • Businesses must provide detached JWS signatures in ap2.merchant_authorization, signing the checkout payload without the ap2 object using ES256/ES384/ES512 algorithms.
  • Platforms must supply SD-JWT credentials (+kb) in ap2.checkout_mandate that cryptographically prove user consent.
  • All JSON must be canonicalized using JCS (RFC 8785) before signing or embedding in mandates.
  • The extension is mandatory for high-value commerce, regulated industries, multi-party payment flows, and digital wallet integrations requiring verifiable consent.

Frequently Asked Questions

What capability key activates the AP2 Mandates extension?

Both the business and platform must advertise dev.ucp.shopping.ap2_mandate in their /.well-known/ucp profiles. This mutual advertisement triggers Security Locking, which prohibits unprotected checkout flows for that session.

How does the merchant authorization signature work?

The business creates a detached JWS using ES256, ES384, or ES512 algorithms, placing it in ap2.merchant_authorization. The signed payload must be the canonicalized checkout object excluding the ap2 field to avoid circular dependencies. The kid in the JWS header must reference a key in the business's published signing_keys.

What cryptographic algorithms does AP2 Mandates require?

The extension mandates ECDSA signatures using ES256 (P-256), ES384 (P-384), or ES512 (P-521) curves. All JSON canonicalization must follow RFC 8785 (JCS), and SD-JWT mandates must use the Key-Binding (+kb) extension for credential binding.

When should businesses avoid using AP2 Mandates?

Low-risk, low-value transactions where cryptographic overhead outweighs security benefits may not require AP2 Mandates. The extension should not be used when either party cannot support the mandatory JCS canonicalization, SD-JWT processing, or ECDSA signature verification required by the specification.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →