> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.runpayments.io/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.runpayments.io/_mcp/server.

# P3 Qualification (L2/L3)

## Overview

**CEDP** — Visa's **Commercial Enhanced Data Program** — is a network initiative that modernizes how B2B and B2G transactions qualify for preferred interchange rates. It replaces legacy Level 2/Level 3 data programs with a validated, structured data standard enforced at the network level.

At Run, we refer to the additional payload fields required for CEDP eligibility as **P3 Qualification**. When a commercial card transaction includes a complete set of P3 fields, it becomes eligible for lower interchange rates — a meaningful cost reduction for high-volume B2B merchants.

> **Note**
>
> **Who does this apply to?** CEDP requirements apply to merchants processing commercial (corporate, purchasing, or business) credit cards in B2B or B2G contexts. Consumer card transactions are unaffected. P3 fields are supported on **Cardpointe**, **Payroc**, and **Cybersource** gateways.

---

## How P3 Qualification Works

To qualify a transaction at P3, the charge request must include:

* **Order-level fields** — tax amounts, freight, duty, purchase order number, and order date
* **Shipping details** — destination ZIP, origin ZIP, and destination country
* A populated **`line_items` array** with at least one complete line item
* Each line item must include a description, quantity, unit cost, net amount, and tax amount

---

## Example Request

The following is a complete charge request payload including all fields required to qualify for P3. Standard charge fields (`mid`, `amount`, `account_token`, etc.) are included for context — the P3-specific fields begin at `tax_exempt`.

```json
{
  "mid": "800000001780",
  "amount": "100.00",
  "account_token": "9416285736761111",
  "account_zip": "19087",
  "expiration": "20291",
  "name": "Testing Test",
  "capture": "Y",
  "cvn": 112,
  "vault": "N",
  "tax_exempt": "N",
  "po_number": "12345678",
  "tax_amount": "0",
  "freight_amount": "0",
  "duty_amount": "0",
  "order_date": "24116",
  "invoice_id": "123456",
  "shipping_zip": "55555",
  "origin_zip": "55555",
  "shipping_country": "US",
  "line_items": [
    {
      "line_number": "1",
      "material": "1005",
      "description": "Ergonomic Office Chair",
      "upc": "80101500",
      "quantity": "1",
      "measure": "each",
      "unit_cost": "100.00",
      "net_amount": "100.00",
      "discount": "0.00",
      "item_tax_amount": "0"
    }
  ]
}
```

---

## P3 Parameter Reference

All P3 fields are optional on the base charge endpoint but **required as a complete set** for CEDP qualification. Submitting a partial set may result in data validation failure at the network level.

### Order-Level Fields

| Parameter        | Type   | Description                                                                                                                                                                                      | Example      |
| ---------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------ |
| `tax_exempt`     | string | Indicates whether the transaction is tax-exempt. Pass `Y` for tax-exempt transactions; `N` otherwise. When `Y`, `tax_amount` must be `0`.                                                        | `"N"`        |
| `po_number`      | string | Customer purchase order number associated with the transaction. Required for most commercial card programs. Max 25 characters.                                                                   | `"12345678"` |
| `tax_amount`     | string | Total tax amount applied to the order, expressed as a decimal. Must be `0` if `tax_exempt` is `Y`. Should reflect the sum of all line-item tax amounts.                                          | `"8.50"`     |
| `freight_amount` | string | Total shipping or freight charges for the order, expressed as a decimal. Defaults to `0` if not applicable.                                                                                      | `"12.00"`    |
| `duty_amount`    | string | Total customs duty or import fee amount for the order, expressed as a decimal. Defaults to `0` if not applicable.                                                                                | `"0"`        |
| `order_date`     | string | The order or shipment date in `YYDDD` format, where `YY` is the two-digit year and `DDD` is the day of the year (001–365). For most industries this represents the delivery or fulfillment date. | `"24116"`    |
| `invoice_id`     | string | Merchant-defined invoice identifier for the order. Used for reconciliation and dispute management. Max 25 characters.                                                                            | `"123456"`   |

### Shipping Fields

| Parameter          | Type   | Description                                                                                                                                                | Example   |
| ------------------ | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- |
| `shipping_zip`     | string | Destination postal (ZIP) code for the shipment. For US addresses, must be 5 or 9 digits. For international addresses, any alphanumeric string is accepted. | `"55555"` |
| `origin_zip`       | string | Origin postal (ZIP) code from which the order ships. Same format rules as `shipping_zip`.                                                                  | `"19087"` |
| `shipping_country` | string | Two-character ISO 3166-1 alpha-2 country code for the shipping destination. Defaults to `US` if not provided.                                              | `"US"`    |

### Line Items — `line_items[]`

The `line_items` array contains individual product or service line items for the order. At least one fully populated line item is required for P3 qualification. All monetary values should be expressed as decimal strings.

| Parameter         | Type   | Description                                                                                                                                                                                 | Example                    |
| ----------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------- |
| `line_number`     | string | Sequential line item number beginning at `1`. Used to uniquely identify each item within the order.                                                                                         | `"1"`                      |
| `material`        | string | Merchant's internal SKU, part number, or material code for the item.                                                                                                                        | `"1005"`                   |
| `description`     | string | Unique description of the product or service in 2 words or more. Max 26 characters.                                                                                                         | `"Ergonomic Office Chair"` |
| `upc`             | string | Universal Product Code for the item. Pass `80101500` as a placeholder if the product does not have a registered UPC.                                                                        | `"80101500"`               |
| `quantity`        | string | Number of units of this line item included in the order.                                                                                                                                    | `"1"`                      |
| `measure`         | string | Unit of measure for the item quantity. Common values: `each` or `ton`.                                                                                                                      | `"each"`                   |
| `unit_cost`       | string | Per-unit cost amount, expressed as a decimal.                                                                                                                                               | `"100.00"`                 |
| `net_amount`      | string | Total line-item amount before tax, expressed as a decimal. Should equal unit cost × quantity (less any discount). The sum of all `net_amount` values should reconcile with the order total. | `"100.00"`                 |
| `item_tax_amount` | string | Tax amount applied to this specific line item, expressed as a decimal. Pass `0` for tax-exempt items. The sum across all line items should equal the order-level `tax_amount`.              | `"0"`                      |
| `discount`        | string | Discount amount applied to this line item, expressed as a decimal. Pass `0` if not applicable.                                                                                              | `"0.00"`                   |

---

## Implementation Notes

> **Note**
>
> **Field completeness matters.** CEDP validation occurs at the network level. A transaction with missing or zero-valued required fields may pass authorization but fail data qualification, resulting in a downgrade. Populate all P3 fields for every eligible commercial card transaction.

**Detecting commercial cards:** The charge response includes a `comm_card` flag (`Y`/`N`). You can use this in your post-authorization logic to verify that a P3 payload was correctly submitted for commercial card transactions.

**order_date format:** `order_date` uses the `YYDDD` format. For example, April 25, 2024 is the 116th day of 2024, so the value would be `24116`. Most server-side date libraries can convert a standard date to a day-of-year value with a single call.

**Tax reconciliation:** Visa validates that the sum of `item_tax_amount` across all line items aligns with the order-level `tax_amount`. Mismatches can trigger qualification failures. If tax is zero across all items, pass `0` at both levels.

**Surcharging:** When a merchant is enrolled in a Compliant Surcharge Program through the gateway, the surcharge amount is applied at settlement rather than being included in the original charge `amount`. Because CEDP validation reconciles line-item totals against the transaction amount, the surcharge must still be represented in the `line_items` array so the data aligns at qualification. Add a dedicated surcharge line item with `description: "Surcharge Total"` and `net_amount` set to the surcharge amount. All other standard line-item fields should still be populated.

```json
{
  "line_items": [
    {
      "line_number": "1",
      "material": "1005",
      "description": "Ergonomic Office Chair",
      "upc": "80101500",
      "quantity": "1",
      "measure": "each",
      "unit_cost": "100.00",
      "net_amount": "100.00",
      "discount": "0.00",
      "item_tax_amount": "0"
    },
    {
      "line_number": "2",
      "material": "SURCHARGE",
      "description": "Surcharge Total",
      "upc": "80101500",
      "quantity": "1",
      "measure": "each",
      "unit_cost": "3.00",
      "net_amount": "3.00",
      "discount": "0.00",
      "item_tax_amount": "0"
    }
  ]
}
```

**Questions?** Contact [integrations@runpayments.io](mailto:integrations@runpayments.io) to confirm CEDP enrollment status for your merchant account or for guidance on integration testing.