---
title: "Create program member"
method: POST
path: "/v2/loyalties/programs/{programId}/members"
tags: ["Programs"]
---

# Create program member

`POST /v2/loyalties/programs/{programId}/members`

Enrolls a customer as a member of the loyalty program. The program must be in `ACTIVE` status (returns a `423` error otherwise) and the customer must exist in Voucherify. A customer can be a member of a given program only once - creating a second member for the same customer ID returns `409` error (`member_already_exists`).

Loyalty cards are created automatically for all card definitions assigned to the program and returned in the `cards` array. Card `code` generation is asynchronous: `code` may be `null` immediately after creation.

## Path parameters

- `programId` string, required

## Request body

- MemberCreateRequest
  - `customer_identification` object
    - `type` 'customer_id' | 'customer_source_id', required — Defines how the customer is identified for the member creation. If `customer_id` is provided, the customer is identified by their unique Voucherify customer ID. Then, pass the required `customer_id` string. If `customer_source_id` is provided, the customer is identified by their source ID (e.g. from an external system). Then, pass the required `customer_source_id` string.
    - `customer_id` string — Unique Voucherify customer ID of an existing customer to enroll as a member. Required when `type` is `customer_id`.
    - `customer_source_id` string — Source ID from an external system of an existing customer to enroll as a member. Required when `type` is `customer_source_id`.
  - `status` 'ACTIVE' | 'INACTIVE', nullable — Initial member status. Defaults to `ACTIVE` when omitted or `null`.
  - `metadata` object, nullable — Free-form metadata attached to the member. Validated against the metadata schema defined for the `vl_member` related object (when one is configured). Defaults to an empty object.

## Response `200`

The created member with its automatically created cards.

- MemberCreateResponse — A loyalty program member.
  - `id` string, required — Unique member ID.
  - `customer_id` string, required — Unique Voucherify ID of the customer enrolled as this member.
  - `program_id` string, required — Unique Voucherify ID of the loyalty program the member belongs to.
  - `status` 'ACTIVE' | 'INACTIVE' | 'DELETED', required — Current member status. `INACTIVE` member can't earn points or redeem rewards.
  - `metadata` object, required — Free-form metadata attached to the member (empty object when none).
  - `created_at` string, date-time, required — Timestamp when the member was created (ISO 8601).
  - `updated_at` string, date-time, nullable, required — Timestamp when the member was last updated (ISO 8601), or `null` if never updated.
  - `object` 'member', required — Object type marker, always `member`.
  - `cards` MemberCard[], required — Member's loyalty cards - one per card definition assigned to the program. Card codes are generated asynchronously, so `card.code` may be `null` right after member creation.
    - `member_role` 'OWNER' | 'MEMBER', required — Role of the member on this card. Currently, loyalty program members can have only the `OWNER` role.
    - `created_at` string, date-time, required — Timestamp when the card was assigned to the member (ISO 8601).
    - `card` CardSimple, required — A loyalty card in its simple representation, as embedded in member responses.
      - `id` string, required — Unique Voucherify ID of the card.
      - `card_definition_id` string, required — Unique Voucherify ID of the card definition the card was created from.
      - `card_type` 'INDIVIDUAL', required — Card type. Currently only `INDIVIDUAL` is supported.
      - `code` string, nullable, required — Human-readable card code. Card code generation is asynchronous - this field is `null` right after member creation and is populated shortly after, once the background code generation completes.
      - `lifetime_bucket` CardLifetimeBucket, required — Lifetime points counters of a card.
        - `points` CardLifetimeBucketPoints, required — Lifetime counters of regular points. All counters default to 0. The available balance is calculated as: `total` - `subtracted` - `expired` - `spent` - `refunded` + `returned` - `locked` + `unlocked` - `purchased_reversed`.
          - `total` number, required — Total accumulated points, including points added manually, earned by fulfilling earning rules and activated from pending points (excluding returned points).
          - `earned` number, required — Total points earned by fulfilling earning rules (does not include activated pending points or points added manually).
          - `added` number, required — Total manually added points.
          - `purchased` number, required — Total points purchased via a `LOYALTY_CARD_POINTS` reward (credited to the target card).
          - `purchased_reversed` number, required — Total purchased points reversed via reward refund.
          - `subtracted` number, required — Total manually subtracted points.
          - `expired` number, required — Total expired points.
          - `spent` number, required — Total points spent on rewards.
          - `refunded` number, required — Total refunded points (points that were earned by products which were later returned).
          - `returned` number, required — Total returned points (by returning a purchased reward).
          - `locked` number, required — Total locked points (by locking a purchased reward).
          - `unlocked` number, required — Total unlocked points (by unlocking a purchased reward).
        - `pending_points` CardLifetimeBucketPendingPoints, required — Lifetime counters of pending points. The available pending balance is max(`total` - `activated` - `canceled`, 0).
          - `total` number, required — Total pending points ever added.
          - `activated` number, required — Total pending points activated into regular points.
          - `canceled` number, required — Total pending points canceled.
      - `balance` CardBalance, required — Current available balance of a card.
        - `points` number, required — Currently available regular points.
        - `pending_points` number, required — Currently pending (not yet activated) points.
      - `next_expiration` CardNextExpiration, required — The nearest upcoming points expiration on a card.
        - `points` number, required — Number of points that will expire.
        - `date` string, date, required — Date when the points expire (`YYYY-MM-DD`).
      - `next_activation` CardNextActivation, required — The nearest upcoming pending points activation on a card. For the `EVENT_BASED` type, `date` is omitted and `cancel_date` is returned instead; for other types `date` is returned and `cancel_date` is omitted.
        - `points` number, required — Number of pending points to be activated.
        - `type` 'IMMEDIATE' | 'PERIOD_BASED' | 'FIXED_DATES' | 'EVENT_BASED', required — Pending points activation type from the card definition.
        - `date` string, date — Activation date (`YYYY-MM-DD`). Present for all types except `EVENT_BASED`.
        - `cancel_date` string, date — Date when the pending points are canceled if the activating event does not occur (`YYYY-MM-DD`). Present only for the `EVENT_BASED` type.
      - `object` 'card', required — Object type marker, always `card`.
    - `object` 'member_card', required — Object type marker, always `member_card`.

## Other responses

- `400` — Validation error - request body or path parameters failed validation, or the operation is not allowed in the current resource state.
- `404` — Resource not found.
- `409` — Conflict - the customer with a given ID has already been added to the loyalty program.
- `423` — Program is not in ACTIVE status.
- `500` — Internal server error.

---

[API](https://skmtc.net/voucherifyio/apis/voucherify-loyalty-v2-api.md) · [All operations](https://skmtc.net/voucherifyio/apis/voucherify-loyalty-v2-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/voucherifyio/voucherify-loyalty-v2-api/revisions/69be73b5cff0/schema)
