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

# Platform

> Tax marketplace and platform sales, with your fees taxed separately

A platform calculation quotes tax for a sale where a [merchant](https://docs.numeral.com/v2026-01-01/objects/merchants.md) is the seller and you facilitate it. Use it if you're a marketplace, a payment processor, or a merchant of record. Your platform fees can be taxed separately from the order. Once the customer pays, record the sale with [Create platform transactions](#create-platform-transactions).

Platform endpoints are new in 2026-01-01 and require `X-API-Version: 2026-01-01`.

```text Where platform calculations fit theme={null}
Sale on your platform
├─ 1. Customer enters address
│     └─ POST /tax/platform/calculations
│          send:    customer + merchant + order (+ fees)
│          receive: order tax + fee tax + calculation id
└─ 2. Customer pays
      └─ POST /tax/platform/transactions
           send:    platform calculation id
           receive: list of transactions
```

Endpoints
[Create a platform calculationPOST/tax/platform/calculations](#create-a-platform-calculation)
[Create platform transactionsPOST/tax/platform/transactions](#create-platform-transactions)

## The Platform calculation object

### Attributes

**id** `string`

The ID of the platform calculation. Use it to create platform transactions.

**object** `string, value is "tax.calculation"`

String representing the object's type.

**testmode** `boolean`

`true` if made with a test API key.

**customer\_currency\_code** `string`

ISO 4217 currency code of the calculation.

**merchant** `object`

The merchant used in this calculation.

**merchant.id** `string`

The merchant's `id`.

**merchant.reference\_merchant\_id** `string`

Your reference ID for the merchant.

**roles** `array of strings`

Echo of the `roles` you sent.

**line\_items** `array of objects`

Tax on the order, one entry per line item in `order_details`.

**line\_items\[].product** `object`

Product information for this line item.

**line\_items\[].product.reference\_line\_item\_id** `string`

Echo of the `reference_line_item_id` you sent.

**line\_items\[].product.reference\_product\_id** `string`

The product ID in your system.

**line\_items\[].product.product\_tax\_code** `string`

The product category used to decide taxability.

**line\_items\[].tax\_jurisdictions** `array of objects`

One row per taxing jurisdiction.

**line\_items\[].tax\_jurisdictions\[].tax\_rate** `number`

Statutory rate for the jurisdiction, as a decimal fraction (`0.0875` = 8.75%). Some rates apply to only part of the amount, so don't sum these. See [Summing tax rates](https://docs.numeral.com/v2026-01-01/objects/calculations.md#summing-tax-rates).

**line\_items\[].tax\_jurisdictions\[].rate\_type** `string`

Descriptive rate classification, e.g. `SALES TAX`.

**line\_items\[].tax\_jurisdictions\[].jurisdiction\_name** `string`

Name of the jurisdiction, e.g. `California`.

**line\_items\[].tax\_jurisdictions\[].tax\_authority\_name** `string`

Name of the tax authority, e.g. `California State`.

**line\_items\[].tax\_jurisdictions\[].tax\_authority\_type** `enum`

`STATE`, `COUNTY`, `CITY`, or `DISTRICT`.

**line\_items\[].tax\_jurisdictions\[].tax\_type** `enum`

`SALES`, `USE`, `VAT`, or `GST`.

**line\_items\[].tax\_jurisdictions\[].fee\_amount** `number`

Fixed fee charged by this jurisdiction.

**line\_items\[].tax\_amount** `integer`

Tax for this line item, in the currency's smallest unit.

**line\_items\[].amount\_excluding\_tax** `integer`

Line amount before tax (`amount × quantity`).

**line\_items\[].amount\_including\_tax** `integer`

`amount_excluding_tax + tax_amount`.

**line\_items\[].quantity** `integer`

Echo of the quantity you sent.

**fee\_line\_items** `array of objects`

Tax on your platform fees, one entry per line item in `fee_details`. Same fields as `line_items`. Only present when `fee_details` is sent.

**totals** `object`

Totals for the order and for the fees, kept separate.

**totals.order** `object`

Totals for `line_items`.

**totals.order.tax\_amount** `integer`

Total tax on the order, in the currency's smallest unit.

**totals.order.amount\_excluding\_tax** `integer`

Order total excluding tax.

**totals.order.amount\_including\_tax** `integer`

Order total including tax.

**totals.fees** `object`

Totals for `fee_line_items`, with the same fields as `totals.order`. Only present when `fee_details` is sent.

**expires\_at** `timestamp`

Unix seconds when the quoted rates expire.

> [!NOTE]
>
> Always charge the returned `tax_amount`. For an effective rate, divide `tax_amount` by `amount_excluding_tax` instead of adding up `tax_rate` values. See [Summing tax rates](https://docs.numeral.com/v2026-01-01/objects/calculations.md#summing-tax-rates).

```json The Platform calculation object theme={null}
{
  "id": "calc_platform_987654321",
  "object": "tax.calculation",
  "testmode": true,
  "customer_currency_code": "USD",
  "line_items": [
    {
      "product": {
        "product_tax_code": "GENERAL_MERCHANDISE"
      },
      "tax_jurisdictions": [
        {
          "tax_rate": 0.0875,
          "rate_type": "SALES TAX",
          "jurisdiction_name": "California",
          "tax_authority_name": "California State",
          "tax_authority_type": "STATE",
          "tax_type": "SALES",
          "fee_amount": 0
        }
      ],
      "quantity": 2,
      "tax_amount": 875,
      "amount_excluding_tax": 10000,
      "amount_including_tax": 10875
    }
  ],
  "fee_line_items": [
    {
      "product": {
        "product_tax_code": "ELECTRONIC_GOODS"
      },
      "tax_jurisdictions": [
        {
          "tax_rate": 0.0875,
          "rate_type": "SALES TAX",
          "jurisdiction_name": "California",
          "tax_authority_name": "California State",
          "tax_authority_type": "STATE",
          "tax_type": "SALES",
          "fee_amount": 0
        }
      ],
      "quantity": 1,
      "tax_amount": 26,
      "amount_excluding_tax": 299,
      "amount_including_tax": 325
    }
  ],
  "totals": {
    "order": {
      "tax_amount": 875,
      "amount_excluding_tax": 10000,
      "amount_including_tax": 10875
    },
    "fees": {
      "tax_amount": 26,
      "amount_excluding_tax": 299,
      "amount_including_tax": 325
    }
  },
  "merchant": {
    "id": "merch_abc123",
    "reference_merchant_id": "my-seller-123"
  },
  "roles": ["payment_processor"],
  "expires_at": 1735690200
}
```

## Create a platform calculation

Quotes tax for an order and, optionally, your platform fees on it. [Try it in the API reference](https://docs.numeral.com/api-reference/v2026-01-01/endpoint/platform_calculations).

> [!WARNING]
>
> `amount` on every line item is the **per-unit** price. The taxable base is `amount × quantity`. For 3 items at \$25.00 each, send `"amount": 2500, "quantity": 3`: the taxable base is \$75.00.

### Parameters

**customer** `object` *required*

The buyer.

**customer.address** `object` *required*

The customer's address.

**customer.address.address\_line\_1** `string` *required*

**customer.address.address\_line\_2** `string`

**customer.address.address\_city** `string` *required*

**customer.address.address\_province** `string` *required*

ISO 3166-2 subdivision code.

**customer.address.address\_postal\_code** `string` *required*

**customer.address.address\_country** `string` *required*

ISO 3166-1 alpha-2 country code.

**customer.address.address\_type** `enum`

`shipping` or `billing`.

**customer.id** `string`

The `cust_…` ID or your own reference ID of a [customer](https://docs.numeral.com/v2026-01-01/objects/customers.md) you created in Numeral. Applies the customer's exemptions to the order: a tax-exempt customer gets zero tax, and exemption certificates on file for the customer apply for the destination jurisdiction. Not applied to `fee_details`, whose buyer is the merchant. If no customer matches, returns `CUSTOMER_NOT_FOUND` unless `default_customer_type` is sent.

**customer.type** `enum` (default: CONSUMER)

`CONSUMER` or `BUSINESS`.

**customer.tax\_ids** `array of objects`

Tax IDs for B2B sales. Each has `type` (e.g. `gb_vat`) and `value`. See [tax IDs](https://docs.numeral.com/essentials/tax-ids.md).

**merchant** `object` *required*

The seller. See [Merchants](https://docs.numeral.com/v2026-01-01/objects/merchants.md).

**merchant.merchant\_id** `string` *required*

The merchant's `id` (`merch_…`) or your `reference_merchant_id`.

**merchant.type** `enum` (default: BUSINESS)

`BUSINESS` or `INDIVIDUAL`.

**merchant.tax\_ids** `array of objects`

Overrides the merchant's stored tax IDs for this calculation.

**order\_details** `object` *required*

The order.

**order\_details.customer\_currency\_code** `string` *required*

ISO 4217 currency code, e.g. `USD` or `EUR`.

**order\_details.tax\_included\_in\_amount** `boolean` *required*

Whether line item amounts already include tax.

**order\_details.automatic\_tax** `enum` (default: auto)

* `auto` returns real rates only where you have an active tax registration, and 0 elsewhere.
* `disabled` always returns 0.
* `forced` returns real destination rates whatever your own registrations are. Use it as a payment processor to show the rates the merchant would owe. Only valid when `roles` is exactly `["payment_processor"]`. Customer exemptions, reverse charge and B2B rules still apply.

For US customer addresses, must be `auto` or `forced`: `disabled` is rejected.

**order\_details.line\_items** `array of objects` *required*

One entry per product.

**order\_details.line\_items\[].amount** `integer` *required*

**Per-unit** price in the currency's smallest unit. For a \$25.00 item, send `2500`.

**order\_details.line\_items\[].quantity** `integer` *required*

Number of units. Taxable base is `amount × quantity`.

**order\_details.line\_items\[].product\_category** `string`

Tax category from the [category list](https://docs.numeral.com/essentials/product-categories.md), e.g. `GENERAL_MERCHANDISE` or `SAAS_GENERAL`.

**order\_details.line\_items\[].reference\_product\_id** `string`

Your product ID, as created in Numeral as a [product](https://docs.numeral.com/v2026-01-01/objects/products.md).

**order\_details.line\_items\[].reference\_line\_item\_id** `string`

Your line item ID.

**roles** `array of enums` *required*

Your role in this sale. One or more of:

* `marketplace_provider`: you run a marketplace that connects buyers and sellers.
* `payment_processor`: you process the payment.
* `merchant_of_record`: you're the legal seller of record.

Roles also decide how many transactions [Create platform transactions](#create-platform-transactions) records.

**fee\_details** `object`

Your platform fees, taxed separately from the order. Same shape as `order_details`.

**fee\_details.customer\_currency\_code** `string` *required*

ISO 4217 currency code.

**fee\_details.tax\_included\_in\_amount** `boolean` *required*

Whether fee amounts already include tax.

**fee\_details.automatic\_tax** `enum` (default: auto)

`auto` or `disabled`. `forced` isn't allowed: the fee is your own tax event toward the merchant, so your own registrations apply.

**fee\_details.line\_items** `array of objects` *required*

One entry per fee, with the same fields as `order_details.line_items`. `amount` is per unit.

**default\_customer\_type** `enum`

`CONSUMER` or `BUSINESS`. Used when `customer.id` isn't found in Numeral: the order is priced with this customer type instead of returning `CUSTOMER_NOT_FOUND`. Lets you always send a customer ID without creating the customer first. If the customer is found, its exemptions apply as normal.

### Returns

A [Platform calculation object](#the-platform-calculation-object).

```bash With platform fees theme={null}
curl https://api.numeralhq.com/tax/platform/calculations \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -H 'X-API-Version: 2026-01-01' \
  -d '{
    "customer": {
      "address": {
        "address_line_1": "100 Market St",
        "address_city": "San Francisco",
        "address_province": "CA",
        "address_postal_code": "94105",
        "address_country": "US"
      }
    },
    "merchant": {
      "merchant_id": "my-seller-123"
    },
    "order_details": {
      "customer_currency_code": "USD",
      "tax_included_in_amount": false,
      "automatic_tax": "auto",
      "line_items": [
        {
          "amount": 5000,
          "quantity": 2,
          "product_category": "GENERAL_MERCHANDISE"
        }
      ]
    },
    "roles": ["payment_processor"],
    "fee_details": {
      "customer_currency_code": "USD",
      "tax_included_in_amount": false,
      "automatic_tax": "auto",
      "line_items": [
        {
          "amount": 299,
          "quantity": 1,
          "product_category": "ELECTRONIC_GOODS"
        }
      ]
    }
  }'
```

```bash Forced rates theme={null}
curl https://api.numeralhq.com/tax/platform/calculations \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -H 'X-API-Version: 2026-01-01' \
  -d '{
    "customer": {
      "address": {
        "address_line_1": "100 Market St",
        "address_city": "San Francisco",
        "address_province": "CA",
        "address_postal_code": "94105",
        "address_country": "US"
      }
    },
    "merchant": {
      "merchant_id": "my-seller-123"
    },
    "order_details": {
      "customer_currency_code": "USD",
      "tax_included_in_amount": false,
      "automatic_tax": "forced",
      "line_items": [
        {
          "amount": 2500,
          "quantity": 3,
          "product_category": "GENERAL_MERCHANDISE"
        }
      ]
    },
    "roles": ["payment_processor"]
  }'
```

```bash Exempt customer theme={null}
curl https://api.numeralhq.com/tax/platform/calculations \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -H 'X-API-Version: 2026-01-01' \
  -d '{
    "customer": {
      "id": "my-buyer-456",
      "address": {
        "address_line_1": "100 Market St",
        "address_city": "San Francisco",
        "address_province": "CA",
        "address_postal_code": "94105",
        "address_country": "US"
      }
    },
    "merchant": {
      "merchant_id": "my-seller-123"
    },
    "order_details": {
      "customer_currency_code": "USD",
      "tax_included_in_amount": false,
      "automatic_tax": "auto",
      "line_items": [
        {
          "amount": 2500,
          "quantity": 3,
          "product_category": "GENERAL_MERCHANDISE"
        }
      ]
    },
    "roles": ["marketplace_provider"],
    "default_customer_type": "CONSUMER"
  }'
```

```json Response theme={null}
{
  "id": "calc_platform_987654321",
  "object": "tax.calculation",
  "totals": {
    "order": {
      "tax_amount": 875,
      "amount_excluding_tax": 10000,
      "amount_including_tax": 10875
    },
    "fees": {
      "tax_amount": 26,
      "amount_excluding_tax": 299,
      "amount_including_tax": 325
    }
  },
  "...": "see The Platform calculation object"
}
```

## Create platform transactions

Records the sale from a platform calculation once the customer pays. Numeral uses it for reporting and filing. [Try it in the API reference](https://docs.numeral.com/api-reference/v2026-01-01/endpoint/platform_transactions).

How many transactions are created depends on the `roles` in the calculation:

| Role | Order transaction | Fee transaction |
| - | - | - |
| `payment_processor` | Yes, `client_role: ["payment_processor"]` | Yes, separate, `client_role: []` |
| `marketplace_provider` | Yes, `client_role: ["marketplace_provider"]` | No |
| `merchant_of_record` | Yes, `client_role: ["merchant_of_record"]` | No |

Payment processors get two transactions, so the fee's tax liability is reported separately from the order's. Marketplace providers and merchants of record get one transaction with all order items. Fee tax, if calculated, is included in it.

### Parameters

**platform\_calculation\_id** `string` *required*

The `id` of the platform calculation to record.

**reference\_order\_id** `string` *required*

Your unique ID for this order.

**reference\_payment\_id** `string`

Your ID for the payment.

**transaction\_processed\_at** `integer`

When the sale was processed, as a Unix timestamp.

### Returns

An object with `object: "list"` and a `transactions` array: two transactions for payment processors, one otherwise.

**transactions** `array of objects`

The transactions created.

**transactions\[].id** `string`

The ID of the transaction, `tr_…`.

**transactions\[].object** `string, value is "tax.transaction"`

String representing the object's type.

**transactions\[].calculation\_id** `string`

The platform calculation this transaction was created from.

**transactions\[].reference\_order\_id** `string`

Your order ID, as sent.

**transactions\[].reference\_payment\_id** `string`

Your payment ID, if sent.

**transactions\[].type** `enum`

`order` for the sale, or `fee` for the platform fee. `fee` transactions are created for payment processors only.

**transactions\[].client\_role** `array of strings`

Your role for this transaction. Empty on `fee` transactions.

**transactions\[].merchant** `object`

The merchant on the sale.

**transactions\[].merchant.id** `string`

The merchant's `id`.

**transactions\[].merchant.reference\_merchant\_id** `string`

Your reference ID for the merchant.

**transactions\[].customer\_currency\_code** `string`

ISO 4217 currency of the transaction.

**transactions\[].filing\_currency\_code** `string`

Currency the tax will be filed in.

**transactions\[].line\_items** `array of objects`

The line items, with the same fields as a [transaction's line items](https://docs.numeral.com/v2026-01-01/objects/transactions.md#the-transaction-object).

**transactions\[].testmode** `boolean`

`true` if made with a test API key.

**transactions\[].transaction\_processed\_at** `timestamp`

When the sale was processed.

```bash POST /tax/platform/transactions theme={null}
curl https://api.numeralhq.com/tax/platform/transactions \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -H 'X-API-Version: 2026-01-01' \
  -d '{
    "platform_calculation_id": "plat_calc_abc123",
    "reference_order_id": "order_12345",
    "reference_payment_id": "pay_67890",
    "transaction_processed_at": 1736300000
  }'
```

```json Payment processor theme={null}
{
  "object": "list",
  "transactions": [
    {
      "id": "tr_abc123",
      "object": "tax.transaction",
      "calculation_id": "plat_calc_abc123",
      "reference_order_id": "order_12345",
      "type": "order",
      "client_role": ["payment_processor"],
      "merchant": {
        "id": "merch_abc123",
        "reference_merchant_id": "my-seller-123"
      },
      "testmode": false
    },
    {
      "id": "tr_def456",
      "object": "tax.transaction",
      "calculation_id": "plat_calc_abc123",
      "reference_order_id": "order_12345",
      "type": "fee",
      "client_role": [],
      "merchant": {
        "id": "merch_abc123",
        "reference_merchant_id": "my-seller-123"
      },
      "testmode": false
    }
  ]
}
```

```json Marketplace provider theme={null}
{
  "object": "list",
  "transactions": [
    {
      "id": "tr_abc123",
      "object": "tax.transaction",
      "calculation_id": "plat_calc_abc123",
      "reference_order_id": "order_12345",
      "type": "order",
      "client_role": ["marketplace_provider"],
      "merchant": {
        "id": "merch_abc123",
        "reference_merchant_id": "my-seller-123"
      },
      "testmode": false
    }
  ]
}
```

## Errors

Errors return `code`, `type`, and `message`. Handle them by `type`. Full list in [Error Codes](https://docs.numeral.com/api-reference/v2026-01-01/error-codes.md).

| HTTP | `type` | When |
| - | - | - |
| 400 | `MISSING_FIELD` | A required field is missing. |
| 400 | `INCORRECT_TYPE` | A field has the wrong type. |
| 400 | `UNRECOGNIZED_FIELD` | An unknown field was sent. |
| 400 | `MISSING_ORIGIN_ADDRESS` | No origin address. Check the merchant's `default_address`. |
| 404 | `MERCHANT_NOT_FOUND` | `merchant.merchant_id` doesn't exist, was deleted, or belongs to the other mode (test or live). |
| 404 | `CUSTOMER_NOT_FOUND` | `customer.id` doesn't exist and no `default_customer_type` was sent. |
| 404 | `CALCULATION_NOT_FOUND` | `platform_calculation_id` doesn't exist. |

```json 404 merchant theme={null}
{
  "code": 404,
  "type": "MERCHANT_NOT_FOUND",
  "message": "Merchant not found or belongs to different testmode"
}
```

```json 404 customer theme={null}
{
  "code": 404,
  "type": "CUSTOMER_NOT_FOUND",
  "message": "Unable to find customer with ID: my-buyer-456 in test environment."
}
```

```json 404 calculation theme={null}
{
  "code": 404,
  "type": "CALCULATION_NOT_FOUND",
  "message": "Platform calculation not found"
}
```


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