# SearchLoyaltyRewards returns abnormal response for a single merchant

**URL:** <https://developer.squareup.com/forums/t/searchloyaltyrewards-returns-abnormal-response-for-a-single-merchant/27356>\
**Category:** Questions\
**Tags:** loyalty-api\
**Created:** [August 27, 2026, 2:36am UTC](https://developer.squareup.com/forums/t/searchloyaltyrewards-returns-abnormal-response-for-a-single-merchant/27356 "2026-08-27T02:36:52Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![katsuda](https://avatars.discourse-cdn.com/v4/letter/k/f4b2a3/32.png) [@katsuda](https://developer.squareup.com/forums/u/katsuda)\
**Post date:** [August 27, 2026, 2:36am UTC](https://developer.squareup.com/forums/t/searchloyaltyrewards-returns-abnormal-response-for-a-single-merchant/27356/1 "2026-08-27T02:36:52Z")

</div>

## Summary

When a customer redeems a loyalty reward at the POS, we needed to detect how much points the customer has used.

We have been able to do so via the following steps.

1. Receive an `order.created` webhook.
2. Resolve the Square customer from the order.
3. Look up the customer’s loyalty account.
4. Call `SearchLoyaltyRewards` with `status = REDEEMED` for that loyalty account.
5. Derive the redeemed points from the returned reward(s).

However, for **a single merchant** , response data for `SearchLoyaltyRewards` does not look right(differs from other merchants), and we cannot derive how much points were redeemed.

## Usual response for `SearchLoyaltyRewards`

A normal redemption produces two loyalty events, both carrying a `reward_id`, and `SearchLoyaltyRewards` returns the reward:

```json
{
  "events": [
    {
      "type": "REDEEM_REWARD",
      "redeem_reward": {
        "loyalty_program_id": "PROGRAM_ID",
        "reward_id": "REWARD_ID",
        "order_id": "ORDER_ID"
      }
    },
    {
      "type": "CREATE_REWARD",
      "create_reward": {
        "loyalty_program_id": "PROGRAM_ID",
        "reward_id": "REWARD_ID",
        "points": -100,
        "order_id": "ORDER_ID"
      }
    }
  ]
}

```

## Abnormal response for `SearchLoyaltyRewards`

For one merchant, a redemption clearly happened — the loyalty account balance dropped by 100 points (139 → 39) within ~3 seconds of the POS checkout, and the order shows a matching discount. The store staff redeemed the reward using the standard Square POS “redeem a reward” flow (selecting a reward from the loyalty program); we have confirmed this via a recording of the POS operation. However:

- `SearchLoyaltyRewards(loyalty_account_id, status = REDEEMED)` returns an empty result (`{}`), both immediately after checkout and ~6 hours later.
- The loyalty events for that order contain a `REDEEM_REWARD` event **without** a `reward_id`, and there is **no** corresponding `CREATE_REWARD` event at all:

```json
{
  "events": [
    {
      "type": "REDEEM_REWARD",
      "redeem_reward": {
        "loyalty_program_id": "PROGRAM_ID",
        "order_id": "ORDER_ID"
      }
    },
    {
      "type": "ACCUMULATE_POINTS",
      "accumulate_points": {
        "loyalty_program_id": "PROGRAM_ID",
        "points": 12,
        "order_id": "ORDER_ID"
      }
    }
  ]
}

```

Because no reward is returned by `SearchLoyaltyRewards` and the `REDEEM_REWARD` event has no `reward_id`, we have no reliable way to attribute the redeemed points to the order.

## Questions

1. The customer used the standard “redeem a reward” flow at the POS, and a redemption clearly occurred (the balance dropped by the redeemed points). What could be the reason the API returns this abnormal response?
2. When a `REDEEM_REWARD` event has no `reward_id`, how can we determine how many points were redeemed for that specific order via the API?
3. Is there a better way to derive used points for a order?

## Environment

- Region: Japan
- API: Loyalty API (Square Connect v2)
- The seller has an active Square Loyalty subscription.
- We can share the specific `loyalty_account_id` / `order_id` privately if needed.

---

<div class="post-metadata">

**Author:** ![ashley-square](https://avatars.discourse-cdn.com/v4/letter/a/5f9b8f/32.png) [@ashley-square](https://developer.squareup.com/forums/u/ashley-square)\
**Post date:** [August 28, 2026, 5:30pm UTC](https://developer.squareup.com/forums/t/searchloyaltyrewards-returns-abnormal-response-for-a-single-merchant/27356/3 "2026-08-28T17:30:34Z")

</div>

Thanks for the detailed writeup. This may come down to which flow performed the redemption.

First, check the `source` field on that `REDEEM_REWARD` event. Per [`LoyaltyEventRedeemReward`](https://developer.squareup.com/reference/square/objects/LoyaltyEventRedeemReward), `reward_id` “is returned only if the event source is `LOYALTY_API`.” A redemption done natively in Square POS has `source: SQUARE` and no `reward_id`, whereas one made through `CreateLoyaltyReward`/`RedeemLoyaltyReward` does carry it. If that’s the difference between this merchant and your others, it’s about which flow was used rather than a merchant-level fault. Could you share the `source` value from a working and a non-working case?

This is also related to your earlier thread, [Search Loyalty Rewards API returns an empty response](https://developer.squareup.com/forums/t/search-loyalty-rewards-api-returns-an-empty-response/21718), where the team confirmed rewards originating outside the Loyalty API aren’t returned by `SearchLoyaltyRewards` and recommended `SearchLoyaltyEvents`. I don’t have a timeline to share on that, so I’d build against `SearchLoyaltyEvents`.

Second, the missing `CREATE_REWARD` might be a filter artifact. `REDEEM_REWARD` has no `points` field; the debit sits on `CREATE_REWARD`, which has no `order_id` field — so an `order_filter` query can’t return it. The two events you posted are exactly the types that do carry `order_id`. Worth re-querying `SearchLoyaltyEvents` by `loyalty_account_filter` plus a `date_time_filter` around checkout. Also watch for `DELETE_REWARD`, since POS lets staff add and remove rewards before tender. In the examples I’ve seen, `create_reward.points` is negative and `delete_reward.points` positive, so confirm the signs in your own data before summing.

If you were already querying by account and time window and there’s still no `CREATE_REWARD`, that would be a genuine gap — send the `loyalty_account_id` and `order_id` and I will dig in further.

On deriving used points: check `Order.rewards[]` on the order each entry has a `reward_tier_id` that maps to `reward_tiers[].points` from `RetrieveLoyaltyProgram`. Failing that, loyalty events can be correlated on `loyalty_account_id`, `created_at` and `location_id`, though there’s no true join key, so multiple redemptions in a short window may be ambiguous.

---

<div class="post-metadata">

**Author:** ![katsuda](https://avatars.discourse-cdn.com/v4/letter/k/f4b2a3/32.png) [@katsuda](https://developer.squareup.com/forums/u/katsuda)\
**Post date:** [September 2, 2026, 8:04am UTC](https://developer.squareup.com/forums/t/searchloyaltyrewards-returns-abnormal-response-for-a-single-merchant/27356/4 "2026-09-02T08:04:23Z")

</div>

Thanks @ashley-square for looking into this matter. Answering your question first: the `source` value is the same: `SQUARE` in both cases, so it seems the source is not what separates them.

**You were right about the** `CREATE_REWARD` **being a filter artifact.** I tried querying `SearchLoyaltyEvents` by `loyalty_account_filter`, and found a `CREATE_REWARD` event, which includes the used points but does not include an `order_id`.

```json
{"type": "CREATE_REWARD", "created_at": "2026-08-03T09:23:37Z",
 "create_reward": {"loyalty_program_id": "PROGRAM", "points": -100},
 "loyalty_account_id": "ACCOUNT", "location_id": "LOCATION", "source": "SQUARE"}

```

On deriving used points:

> check `Order.rewards[]` on the order each entry has a `reward_tier_id` that maps to `reward_tiers[].points` from `RetrieveLoyaltyProgram`.

I checked `RetrieveOrder` for the `Order.rewards[]` on the latest API version but the response did not include `rewards` field. However, for the other merchants, `rewards` field existed and I was able to find the corresponding tier in `RetrieveLoyaltyProgram`.

* * *

So, my question would be:

Given that both are `source: SQUARE`, what else can produce the current difference (including the existence of `Order.rewards[]` field) between the merchants?

* * *

BTW, in the “abnormal” case,`CREATE_REWARD` is created 36 seconds before the `REDEEM_REWARD` (09:23:37 vs 09:24:13), which per our logs is also before the order itself was created (09:24:09). In the working case, both `CREATE_REWARD`and `REDEEM_REWARD` are created around the same time.

---

<div class="post-metadata">

**Author:** ![katsuda](https://avatars.discourse-cdn.com/v4/letter/k/f4b2a3/32.png) [@katsuda](https://developer.squareup.com/forums/u/katsuda)\
**Post date:** [September 25, 2026, 3:52am UTC](https://developer.squareup.com/forums/t/searchloyaltyrewards-returns-abnormal-response-for-a-single-merchant/27356/5 "2026-09-25T03:52:34Z")

</div>

@ashley-square Just bumping this. Any thoughts on why `Order.rewards[]` is missing for this merchant?
