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

# Send Level 2 and Level 3 Card Data

> Send purchase order, tax, and line-item detail with card payments so business, purchasing, and corporate cards can qualify for lower interchange.

Level 2 and Level 3 data is extra order detail that you send with a card payment. When the cardholder uses a **business, purchasing, or corporate card**, the card networks can charge a lower interchange fee on transactions that carry it. It matters most for B2B and government sales in the United States, and it has no effect on consumer cards.

| Level | What you send | Typical use |
| - | - | - |
| **Level 2** | Customer reference (purchase order number) and the sales tax amount | Any commercial-card sale |
| **Level 3** | Level 2, plus every line item (product code, quantity, unit of measure, unit price, commodity code, discount, tax), freight, and ship-to details | Physical goods shipped to a business or agency |

> [!NOTE]
>
> Therius forwards the data. Whether a payment actually qualifies for the lower rate is decided by the card network, the issuer, and your acquirer, based on the card type, your merchant category, and the amounts.

## Opt in with `commercialData`

Add a `commercialData` object at the root of a card `POST /payment/purchase` or `POST /payment/authorization` request, next to `lineItems`. Level 3 line detail is read from `lineItems` only when `commercialData` is present.

| Field | Type | Description |
| - | - | - |
| `customerReference` | string | Your buyer's reference for the order, such as a purchase order number. Up to 25 printable ASCII characters, no leading space. |
| `taxAmount` | integer | Total sales tax included in the payment `amount`, in minor units. Omit it to use the sum of the line items' `taxAmount`. Send `0` for a tax-exempt order. |
| `freightAmount` | integer | Shipping or freight included in the payment `amount`, in minor units. |
| `shipFromPostalCode` | string | Postal code the goods ship from, up to 10 characters. |
| `destination` | object | Where the goods go: `countryCode` (ISO 3166-1), `postalCode` (up to 10 characters), and `stateOrProvince` (up to 3 characters). |
| `orderDate` | string | Purchase order date, `YYYY-MM-DD`. |

For Level 2, `customerReference` and the tax amount are all you need. For Level 3, also add the following fields to **every** item in `lineItems`:

| Field | Type | Description |
| - | - | - |
| `description` | string | What the item is. Required. |
| `quantity` | integer | Units purchased, 1 to 9999. Required. |
| `unitAmount` | integer | Price of one unit in minor units, before discount and tax. Setting it on a line item marks the request as Level 3, so set it on all line items or none. |
| `amount` | integer | The line total **including the line's tax**. It must equal `unitAmount × quantity − discountAmount + taxAmount`. |
| `productCode` | string | Product code or SKU, up to 12 characters. Defaults to `id`. |
| `unitOfMeasure` | string | Unit of measure code, such as `EA` for each. |
| `commodityCode` | string | Commodity code for the item (UNSPSC, NAICS, or NAPCS), up to 12 characters. |
| `discountAmount` | integer | Discount applied to the line, in minor units. |
| `taxAmount` | integer | Tax on the line, in minor units. |

## The amounts must add up

Therius checks the arithmetic before it calls the provider and returns a `400` with the exact mismatch if it fails:

```
sum of (unitAmount × quantity − discountAmount) + total tax + freightAmount = payment amount
```

Each line's `amount` is its own total with tax, as in the example below.

```json theme={"dark"}
{
  "merchantCode": "MERCHANT_001",
  "orderCode": "ORDER-1001",
  "amount": { "currency": "USD", "value": 12800, "exponent": 2 },
  "paymentMethod": { "type": "card", "card": { "nonceData": { "nonce": "<nonce>" } } },
  "commercialData": {
    "customerReference": "PO-2026-9",
    "freightAmount": 300,
    "shipFromPostalCode": "94110",
    "destination": { "countryCode": "US", "postalCode": "94117", "stateOrProvince": "CA" },
    "orderDate": "2026-10-25"
  },
  "lineItems": [
    {
      "description": "Widget", "quantity": 2, "unitAmount": 5000, "discountAmount": 500, "taxAmount": 900,
      "amount": 10400, "productCode": "W-1", "unitOfMeasure": "EA", "commodityCode": "44121706"
    },
    {
      "description": "Gadget", "quantity": 1, "unitAmount": 2000, "taxAmount": 100,
      "amount": 2100, "productCode": "G-2", "unitOfMeasure": "EA", "commodityCode": "44121706"
    }
  ]
}
```

Here the net lines are 9,500 + 2,000 = 11,500, the tax is 900 + 100 = 1,000, and freight is 300, which totals 12,800.

> [!TIP]
>
> If you send both an order-level `taxAmount` and line-level `taxAmount` values, they must agree. Send tax at only one level if you prefer.

## Send it on capture

If you authorize first and capture later, you can send `commercialData` and `lineItems` in the body of `POST /payment/{id}/capture`. Do this when you did not send the data with the authorization, or when the captured amount or lines differ from it. The same rules apply, checked against the capture `amount`.

## Checkout sessions lock the data

When you create a checkout session with `POST /sdk/session`, pass `commercialData` and `lineItems` there. The session locks them: a purchase made with the session token always uses the locked values and ignores any `commercialData` in the purchase call, because that call can come from the browser. A purchase your server makes with a private API key sends its own `commercialData`.

## What each connection sends

| Connection | Level 2 | Level 3 | Authorization and purchase | Capture |
| - | - | - | - | - |
| Adyen | Yes | Yes | Yes | Yes |
| Stripe | Yes | Yes | Yes | Yes |
| NMI | Yes | Yes | Yes | No |

Other card connections ignore `commercialData`; the payment is processed normally.

Each acquirer is strict about what it accepts, and Therius never declines or fails a payment because enhanced data is missing or rejected. When the data falls short, Therius sends what it can:

* **Adyen** requires `customerReference` and tax at both levels, a non-zero tax for Level 2, and on every line a `productCode` (up to 12 characters), `unitOfMeasure` (up to 3 characters), and `commodityCode` (up to 12 characters). If a line is missing one, Therius sends Level 2 only. Descriptions are cut to 26 characters.
* **Stripe** uses your `orderCode` as the order reference and sends the order-level tax. Product code, unit of measure, and commodity code are optional for the request but needed to receive Level 3 rates. If your Stripe account's API version does not yet support payment line items, Therius sends the payment without the data.
* **NMI** accepts up to 99 line items. With more, Therius sends the order-level fields only.

## What is not included

* Level 2/3 data is for card payments. It is ignored for alternative payment methods and wallets that settle outside the card networks.
* Refunds and cancellations do not carry it.
* Duty, VAT, and order-level discount fields are not supported. Put discounts on the line items.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.