How UCP Payment Handlers Specify Available Instruments and Constraints

UCP payment handlers declare supported payment methods through the available_instruments array, which binds instrument types like "card" or "gift_card" to optional constraint objects that narrow acceptance criteria.

The Universal Commerce Protocol (UCP) defines a strict schema-driven mechanism for payment handlers to advertise their capabilities. When integrating with the Universal-Commerce-Protocol/ucp ecosystem, handlers must explicitly enumerate which payment instruments they can process and any specific limitations—such as card brands or region restrictions—that apply to each instrument type.

Schema Definition and Structure

The available_instruments Field

In source/schemas/payment_handler.json, the core handler schema defines available_instruments as an array of objects. Each item references the available_payment_instrument type defined in source/schemas/shopping/types/available_payment_instrument.json.

"available_instruments": {
  "type": "array",
  "items": { "$ref": "shopping/types/available_payment_instrument.json" },
  "description": "Instrument types this handler supports, with optional constraints."
}

Every entry in this array represents a distinct payment instrument the handler is equipped to process. Omitting this field signals that the handler supports all instrument types defined by its underlying handler schema, though explicit declaration is recommended for clarity and security.

Instrument Type Identification

Each instrument entry requires a type string that acts as a discriminator. Valid values correspond to concrete instrument schemas, such as "card" for card payments or "gift_card" for stored-value instruments. This identifier is defined in source/schemas/shopping/types/available_payment_instrument.json (lines 9-12) and must match the payment instrument's canonical name exactly.

{
  "type": "card"
}

Declaring Constraints

Optional Constraints Object

Handlers refine generic instrument definitions using a free-form constraints object. While the base schema in available_payment_instrument.json (lines 13-18) only mandates that the object contain at least one property, instrument-specific schemas—such as available_card_payment_instrument—define strict sub-properties like brands, issuing_countries, or currencies.

The constraints object's structure varies by instrument type, allowing granular control without breaking the extensible schema contract.

Constraint Examples

A minimal declaration accepts all variations of an instrument type:

{
  "type": "card"
}

A constrained declaration narrows acceptance to specific card brands:

{
  "type": "card",
  "constraints": {
    "brands": ["visa", "mastercard"]
  }
}

Declaration Contexts and Resolution

Platform vs Business Declarations

UCP recognizes three hierarchical contexts where available_instruments appears:

  • Platform schema: The payment processor advertises its global capabilities.
  • Business schema: The merchant declares a filtered subset of platform instruments they wish to accept.
  • Response schema: The authoritative, resolved list delivered to the checkout frontend.

When declared in source/schemas/payment_handler.json compliant configurations, these schemas layer to create a permission hierarchy.

Runtime Resolution Flow

At checkout, the system computes the intersection of three authoritative sources:

  1. Platform-declared capabilities (what the processor can technically handle)
  2. Business-declared list (what the merchant chooses to offer)
  3. Checkout-specific restrictions (session-level filters like amount limits or risk checks)

The resulting array appears in the response schema and becomes the definitive source for transaction processing. According to docs/specification/payment-handler-guide.md, this resolution ensures that neither platforms nor businesses can unilaterally expand instrument availability beyond their mutual agreement.

Implementation Examples

Full Business Schema Declaration

Below is a complete handler configuration showing multiple instrument types with mixed constraint levels:

{
  "id": "processor_tokenizer_1234",
  "version": "2024-03-01",
  "spec": "https://example.com/ucp/handler",
  "schema": "https://example.com/ucp/handler/schema.json",
  "available_instruments": [
    {
      "type": "card",
      "constraints": {
        "brands": ["visa", "mastercard"],
        "currencies": ["USD", "EUR"]
      }
    },
    {
      "type": "gift_card"
    }
  ],
  "config": {
    "environment": "production",
    "business_id": "biz_789"
  }
}

Runtime Response Schema

After resolution, the checkout receives the definitive instrument list:

{
  "id": "processor_tokenizer_1234",
  "version": "2024-03-01",
  "available_instruments": [
    {
      "type": "card",
      "constraints": {
        "brands": ["visa", "mastercard"]
      }
    }
  ],
  "config": {
    "api_version": 2,
    "environment": "production",
    "business_id": "biz_789"
  }
}

Summary

  • available_instruments in source/schemas/payment_handler.json is the canonical field for declaring payment method support.
  • Each array item requires a type discriminator and may include a constraints object for granular filtering.
  • Absence of the field implies support for all instrument types defined by the handler schema.
  • Resolution involves intersecting platform capabilities, business preferences, and checkout restrictions to produce the final authoritative list.
  • Constraint shapes are defined by instrument-specific schemas (e.g., available_card_payment_instrument) rather than the base type alone.

Frequently Asked Questions

What happens if a handler omits the available_instruments field?

According to the payment handler guide in docs/specification/payment-handler-guide.md, omitting available_instruments signals that the handler supports every instrument type defined by its underlying schema. While this provides maximum flexibility, explicit declaration is recommended to avoid ambiguous acceptance boundaries and ensure compliance with platform-specific capabilities.

How are constraints validated against instrument types?

The base schema in source/schemas/shopping/types/available_payment_instrument.json requires only that the constraints object contain at least one property. Validation against specific constraint keys—such as brands for cards—occurs through JSON Schema references to instrument-specific definitions like available_card_payment_instrument.json. This allows the protocol to remain extensible while enforcing strict typing per instrument.

Can a business support instruments that the platform does not declare?

No. The resolution flow computes an intersection of platform capabilities and business declarations. If a business includes an instrument in their available_instruments array that the platform has not declared or has excluded, that instrument is filtered out of the final response schema. The platform serves as the capability ceiling, while the business acts as a selective filter.

What is the resolution order during checkout resolution?

The system evaluates three layers in sequence: first, the platform's declared capabilities; second, the business's declared subset; and third, any runtime restrictions applied to the specific checkout session. The intersection of these three sets becomes the available_instruments array returned in the response schema, ensuring that all parties must explicitly agree on instrument availability before processing can occur.

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 →