Skip to content

Commit 69a3cd0

Browse files
author
James Andersen
committed
feat: add required_fields to available payment instruments
Enable payment handlers to declare which optional fields they require for payment processing via a new `required_fields` property on `available_payment_instrument.json`. Uses dot notation for nested properties (e.g., `credential.cvc`, `billing_address.postal_code`). This eliminates guesswork for agentic platforms — they can collect exactly the right fields before attempting tokenization, avoiding trial-and-error retries and unnecessary over-collection of buyer data.
1 parent 5f8b834 commit 69a3cd0

2 files changed

Lines changed: 62 additions & 5 deletions

File tree

docs/specification/payment-handler-guide.md

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,48 @@ instrument types defined by its handler schema. When present, it narrows the
197197
advertised types and/or applies additional constraints (e.g., limiting card
198198
brands to `["visa", "mastercard"]`).
199199

200+
#### Required Fields
201+
202+
Each entry in `available_instruments` **MAY** include a `required_fields`
203+
array that declares which optional fields from the instrument or credential
204+
schemas this handler requires for payment processing.
205+
206+
Many instrument and credential properties are optional at the protocol level
207+
but required by individual merchants and their PSPs. For example, `cvc` is
208+
optional in `card_credential.json` but most merchants require it for
209+
card-not-present transactions. Without `required_fields`, the platform must
210+
guess which optional fields the merchant actually needs — leading to
211+
trial-and-error tokenization or over-collection of buyer data.
212+
213+
**Dot notation** identifies which layer a field belongs to:
214+
215+
| Notation | Layer | Example |
216+
| :------- | :---- | :------ |
217+
| `credential.<field>` | Credential property | `credential.cvc`, `credential.name` |
218+
| `billing_address.<field>` | Billing address subfield | `billing_address.postal_code` |
219+
| `<field>` (no prefix) | Top-level instrument property | `billing_address` (full object) |
220+
221+
**Example — CVC and postal-only AVS:**
222+
223+
```json
224+
{
225+
"available_instruments": [
226+
{
227+
"type": "card",
228+
"required_fields": ["credential.cvc", "billing_address.postal_code"]
229+
}
230+
]
231+
}
232+
```
233+
234+
The platform reads `required_fields` from the resolved `available_instruments`
235+
in the response and knows exactly which fields to collect from the buyer
236+
before constructing the instrument — no guesswork, no retry loops.
237+
238+
When `required_fields` is absent, the handler places no additional field
239+
requirements beyond what the schema already marks as required. Platforms fall
240+
back to existing behavior.
241+
200242
---
201243

202244
#### Handler Declaration Variants
@@ -268,7 +310,8 @@ and typically includes different configuration:
268310
"type": "card",
269311
"constraints": {
270312
"brands": ["visa", "mastercard"]
271-
}
313+
},
314+
"required_fields": ["credential.cvc", "billing_address.postal_code"]
272315
}
273316
],
274317
"config": {
@@ -314,6 +357,11 @@ authoritative value returned in the `response_schema`.
314357
In this example, the business's PSP is not configured for Discover, so Discover
315358
is excluded from the response even though the platform supports it.
316359

360+
`required_fields` participates in this resolution naturally: the business
361+
includes `required_fields` in the resolved `available_instruments` returned
362+
in the response. The platform reads these requirements at the same time it
363+
discovers which instruments are available — no additional round-trip needed.
364+
317365
---
318366

319367
#### Defining the Schema
@@ -511,10 +559,10 @@ specifies what constraints are valid for that instrument type. For example,
511559
[`card_payment_instrument.json`](site:schemas/shopping/types/card_payment_instrument.json)
512560
defines `available_card_payment_instrument` with a `brands` constraint.
513561

514-
| Schema | Constraints |
515-
| :----------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------- |
516-
| [`available_payment_instrument.json`](site:schemas/shopping/types/available_payment_instrument.json) | Base: type, constraints (open object) |
517-
| `card_payment_instrument.json#/$defs/available_card_payment_instrument` | Extends base with `constraints.brands` for card networks |
562+
| Schema | Constraints |
563+
| :----------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------- |
564+
| [`available_payment_instrument.json`](site:schemas/shopping/types/available_payment_instrument.json) | Base: type, constraints (open object), required_fields (optional array) |
565+
| `card_payment_instrument.json#/$defs/available_card_payment_instrument` | Extends base with `constraints.brands` for card networks |
518566

519567
Handlers reference these instrument-defined schemas when declaring
520568
`available_instruments`. The **instrument schema authors** define what

source/schemas/shopping/types/available_payment_instrument.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,15 @@
1515
"additionalProperties": true,
1616
"description": "Constraints on this instrument type. Structure depends on instrument type and active capabilities.",
1717
"minProperties": 1
18+
},
19+
"required_fields": {
20+
"type": "array",
21+
"items": {
22+
"type": "string"
23+
},
24+
"description": "Optional fields from the instrument or credential schemas that this handler requires for payment processing. Uses dot notation for nested properties: credential fields use 'credential.' prefix (e.g., 'credential.cvc', 'credential.name'), billing address subfields use 'billing_address.' prefix (e.g., 'billing_address.postal_code'). Top-level instrument fields use their property name directly (e.g., 'billing_address' for the full object).",
25+
"minItems": 1,
26+
"uniqueItems": true
1827
}
1928
}
2029
}

0 commit comments

Comments
 (0)