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

# POST /transaction — Process a cash transaction

> Submit a cash transaction for jurisdiction-aware rounding. Pass merchant ID, amounts in cents, payment method, and a ZIP code or state. Returns rounded total and compliance status.

The `/transaction` endpoint is the core of the Centsless API. You send a transaction, and the engine resolves the jurisdiction, applies the correct rounding rule for that location, and returns the legally correct cash total — complete with compliance certification and a fraud score. Every transaction is committed to an immutable audit hash chain, giving you a tamper-evident record for regulators and auditors.

## Endpoint

```
POST https://api.centsless.org/api/v1/transaction
```

## Authentication

All requests require an `x-api-key` header. Use your merchant key or partner key.

<ParamField header="x-api-key" type="string" required>
  Your merchant or partner API key.
</ParamField>

## Request body

<ParamField body="merchant_id" type="string" required>
  Unique merchant identifier issued by Centsless or your POS vendor.
</ParamField>

<ParamField body="subtotal_cents" type="integer" required>
  Pre-tax subtotal in cents. Tax is always calculated on this pre-rounded amount.
</ParamField>

<ParamField body="tax_total_cents" type="integer" required>
  Sales tax in cents. Always pass the tax calculated on the pre-rounded subtotal — never recalculate tax after rounding.
</ParamField>

<ParamField body="payment_method" type="string" required>
  Payment tender type. One of: `cash`, `card`, `ebt`, `mobile`. Only `cash` transactions are subject to rounding. EBT transactions are never rounded per 7 CFR 278.2.
</ParamField>

<ParamField body="zip_code" type="string">
  ZIP code for automatic jurisdiction resolution. Recommended — the engine resolves state, county, city, and the applicable rounding rule from a single field.
</ParamField>

<ParamField body="state" type="string">
  Two-letter state code (e.g., `AZ`, `IN`). Use when you don't have a ZIP code.
</ParamField>

<ParamField body="county" type="string">
  County name for sub-state jurisdiction resolution. Combined with `state` for county-level rules.
</ParamField>

<ParamField body="city" type="string">
  City name for municipal-level jurisdiction resolution. Combined with `state` and `county`.
</ParamField>

<ParamField body="cash_rounding_mode" type="string">
  Explicit rounding mode override. One of: `swedish_rounding`, `mandatory_round_down`, `mandatory_round_up`, `symmetrical_rounding`, `nearest_nickel`, `none`. Use for testing only — omit this field in production to let the engine resolve the correct rule for the jurisdiction.
</ParamField>

<ParamField body="store_id" type="string">
  Store location identifier for multi-location merchants.
</ParamField>

<ParamField body="terminal_id" type="string">
  POS terminal identifier. Included in the audit record.
</ParamField>

<ParamField body="cashier_id" type="string">
  Cashier or employee identifier. Included in the audit record.
</ParamField>

<ParamField body="is_split_tender" type="boolean">
  Set to `true` when the customer is splitting payment across multiple tender types.
</ParamField>

<ParamField body="tenders" type="array">
  Array of tender components for split tender transactions. Each item has a `type` (one of `cash`, `card`, `ebt`, `mobile`) and an `amount_cents` integer.
</ParamField>

## Examples

<CodeGroup>
  ```bash Arizona cash (ZIP code) theme={null}
  curl -X POST https://api.centsless.org/api/v1/transaction \
    -H "Content-Type: application/json" \
    -H "x-api-key: YOUR_API_KEY" \
    -d '{
      "merchant_id": "YOUR-MERCHANT-ID",
      "subtotal_cents": 523,
      "tax_total_cents": 200,
      "payment_method": "cash",
      "zip_code": "85001"
    }'
  ```

  ```bash Indiana cash (state code) theme={null}
  curl -X POST https://api.centsless.org/api/v1/transaction \
    -H "Content-Type: application/json" \
    -H "x-api-key: YOUR_API_KEY" \
    -d '{
      "merchant_id": "YOUR-MERCHANT-ID",
      "subtotal_cents": 523,
      "tax_total_cents": 200,
      "payment_method": "cash",
      "state": "IN"
    }'
  ```

  ```bash EBT (exempt from rounding) theme={null}
  curl -X POST https://api.centsless.org/api/v1/transaction \
    -H "Content-Type: application/json" \
    -H "x-api-key: YOUR_API_KEY" \
    -d '{
      "merchant_id": "YOUR-MERCHANT-ID",
      "subtotal_cents": 523,
      "tax_total_cents": 200,
      "payment_method": "ebt",
      "state": "AZ"
    }'
  ```
</CodeGroup>

## Response fields

<ResponseField name="transaction" type="object">
  The processed transaction record.

  <Expandable title="properties">
    <ResponseField name="id" type="string">
      Unique transaction identifier. Format: `TXN-YYYY-MM-DD-XXXXXXXX` (e.g., `TXN-2026-04-14-A82C2EAA`).
    </ResponseField>

    <ResponseField name="calculation" type="object">
      Rounding calculation results.

      <Expandable title="properties">
        <ResponseField name="cash_total_cents" type="integer">
          Post-rounded cash total to collect from the customer, in cents.
        </ResponseField>

        <ResponseField name="rounding_delta_cents" type="integer">
          The rounding adjustment in cents — the difference between the ledger total and the cash total. Positive means rounded up, negative means rounded down.
        </ResponseField>

        <ResponseField name="cash_rounding_mode" type="string">
          The rounding method applied to this transaction (e.g., `swedish_rounding`).
        </ResponseField>

        <ResponseField name="jurisdiction" type="string">
          The resolved jurisdiction identifier (e.g., `US-AZ`).
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="compliance" type="object">
      Compliance certification for this transaction.

      <Expandable title="properties">
        <ResponseField name="compliance_status" type="string">
          Overall compliance result. One of: `PASS`, `WARN`, or `FAIL`.
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="fraud_score" type="integer">
      Fraud risk score for this transaction. `0` means no detected risk.
    </ResponseField>

    <ResponseField name="risk_level" type="string">
      Risk classification. One of: `NONE`, `LOW`, `MEDIUM`, `HIGH`, `CRITICAL`.
    </ResponseField>

    <ResponseField name="auditHash" type="string">
      SHA-256 hash of this transaction record. Each hash includes the previous transaction's hash, forming a tamper-evident chain.
    </ResponseField>
  </Expandable>
</ResponseField>

## Response example

```json theme={null}
{
  "success": true,
  "transaction": {
    "id": "TXN-2026-04-14-A82C2EAA",
    "calculation": {
      "subtotal_cents": 523,
      "tax_total_cents": 200,
      "ledger_total_cents": 723,
      "cash_total_cents": 725,
      "rounding_delta_cents": 2,
      "payment_method": "cash",
      "cash_rounding_mode": "swedish_rounding",
      "jurisdiction": "US-AZ",
      "rounding_applied": true
    },
    "compliance": {
      "compliance_status": "PASS"
    },
    "fraud_score": 0,
    "risk_level": "NONE"
  }
}
```

The customer pays \*\*$7.25** instead of $7.23. The 2-cent rounding delta is applied per Arizona HB 2938 (mandatory Swedish rounding).
