> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://developers.upwardli.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://developers.upwardli.com/_mcp/server.

# Cashback Rewards

> Enroll a payment card in cashback rewards and view the offers a cardholder is eligible for.

## Overview

Cashback Rewards let a cardholder earn money back on eligible purchases made with
their Upwardli-issued card. Rewards are powered by a rewards **configuration** that
your partner program makes available; once a card is **enrolled** in a configuration,
the cardholder can browse the **offers** they're eligible for and cashback is posted
to their account automatically.

This guide walks through the full lifecycle:

1. Find the cardholder's payment card.
2. Check whether the card is already enrolled.
3. List the rewards configurations the card is eligible for.
4. Enroll the card in an active configuration.
5. View the offers available to the enrolled card.

**Who this is for:** partners integrating directly against the API, and the embedded
web component that surfaces this same flow to a consumer.

Token scope required: `api:rewards:read` for the read endpoints, `api:rewards:write`
to enroll. The broader `api:read` / `api:write` scopes also grant access.

---

## Prerequisites

* Valid OAuth 2.0 Bearer token ([see Authentication](/concepts/authentication/introduction))
* The consumer has at least one active payment card on your partner network
* Cashback Rewards are enabled for your partner configuration

---

## How It Works

```
Partner App / Component              Upwardli API
        │                                 │
        │  GET .../payment-cards/         │   Resolve the active card
        │────────────────────────────────>│
        │                                 │
        │  GET .../rewards/enrollments/   │   Already enrolled?
        │────────────────────────────────>│
        │        ┌── active enrollment ───┤── yes ─> go straight to offers
        │        │                        │
        │  GET .../rewards/               │   no -> list eligible configs
        │────────────────────────────────>│
        │                                 │
        │  POST .../rewards/{cfg}/enrollments/   Enroll the card
        │────────────────────────────────>│
        │                                 │
        │  GET .../rewards/{program}/offers/     Browse offers
        │────────────────────────────────>│
        │                                 │
```

### Base URLs

```
Production: https://api.upwardli.com
Sandbox:    https://api-sandbox.upwardli.com
```

---

## 1. Find the payment card

Rewards endpoints are keyed by a **payment card external ID**. List the consumer's
cards and select an active one (skip cards whose `status` is `canceled`, `closed`,
or `deactivated`).

### Endpoint

```
GET /v2/consumers/{consumer_id}/payment-cards/
```

### Example request

```bash
curl "https://api.upwardli.com/v2/consumers/{consumer_id}/payment-cards/" \
  -H "Authorization: Bearer <token>"
```

The `id` of the chosen card is the `{payment_card_id}` used in every step below.

### Full API reference

[List Consumer Payment Cards →](/api-access/api-reference/consumers/payment-cards/list-consumer-payment-cards)

---

## 2. Check the current enrollment

Before showing an activation prompt, check whether the card is already enrolled.
An enrollment with `is_active: true` means the cardholder is already earning rewards —
skip to [step 5](#5-view-available-offers) and use its `program_id` to fetch offers.

### Endpoint

```
GET /v2/payment-cards/{payment_card_id}/rewards/enrollments/
```

### Example request

```bash
curl "https://api.upwardli.com/v2/payment-cards/{payment_card_id}/rewards/enrollments/" \
  -H "Authorization: Bearer <token>"
```

### Response — 200 OK

```json
{
  "count": 1,
  "next": null,
  "previous": null,
  "results": [
    {
      "id": "a1b2c3d4-0000-4000-8000-000000000001",
      "program_id": "9f8e7d6c-0000-4000-8000-0000000000aa",
      "configuration_name": "Upwardli Cashback",
      "is_active": true,
      "created_at": "2026-06-25T14:30:00Z"
    }
  ]
}
```

> **Note**
>
> If no result has `is_active: true`, the card is not enrolled yet — continue to step 3.

### Full API reference

[List Rewards Enrollments →](/api-access/api-reference/payment-cards/get-payment-card-rewards-enrollments-v-2)

---

## 3. List eligible rewards configurations

When the card has no active enrollment, list the configurations available to it. A
configuration with `is_active: true` can be enrolled in; its `id` is the
`{rewards_configuration_id}` you pass in step 4. `is_enrolled` tells you whether the
card is already enrolled in that specific configuration.

### Endpoint

```
GET /v2/payment-cards/{payment_card_id}/rewards/
```

### Example request

```bash
curl "https://api.upwardli.com/v2/payment-cards/{payment_card_id}/rewards/" \
  -H "Authorization: Bearer <token>"
```

### Response — 200 OK

```json
{
  "count": 1,
  "next": null,
  "previous": null,
  "results": [
    {
      "id": "5c4b3a29-0000-4000-8000-0000000000bb",
      "configuration_name": "Upwardli Cashback",
      "is_active": true,
      "provider": "kard",
      "created_at": "2026-06-01T00:00:00Z",
      "is_enrolled": false
    }
  ]
}
```

> **Note**
>
> No active configuration means rewards aren't available for this card yet — surface a
> "coming soon" state rather than an activation prompt.

### Full API reference

[List Rewards Configurations →](/api-access/api-reference/payment-cards/list-payment-card-rewards-configurations-v-2)

---

## 4. Enroll the card

Enroll the card in an active configuration. No request body is required — the card and
configuration are identified entirely by the path. The response is the new enrollment,
which carries the `program_id` you'll need to fetch offers.

### Endpoint

```
POST /v2/payment-cards/{payment_card_id}/rewards/{rewards_configuration_id}/enrollments/
```

### Example request

```bash
curl -X POST \
  "https://api.upwardli.com/v2/payment-cards/{payment_card_id}/rewards/{rewards_configuration_id}/enrollments/" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json"
```

### Response — 201 Created

```json
{
  "id": "a1b2c3d4-0000-4000-8000-000000000001",
  "program_id": "9f8e7d6c-0000-4000-8000-0000000000aa",
  "configuration_name": "Upwardli Cashback",
  "is_active": true,
  "created_at": "2026-06-25T14:30:00Z"
}
```

### Full API reference

[Create Rewards Enrollment →](/api-access/api-reference/payment-cards/create-payment-card-rewards-enrollment-v-2)

---

## 5. View available offers

With an active enrollment, fetch the offers the cardholder is eligible for. Pass the
`program_id` from the enrollment as the `{program_id}` path parameter. To surface
nearby in-store offers, include the cardholder's `latitude` and `longitude` (and an
optional `radius`).

### Endpoint

```
GET /v2/payment-cards/{payment_card_id}/rewards/{program_id}/offers/
```

### Query parameters

| Parameter          | Type    | Description                                      |
| ------------------ | ------- | ------------------------------------------------ |
| `latitude`         | float   | Latitude used to surface nearby in-store offers  |
| `longitude`        | float   | Longitude used to surface nearby in-store offers |
| `radius`           | float   | Search radius, in miles, around the coordinates  |
| `search`           | string  | Filter offers by a search term                   |
| `limit` / `offset` | integer | Pagination controls                              |

### Example request

```bash
curl "https://api.upwardli.com/v2/payment-cards/{payment_card_id}/rewards/{program_id}/offers/?latitude=30.2672&longitude=-97.7431" \
  -H "Authorization: Bearer <token>"
```

### Response — 200 OK

```json
{
  "count": 1,
  "next": null,
  "previous": null,
  "results": [
    {
      "type": "offer",
      "id": "off_8a72b1",
      "relationships": {
        "category": { "data": [{ "id": "cat_grocery", "type": "GROCERY" }] }
      },
      "attributes": {
        "name": "Whole Foods Market",
        "description": "Earn cash back on groceries",
        "terms": "Excludes gift cards and alcohol where prohibited.",
        "purchaseChannel": ["INSTORE"],
        "userReward": { "type": "PERCENT", "value": 5 },
        "assets": [
          { "type": "IMG_VIEW", "url": "https://cdn.example.com/wf.png", "alt": "Whole Foods" }
        ],
        "expirationDate": "2026-09-30",
        "websiteUrl": "https://www.wholefoodsmarket.com"
      },
      "address": {
        "street": "525 N Lamar Blvd",
        "city": "Austin",
        "state": "TX",
        "zipCode": "78703"
      },
      "coordinates": {
        "latitude": 30.2672,
        "longitude": -97.7431
      }
    }
  ]
}
```

### Reward types

The `attributes.userReward` object describes how much the cardholder earns:

| `type`    | Meaning                      | Example display   |
| --------- | ---------------------------- | ----------------- |
| `FLAT`    | A fixed dollar amount back   | `$5.00 cash back` |
| `PERCENT` | A percentage of the purchase | `5% cash back`    |

`purchaseChannel` is `["INSTORE"]` for in-store offers (which include an `address`
and `coordinates`) or `["ONLINE"]` for online offers (use `websiteUrl`).

For in-store offers, `coordinates` carries the location's `latitude` and `longitude`,
letting you plot the merchant on a map or sort offers by distance from the cardholder.
Both fields may be `null`, and `coordinates` itself is `null` for online offers.

### Full API reference

[List Rewards Offers →](/api-access/api-reference/payment-cards/get-payment-card-rewards-offers-v-2)

---

## Error Reference

| HTTP status | Cause                                                                                                                        |
| ----------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `401`       | Missing or invalid Bearer token                                                                                              |
| `403`       | Token scope does not include `api:rewards:read` (reads) or `api:rewards:write` (enroll) — `api:read` / `api:write` also work |
| `404`       | Payment card, configuration, or program not found, or not on your partner network                                            |
| `500`       | Unexpected server error — open a support ticket                                                                              |