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

# GET /v1/loyalty/programs/{id}

> Get one loyalty program with the rules that govern accrual, expiry, and tiers.

Returns a single program. Read it when you need the rules behind a balance — how many points a purchase is worth, how many stamps the reward takes, or where the tier thresholds sit.

## Endpoint

```
GET https://api.keebai.com/v1/loyalty/programs/{id}
```

## Required scope

`loyalty:read`

## Headers

| Header          | Required | Value                    |
| --------------- | -------- | ------------------------ |
| `Authorization` | Yes      | `Bearer kbai_pk_<token>` |

## Path parameters

| Parameter | Type     | Description             |
| --------- | -------- | ----------------------- |
| `id`      | `string` | The program `ObjectId`. |

## Example request

<CodeGroup>
  ```bash curl theme={null}
  curl https://api.keebai.com/v1/loyalty/programs/6650a1b2c3d4e5f6a7b8c9d0 \
    -H "Authorization: Bearer kbai_pk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
  ```

  ```js JavaScript theme={null}
  const response = await fetch(
    "https://api.keebai.com/v1/loyalty/programs/6650a1b2c3d4e5f6a7b8c9d0",
    { headers: { Authorization: `Bearer ${process.env.KEEBAI_API_TOKEN}` } },
  );
  const { program } = await response.json();
  ```

  ```python Python theme={null}
  import os, requests

  resp = requests.get(
      "https://api.keebai.com/v1/loyalty/programs/6650a1b2c3d4e5f6a7b8c9d0",
      headers={"Authorization": f"Bearer {os.environ['KEEBAI_API_TOKEN']}"},
      timeout=10,
  )
  resp.raise_for_status()
  program = resp.json()["program"]
  ```
</CodeGroup>

## Response

### 200 OK

A tiers program, showing the level thresholds:

```json theme={null}
{
  "program": {
    "_id": "6650a1b2c3d4e5f6a7b8c9d0",
    "name": "Rewards Club",
    "type": "tiers",
    "status": "active",
    "description": "Levels by accumulated points",
    "rules": {
      "tiers": {
        "levels": [
          { "key": "bronze", "name": "Bronze", "threshold": 0, "benefits": [] },
          { "key": "silver", "name": "Silver", "threshold": 2000, "benefits": ["Free shipping"] },
          { "key": "gold", "name": "Gold", "threshold": 5000, "benefits": ["Free shipping", "Early access"] }
        ]
      }
    },
    "created_at": "2026-01-05T12:00:00.000Z",
    "updated_at": "2026-02-01T09:30:00.000Z"
  }
}
```

### 401 Unauthorized

Missing, invalid, revoked, or expired token.

### 403 Forbidden

The token does not have the `loyalty:read` scope.

### 404 Not Found

No program with that id in your company.

### 502 Bad Gateway

The loyalty service is unreachable.

## Operational notes

* **Tier thresholds are read against `balance_points`.** A membership's `tier` is recomputed on every movement by finding the highest level whose `threshold` the point balance reaches.
* **A tiers program with no levels never assigns a tier.** `tier` stays an empty string.
* **`rules.points.expiration_days` of `0` means no expiry.** Any positive value makes the balance read as zero once that many days have passed since the member enrolled — see the [overview](/dev/loyalty/overview#balances-are-a-projection) for why that reading can disagree with the ledger.


## OpenAPI

````yaml GET /v1/loyalty/programs/{id}
openapi: 3.0.0
info:
  title: Keebai Public API
  description: Superficie pública REST autenticada con Personal Access Tokens (PAT).
  version: 1.0.0
  contact: {}
servers:
  - url: https://api.keebai.com
    description: Production
security: []
tags: []
paths:
  /v1/loyalty/programs/{id}:
    get:
      tags:
        - loyalty
      summary: Obtener un programa de fidelidad
      operationId: PublicLoyaltyController_getProgram
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicProgramEnvelopeDto'
      security:
        - PAT: []
components:
  schemas:
    PublicProgramEnvelopeDto:
      type: object
      properties:
        program:
          $ref: '#/components/schemas/PublicProgramDto'
      required:
        - program
    PublicProgramDto:
      type: object
      properties:
        _id:
          type: string
        name:
          type: string
          example: Club Cafetería
        type:
          type: string
          enum:
            - points
            - stamps
            - tiers
        status:
          type: string
          enum:
            - draft
            - active
            - archived
        description:
          type: string
          example: Programa de sellos de la cafetería
        rules:
          description: Solo viene poblada la variante que corresponde al type
          allOf:
            - $ref: '#/components/schemas/PublicProgramRulesDto'
        created_at:
          type: string
        updated_at:
          type: string
      required:
        - _id
        - name
        - type
        - status
        - description
        - rules
        - created_at
        - updated_at
    PublicProgramRulesDto:
      type: object
      properties:
        points:
          $ref: '#/components/schemas/PublicPointsRulesDto'
        stamps:
          $ref: '#/components/schemas/PublicStampsRulesDto'
        tiers:
          $ref: '#/components/schemas/PublicTiersRulesDto'
    PublicPointsRulesDto:
      type: object
      properties:
        points_per_currency_unit:
          type: number
          description: Cuántos puntos otorga cada unidad de moneda gastada
          example: 1
        expiration_days:
          type: number
          description: >-
            Días desde la inscripción tras los cuales el saldo se lee 0. Cero
            significa sin vencimiento
          example: 0
      required:
        - points_per_currency_unit
        - expiration_days
    PublicStampsRulesDto:
      type: object
      properties:
        target:
          type: number
          description: Sellos necesarios para el premio
          example: 10
        reward:
          type: string
          description: Descripción libre del premio. No es una entidad, es texto
          example: Un café gratis
        reset_on_redeem:
          type: boolean
          description: Si los sellos vuelven a cero al canjear
      required:
        - target
        - reward
        - reset_on_redeem
    PublicTiersRulesDto:
      type: object
      properties:
        levels:
          type: array
          items:
            $ref: '#/components/schemas/PublicTierLevelDto'
      required:
        - levels
    PublicTierLevelDto:
      type: object
      properties:
        key:
          type: string
          example: gold
        name:
          type: string
          example: Oro
        threshold:
          type: number
          description: Puntos mínimos para alcanzar el nivel
          example: 5000
        benefits:
          example:
            - Envío gratis
            - Acceso anticipado
          type: array
          items:
            type: string
      required:
        - key
        - name
        - threshold
        - benefits
  securitySchemes:
    PAT:
      scheme: bearer
      bearerFormat: kbai_pk_<hex>
      type: http
      description: >-
        Personal Access Token con prefijo `kbai_pk_`. Generar desde el portal
        con permiso `developer.manage_tokens`.

````