> ## 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.

# Find a customer

> Resolve a single BrandWallet customer by phone, email, or card barcode. Returns loyalty balances, wallet cards, and active coupons in one call.

`GET /v1/customers/find` resolves a customer of your organization using a single search term. Use it to identify the customer who is checking out, and to load their cards and coupons before running a transaction.

```bash theme={null}
GET $BASE_URL/v1/customers/find?q=<term>
```

The `q` term is matched in three ways:

<Steps>
  <Step title="Phone">
    Case-insensitive substring match on `data.phone`.
  </Step>

  <Step title="Email">
    Exact match on `data.email`.
  </Step>

  <Step title="Barcode">
    Exact match. Only attempted when `q` is purely numeric.
  </Step>
</Steps>

The first matching customer is returned, with loyalty balances (`collectables`), wallet cards (`cards`), and active coupons (`coupons`).

## Request headers

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

## Query parameters

<ParamField query="q" type="string" required>
  Search term: phone, email, or card barcode.
</ParamField>

## Response fields (200 OK)

<ResponseField name="id" type="string">
  Unique identifier of the customer. Use it on the coupon and transaction endpoints.
</ResponseField>

<ResponseField name="data" type="object">
  Customer profile fields (`fullname`, `phone`, `email`, ...). The set of keys depends on the organization's customer form configuration.
</ResponseField>

<ResponseField name="collectables" type="object">
  Loyalty balances, keyed by collectable key.

  <Expandable title="collectable entry fields">
    <ResponseField name="label" type="string">
      Optional human-readable label.
    </ResponseField>

    <ResponseField name="value" type="number">
      Current spendable balance.
    </ResponseField>

    <ResponseField name="total" type="number">
      Lifetime collected total.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="cards" type="array">
  The customer's wallet cards. A single entry for a barcode search; possibly several for email/phone.

  <Expandable title="card fields">
    <ResponseField name="id" type="string">
      Customerpass id. Send it as `card` on other endpoints.
    </ResponseField>

    <ResponseField name="name" type="string">
      Card name.
    </ResponseField>

    <ResponseField name="barcode" type="string">
      Card barcode.
    </ResponseField>

    <ResponseField name="status" type="number">
      Status code of the card.
    </ResponseField>

    <ResponseField name="options" type="object">
      Campaign configuration of the card. Present only when the card has a point campaign; omitted otherwise.

      <Expandable title="options fields">
        <ResponseField name="spend" type="object">
          Point-spend configuration of the card's point campaign. For tiered point campaigns the values reflect the customer's current tier.

          <Expandable title="spend fields">
            <ResponseField name="ratio" type="number">
              Money value of a single point, precomputed as `convertto / pointstoconvert`. Multiply the points to spend by `ratio` to get the discount amount. E.g. `ratio: 0.1` means 1 point is worth 0.10 in currency.
            </ResponseField>

            <ResponseField name="pointstoconvert" type="number">
              How many points convert into `convertto` currency units.
            </ResponseField>

            <ResponseField name="convertto" type="number">
              Currency amount that `pointstoconvert` points convert into.
            </ResponseField>

            <ResponseField name="collectwhilespending" type="boolean">
              Whether the customer keeps collecting points on the portion of the basket paid with points.
            </ResponseField>

            <ResponseField name="collectfromdiscountedamount" type="boolean">
              Whether points are collected over the discounted amount instead of the gross amount.
            </ResponseField>
          </Expandable>
        </ResponseField>
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="coupons" type="array">
  The customer's active coupons. Same shape as items in [GET /v1/customers/:id/coupons](/api/list-coupons).

  <Expandable title="coupon fields">
    <ResponseField name="id" type="string">
      Coupon instance id. Use it as `:couponId` on redeem, or as `reward` on transactions.
    </ResponseField>

    <ResponseField name="coupon" type="object">
      Coupon summary: `name`.
    </ResponseField>

    <ResponseField name="code" type="string">
      Coupon code, when one is assigned. Optional.
    </ResponseField>

    <ResponseField name="type" type="string">
      Coupon type, e.g. `discount` or `product`. Optional.
    </ResponseField>

    <ResponseField name="discountAmount" type="number">
      Discount value. Interpreted as a percentage when `isPercent` is true. For `product` coupons this is `100` with `isPercent: true` (the product is free). Optional.
    </ResponseField>

    <ResponseField name="isPercent" type="boolean">
      Whether `discountAmount` is a percentage. Optional.
    </ResponseField>

    <ResponseField name="maxDiscountAmount" type="number">
      Cap for percentage discounts. Optional.
    </ResponseField>

    <ResponseField name="includesModifiers" type="boolean">
      Whether product modifiers are included in the discount. Optional.
    </ResponseField>

    <ResponseField name="products" type="object">
      Which products the coupon applies to. Present on product-scoped coupons.

      <Expandable title="products fields">
        <ResponseField name="quantity" type="number">
          How many items the coupon covers.
        </ResponseField>

        <ResponseField name="productIds" type="string[]">
          Product opaque ids the coupon applies to.
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="issued" type="object">
      Where the coupon was issued (`branch`, `user`). Optional.
    </ResponseField>

    <ResponseField name="issuedAt" type="string">
      When the coupon was issued (ISO 8601). Optional.
    </ResponseField>

    <ResponseField name="expiresAt" type="string">
      Expiry time (ISO 8601). Optional.
    </ResponseField>

    <ResponseField name="status" type="string">
      Coupon status, e.g. `active`.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="metaData" type="object">
  Free-form metadata attached to the customer. Optional.
</ResponseField>

<ResponseField name="consents" type="object">
  Customer consent flags. Optional.
</ResponseField>

<ResponseField name="barcode" type="string | null">
  Customer-level barcode, when one is assigned.
</ResponseField>

<ResponseField name="opaqueId" type="string | null">
  External identifier from your own system, if assigned.
</ResponseField>

<ResponseField name="status" type="number">
  Status code of the customer record.
</ResponseField>

<ResponseField name="createdAt" type="string">
  ISO 8601 creation timestamp. Omitted when not available.
</ResponseField>

<ResponseField name="createdBy" type="string">
  Identifier of the actor that created the customer record. Omitted when not available.
</ResponseField>

<ResponseField name="updatedAt" type="string">
  ISO 8601 timestamp of the most recent update. Omitted when not available.
</ResponseField>

<RequestExample>
  ```bash Request theme={null}
  curl --request GET \
    --url "$BASE_URL/v1/customers/find?q=803606" \
    --header 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...'
  ```
</RequestExample>

<ResponseExample>
  ```json 200 OK theme={null}
  {
    "id": "3d8ec956-de2a-4d43-9c1e-74475b153362",
    "data": {
      "fullname": "Jane Doe",
      "phone": "+905551234567",
      "email": "jane@example.com"
    },
    "collectables": {
      "point_MMSR5": { "label": "Points", "value": 1000, "total": 2760 }
    },
    "consents": { "marketing": true },
    "barcode": "803606",
    "cards": [
      {
        "id": "41dd8263-288e-4b55-bf2e-6a82995a0441",
        "name": "Point Card",
        "barcode": "803606",
        "status": 1,
        "options": {
          "spend": {
            "pointstoconvert": 1,
            "convertto": 1,
            "collectwhilespending": false,
            "collectfromdiscountedamount": false,
            "ratio": 1
          }
        }
      }
    ],
    "opaqueId": null,
    "status": 1,
    "createdAt": "2026-04-21T12:19:19.037Z",
    "coupons": [
      {
        "id": "906550fd-dcf5-4aed-a80e-03e8939fc2b4",
        "coupon": { "name": "Free Coffee Coupon" },
        "code": "431825",
        "type": "product",
        "discountAmount": 100,
        "isPercent": true,
        "products": {
          "quantity": 1,
          "productIds": ["4221450", "4221453", "4221456"]
        },
        "issuedAt": "2026-04-21T12:19:19.037Z",
        "expiresAt": "2026-09-09T12:14:08.511Z",
        "status": "active"
      },
      {
        "id": "eb2373b1-8a01-41b7-a8f9-48d462ede4e0",
        "coupon": { "name": "10% Discount Coupon" },
        "code": "667500",
        "type": "discount",
        "discountAmount": 10,
        "isPercent": true,
        "maxDiscountAmount": 25,
        "issuedAt": "2026-04-27T12:14:20.513Z",
        "status": "active"
      }
    ]
  }
  ```

  ```json 400 Bad Request theme={null}
  {
    "statuscode": 400,
    "errorcode": 400,
    "message": "_customer_not_found",
    "description": "",
    "timestamp": 1754040000000,
    "path": "/v1/customers/find?q=803606",
    "method": "GET"
  }
  ```
</ResponseExample>

<Tip>
  Save the returned `id` (customer id) and the `cards[].id` (customerpass id). You will need both on the coupon and transaction endpoints.
</Tip>
