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

# Process a transaction

> Commit a basket transaction for a BrandWallet customer's card: run campaigns, redeem applied coupons, and deduct spent points in a single call.

`POST /v1/transactions/process` commits a transaction for the selected `card`. Three things can happen, individually or together:

<Steps>
  <Step title="Campaign collection">
    Applicable campaigns on the card run; balances update and reward coupons are granted when thresholds are reached.
  </Step>

  <Step title="Coupon redemption">
    Any `reward` (coupon instance id) on a line item or at the order level is redeemed.
  </Step>

  <Step title="Point spend">
    `pointsToSpend` is deducted from the card's point balance.
  </Step>
</Steps>

```bash theme={null}
POST $BASE_URL/v1/transactions/process
```

Discount amounts (`discountAmount` / `discountedAmount`, per-line and order-level) are calculated by your system and stored as-is. Product, user, and branch IDs are **opaque IDs**. `user` and `branch` default to the authenticated user and its branch.

## Request headers

<ParamField header="Authorization" type="string" required>
  Your active Bearer token: `Bearer <accessToken>`.
</ParamField>

<ParamField header="Content-Type" type="string" required>
  Always `application/json`.
</ParamField>

## Request body

<ParamField body="customer" type="string" required>
  Customer id (from [GET /v1/customers/find](/api/find-customer)).
</ParamField>

<ParamField body="card" type="string" required>
  Selected card (customerpass id). The campaigns run come from this card.
</ParamField>

<ParamField body="user" type="string">
  Cashier user opaque id.
</ParamField>

<ParamField body="branch" type="string">
  Branch opaque id.
</ParamField>

<ParamField body="items" type="array">
  Basket lines.

  <Expandable title="item fields">
    <ParamField body="id" type="string" required>
      Product opaque id.
    </ParamField>

    <ParamField body="quantity" type="number">
      Line quantity.
    </ParamField>

    <ParamField body="price" type="number">
      Unit price.
    </ParamField>

    <ParamField body="name" type="string">
      Product name.
    </ParamField>

    <ParamField body="discountAmount" type="number">
      Discount applied to the line.
    </ParamField>

    <ParamField body="discountedAmount" type="number">
      Final line amount after discounts.
    </ParamField>

    <ParamField body="reward" type="string">
      Coupon instance id applied to this line. It will be redeemed.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="amount" type="number">
  Total amount before discounts.
</ParamField>

<ParamField body="discountAmount" type="number">
  Total discount applied to the order.
</ParamField>

<ParamField body="discountedAmount" type="number">
  Final amount after discounts.
</ParamField>

<ParamField body="reward" type="string[]">
  Coupon instance ids applied to the order total. They will be redeemed.
</ParamField>

<ParamField body="pointsToSpend" type="number">
  Loyalty points the customer spends on the order total. They will be deducted.
</ParamField>

## Response fields (200 OK)

<ResponseField name="message" type="string">
  Human-readable summary of what happened.
</ResponseField>

<ResponseField name="executedActions" type="array">
  Campaign actions executed in this transaction.

  <Expandable title="executed action fields">
    <ResponseField name="actionName" type="string">
      Name of the campaign action.
    </ResponseField>

    <ResponseField name="transactionCategory" type="string">
      Transaction category the action belongs to.
    </ResponseField>

    <ResponseField name="netCollected" type="number">
      Amount collected by this action in the current transaction.
    </ResponseField>

    <ResponseField name="previousCollectableValue" type="number">
      Collectable value before the action ran.
    </ResponseField>

    <ResponseField name="result" type="object">
      Updated collectable state: `value` (current spendable balance) and `total` (lifetime total).
    </ResponseField>

    <ResponseField name="rewards" type="string[]">
      Coupon instance ids granted when a threshold was reached.
    </ResponseField>
  </Expandable>
</ResponseField>

<RequestExample>
  ```bash Request theme={null}
  curl --request POST \
    --url "$BASE_URL/v1/transactions/process" \
    --header 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...' \
    --header 'Content-Type: application/json' \
    --data '{
      "customer": "3d8ec956-de2a-4d43-9c1e-74475b153362",
      "card": "41dd8263-288e-4b55-bf2e-6a82995a0441",
      "items": [
        { "id": "8f26e6c7-...", "quantity": 4, "price": 140, "name": "Americano" }
      ],
      "amount": 560,
      "pointsToSpend": 120
    }'
  ```
</RequestExample>

<ResponseExample>
  ```json 200 OK theme={null}
  {
    "message": "You collected 4 stamps, earned a Free Coffee coupon",
    "executedActions": [
      {
        "actionName": "collect-stamps",
        "transactionCategory": "collect-stamps",
        "netCollected": 4,
        "previousCollectableValue": 3,
        "result": { "value": 2, "total": 12 },
        "rewards": ["2f19b6ba-e7f8-4dd5-b328-cbfabc08e412"]
      }
    ]
  }
  ```

  ```json 400 Bad Request theme={null}
  {
    "statuscode": 400,
    "errorcode": 400,
    "message": "_insufficient_collectable_balance",
    "description": "",
    "timestamp": 1754040000000,
    "path": "/v1/transactions/process",
    "method": "POST"
  }
  ```
</ResponseExample>

<Tip>
  Preview the discount a point spend would produce with [POST /v1/transactions/validate](/api/validate-transaction) before committing.
</Tip>
