{ "openapi": "3.1.0", "info": { "title": "Voucherify Loyalty v2 API", "version": "2.0.0", "description": "Complete API documentation for Voucherify Loyalty v2 system. Requires LOYALTY_V2 feature flag." }, "servers": [ { "url": "https://api.voucherify.io", "description": "Production" } ], "security": [ { "bearerAuth": [], "X-App-Id": [], "X-App-Token": [] } ], "tags": [ { "name": "Card Definitions", "description": "CRUD operations, lifecycle management, and activity history for card definitions. Card definitions describe the configuration for loyalty cards, including code generation, points expiration, earning/spending limits, pending points, refunds, and balance settings." }, { "name": "Programs", "description": "Loyalty program CRUD, lifecycle management, program-scoped resource assignments (card definitions, earning rules, rewards, tier structures), member management (create, list, get, activate, deactivate, delete), card operations (points adjustment, pending points, expiring points, transactions), reward purchases, and activity history." }, { "name": "Earning Rules", "description": "Manage earning rules that define how customers earn points or receive incentives based on triggers (events, segments, custom events). Includes CRUD, lifecycle, and activity history." }, { "name": "Tier Structures", "description": "CRUD operations, lifecycle management, and activity history for tier structures. Includes nested tier definitions (create, list, update, delete) within tier structures. Tier structures define the tiering model for loyalty programs — how members qualify for and move between tiers." }, { "name": "Incentives", "description": "Manage incentive definitions (fixed points, proportional points, material, digital). Includes CRUD, lifecycle transitions, and activity history." }, { "name": "Rewards", "description": "CRUD, lifecycle operations, and activity history for reward definitions. Rewards can be material (product/SKU) or digital (discount coupons, gift vouchers)." }, { "name": "Examine", "description": "Examines the earning of loyalty points for a loyalty program member." } ], "paths": { "/v2/loyalties/card-definitions": { "get": { "operationId": "listCardDefinitions", "summary": "List Card Definitions", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nReturns a paginated, cursor-based list of card definitions with optional filtering and ordering.\n", "tags": [ "Card Definitions" ], "parameters": [ { "name": "filters[junction]", "in": "query", "required": false, "schema": { "type": "string", "enum": [ "AND", "OR" ] }, "description": "Logical junction for combining filter conditions." }, { "name": "filters[id][conditions][$is]", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Filter by exact card definition ID." }, { "name": "filters[id][conditions][$is_not]", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Exclude card definitions with this ID." }, { "name": "filters[id][conditions][$in]", "in": "query", "required": false, "schema": { "type": "array", "items": { "type": "string" }, "maxItems": 100 }, "description": "Filter by multiple card definition IDs." }, { "name": "filters[id][conditions][$not_in]", "in": "query", "required": false, "schema": { "type": "array", "items": { "type": "string" }, "maxItems": 100 }, "description": "Exclude card definitions with these IDs." }, { "name": "filters[name][conditions][$is]", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Filter by exact name." }, { "name": "filters[name][conditions][$is_not]", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Exclude by exact name." }, { "name": "filters[name][conditions][$contains]", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Filter by name containing substring." }, { "name": "filters[name][conditions][$starts_with]", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Filter by name starting with." }, { "name": "filters[name][conditions][$ends_with]", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Filter by name ending with." }, { "name": "filters[type][conditions][$is]", "in": "query", "required": false, "schema": { "type": "string", "enum": [ "INDIVIDUAL" ] }, "description": "Filter by exact card type." }, { "name": "filters[type][conditions][$in]", "in": "query", "required": false, "schema": { "type": "array", "items": { "type": "string", "enum": [ "INDIVIDUAL" ] } }, "description": "Filter by multiple card types." }, { "name": "filters[status][conditions][$is]", "in": "query", "required": false, "schema": { "type": "string", "enum": [ "ACTIVE", "INACTIVE", "DRAFT" ] }, "description": "Filter by exact status." }, { "name": "filters[status][conditions][$in]", "in": "query", "required": false, "schema": { "type": "array", "items": { "type": "string", "enum": [ "ACTIVE", "INACTIVE", "DRAFT" ] } }, "description": "Filter by multiple statuses." }, { "name": "filters[created_at][conditions][$before]", "in": "query", "required": false, "schema": { "type": "string", "format": "date-time" }, "description": "Filter for records created before this date." }, { "name": "filters[created_at][conditions][$after]", "in": "query", "required": false, "schema": { "type": "string", "format": "date-time" }, "description": "Filter for records created after this date." }, { "name": "filters[updated_at][conditions][$before]", "in": "query", "required": false, "schema": { "type": "string", "format": "date-time" }, "description": "Filter for records updated before this date." }, { "name": "filters[updated_at][conditions][$after]", "in": "query", "required": false, "schema": { "type": "string", "format": "date-time" }, "description": "Filter for records updated after this date." }, { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 10 }, "description": "Maximum number of results to return (1-100)." }, { "name": "order", "in": "query", "required": false, "schema": { "type": "array", "items": { "type": "string", "enum": [ "-name", "name", "-type", "type", "-status", "status", "-created_at", "created_at" ] } }, "description": "Sort order. Prefix with `-` for descending. Default: `-created_at`." }, { "name": "cursor", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Cursor for pagination. Obtained from a previous list response." } ], "responses": { "200": { "description": "List of card definitions", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CardDefinitionListResponse" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "500": { "$ref": "#/components/responses/InternalServerError" } } }, "post": { "operationId": "createCardDefinition", "summary": "Create Card Definition", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nCreates a new card definition with the specified configuration.\n\nRequired fields: `name`, `type`. All other fields have sensible defaults.\nThe `code_config` is optional on input but required internally (defaults are generated).\n\n**Custom validators applied:**\n- `createCardDefinitionBalanceSettings`: `balance_settings.allow_negative` can only be `true` when `points_expiration.type` is `NO_EXPIRATION`.\n- `createCardDefinitionRefunds`: `refunds.earned_points.methods` with type `REVOKE_BELOW_ZERO` requires `balance_settings.allow_negative: true`. Method type `REVOKE_FROM_PENDING` requires `pending_points.type` to be one of `PERIOD_BASED`, `FIXED_DATES`, or `EVENT_BASED`.\n", "tags": [ "Card Definitions" ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CardDefinitionCreateRequest" } } } }, "responses": { "200": { "description": "Created card definition", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CardDefinitionResponse" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/card-definitions/{id}": { "get": { "operationId": "getCardDefinition", "summary": "Get Card Definition", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nRetrieves a single card definition by its ID.", "tags": [ "Card Definitions" ], "parameters": [ { "$ref": "#/components/parameters/CardDefinitionId" } ], "responses": { "200": { "description": "Card definition details", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CardDefinitionResponse" } } } }, "404": { "$ref": "#/components/responses/NotFound" }, "500": { "$ref": "#/components/responses/InternalServerError" } } }, "put": { "operationId": "updateCardDefinition", "summary": "Update Card Definition", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nUpdates an existing card definition. At least one property must be provided.\n\nWhen the card definition is **not** in `DRAFT` status, only `name` and `metadata` properties can be updated.\nIn `DRAFT` status, all available properties can be updated.\n", "tags": [ "Card Definitions" ], "parameters": [ { "$ref": "#/components/parameters/CardDefinitionId" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CardDefinitionUpdateRequest" } } } }, "responses": { "200": { "description": "Updated card definition", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CardDefinitionResponse" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "404": { "$ref": "#/components/responses/NotFound" }, "500": { "$ref": "#/components/responses/InternalServerError" } } }, "delete": { "operationId": "deleteCardDefinition", "summary": "Delete Card Definition", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nSoft-deletes a card definition. The card definition cannot be deleted if it is assigned to a program,\nconnected to earning rules, incentives, or tier structures.\n", "tags": [ "Card Definitions" ], "parameters": [ { "$ref": "#/components/parameters/CardDefinitionId" } ], "responses": { "200": { "description": "Deleted card definition", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CardDefinitionResponse" } } } }, "404": { "$ref": "#/components/responses/NotFound" }, "409": { "$ref": "#/components/responses/ResourceLocked" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/card-definitions/{id}/activate": { "post": { "operationId": "activateCardDefinition", "summary": "Activate Card Definition", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nTransitions the card definition to `ACTIVE` status.\n\nAllowed transitions: `DRAFT` -> `ACTIVE`, `INACTIVE` -> `ACTIVE`.\n", "tags": [ "Card Definitions" ], "parameters": [ { "$ref": "#/components/parameters/CardDefinitionId" } ], "responses": { "200": { "description": "Activated card definition", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CardDefinitionResponse" } } } }, "400": { "description": "Invalid state transition", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "$ref": "#/components/responses/NotFound" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/card-definitions/{id}/draft": { "post": { "operationId": "draftCardDefinition", "summary": "Move Card Definition to Draft", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nTransitions the card definition back to `DRAFT` status.\n\nAllowed transitions: `ACTIVE` -> `DRAFT`.\n\nCannot draft a card definition that is connected to a non-draft program, reward,\nearning rule, incentive, or tier structure.\n", "tags": [ "Card Definitions" ], "parameters": [ { "$ref": "#/components/parameters/CardDefinitionId" } ], "responses": { "200": { "description": "Drafted card definition", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CardDefinitionResponse" } } } }, "400": { "description": "Invalid state transition", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "$ref": "#/components/responses/NotFound" }, "409": { "$ref": "#/components/responses/ResourceLocked" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/card-definitions/{id}/activities": { "get": { "operationId": "listCardDefinitionActivities", "summary": "List Card Definition Activities", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nReturns a paginated list of activities (audit log) for a specific card definition.\n", "tags": [ "Card Definitions" ], "parameters": [ { "$ref": "#/components/parameters/CardDefinitionId" }, { "name": "filters[junction]", "in": "query", "required": false, "schema": { "type": "string", "enum": [ "AND", "OR" ] } }, { "name": "filters[id][conditions][$is]", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Filter by exact activity ID." }, { "name": "filters[type][conditions][$is]", "in": "query", "required": false, "schema": { "type": "string", "enum": [ "vl.card_definition.created", "vl.card_definition.updated", "vl.card_definition.deleted", "vl.card_definition.activated", "vl.card_definition.deactivated", "vl.card_definition.drafted", "vl.card_definition.assigned", "vl.card_definition.unassigned" ] }, "description": "Filter by exact activity type." }, { "name": "filters[type][conditions][$in]", "in": "query", "required": false, "schema": { "type": "array", "items": { "type": "string", "enum": [ "vl.card_definition.created", "vl.card_definition.updated", "vl.card_definition.deleted", "vl.card_definition.activated", "vl.card_definition.deactivated", "vl.card_definition.drafted", "vl.card_definition.assigned", "vl.card_definition.unassigned" ] } }, "description": "Filter by multiple activity types." }, { "name": "filters[created_at][conditions][$before]", "in": "query", "required": false, "schema": { "type": "string", "format": "date-time" } }, { "name": "filters[created_at][conditions][$after]", "in": "query", "required": false, "schema": { "type": "string", "format": "date-time" } }, { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 10 } }, { "name": "order", "in": "query", "required": false, "schema": { "type": "array", "items": { "type": "string", "enum": [ "created_at", "-created_at" ] } }, "description": "Sort order. Default: `-created_at`." }, { "name": "cursor", "in": "query", "required": false, "schema": { "type": "string" } } ], "responses": { "200": { "description": "List of card definition activities", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CardDefinitionActivityListResponse" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "404": { "$ref": "#/components/responses/NotFound" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/programs": { "post": { "operationId": "createProgram", "summary": "Create a loyalty program", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nCreates a new loyalty program. Optionally attaches card definitions,\nearning rules, rewards, and tier structures in the same request.\nThe response uses `toCreateDTO(params)` which includes the attached\nresource ids alongside the program fields.\n", "tags": [ "Programs" ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProgramCreateRequest" } } } }, "responses": { "200": { "description": "Program created successfully", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProgramCreateResponse" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "500": { "$ref": "#/components/responses/InternalServerError" } } }, "get": { "operationId": "listPrograms", "summary": "List loyalty programs", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nReturns a cursor-paginated list of loyalty programs. Supports filtering\nby id, name, status, and created_at with various conditions.\n", "tags": [ "Programs" ], "parameters": [ { "$ref": "#/components/parameters/ProgramsFilterId" }, { "$ref": "#/components/parameters/ProgramsFilterName" }, { "$ref": "#/components/parameters/ProgramsFilterStatus" }, { "$ref": "#/components/parameters/ProgramsFilterCreatedAt" }, { "$ref": "#/components/parameters/ProgramsFilterJunction" }, { "$ref": "#/components/parameters/QueryLimit" }, { "$ref": "#/components/parameters/ProgramsOrder" }, { "$ref": "#/components/parameters/ProgramsCursor" } ], "responses": { "200": { "description": "Paginated list of programs", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProgramListResponse" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/programs/{id}": { "get": { "operationId": "getProgram", "summary": "Get a loyalty program", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nRetrieves a single loyalty program by id.", "tags": [ "Programs" ], "parameters": [ { "$ref": "#/components/parameters/ProgramId" } ], "responses": { "200": { "description": "Program details", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProgramResponse" } } } }, "404": { "$ref": "#/components/responses/NotFound" }, "500": { "$ref": "#/components/responses/InternalServerError" } } }, "put": { "operationId": "updateProgram", "summary": "Update a loyalty program", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nUpdates program properties. When the program is not in DRAFT status,\nonly `name` and `metadata` can be updated.\n", "tags": [ "Programs" ], "parameters": [ { "$ref": "#/components/parameters/ProgramId" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProgramUpdateRequest" } } } }, "responses": { "200": { "description": "Program updated successfully", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProgramResponse" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "404": { "$ref": "#/components/responses/NotFound" }, "500": { "$ref": "#/components/responses/InternalServerError" } } }, "delete": { "operationId": "deleteProgram", "summary": "Delete a loyalty program", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nSoft-deletes a loyalty program and all its assignments\n(card definitions, earning rules, rewards, tier structures).\n", "tags": [ "Programs" ], "parameters": [ { "$ref": "#/components/parameters/ProgramId" } ], "responses": { "200": { "description": "Program deleted successfully", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProgramResponse" } } } }, "404": { "$ref": "#/components/responses/NotFound" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/programs/{id}/activate": { "post": { "operationId": "activateProgram", "summary": "Activate a loyalty program", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nTransitions a program to ACTIVE status. Valid transitions:\nDRAFT -> ACTIVE (requires all assignments are ACTIVE),\nINACTIVE -> ACTIVE (requires no DRAFT assignments exist).\n", "tags": [ "Programs" ], "parameters": [ { "$ref": "#/components/parameters/ProgramId" } ], "responses": { "200": { "description": "Program activated", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProgramResponse" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "404": { "$ref": "#/components/responses/NotFound" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/programs/{id}/deactivate": { "post": { "operationId": "deactivateProgram", "summary": "Deactivate a loyalty program", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nTransitions a program to INACTIVE status.\nOnly ACTIVE programs can be deactivated.\n", "tags": [ "Programs" ], "parameters": [ { "$ref": "#/components/parameters/ProgramId" } ], "responses": { "200": { "description": "Program deactivated", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProgramResponse" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "404": { "$ref": "#/components/responses/NotFound" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/programs/{id}/activities": { "get": { "operationId": "listProgramActivities", "summary": "List program activities", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nReturns a cursor-paginated list of activities for a specific program.\nSupports filtering by activity id, type, and created_at.\n", "tags": [ "Programs", "Programs" ], "parameters": [ { "$ref": "#/components/parameters/ProgramId" }, { "$ref": "#/components/parameters/ProgramActivitiesFilterId" }, { "$ref": "#/components/parameters/ProgramActivitiesFilterType" }, { "$ref": "#/components/parameters/ProgramActivitiesFilterCreatedAt" }, { "$ref": "#/components/parameters/ProgramActivitiesFilterJunction" }, { "$ref": "#/components/parameters/QueryLimit" }, { "$ref": "#/components/parameters/ProgramActivitiesOrder" }, { "$ref": "#/components/parameters/ProgramActivitiesCursor" } ], "responses": { "200": { "description": "Paginated list of program activities", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProgramActivityListResponse" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "404": { "$ref": "#/components/responses/NotFound" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/programs/{id}/card-definitions": { "get": { "operationId": "listProgramCardDefinitions", "summary": "List card definition assignments for a program", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nReturns a cursor-paginated list of card definition assignments\nfor the specified program.\n", "tags": [ "Programs", "Programs" ], "parameters": [ { "$ref": "#/components/parameters/ProgramId" }, { "$ref": "#/components/parameters/QueryLimit" }, { "$ref": "#/components/parameters/CardDefinitionAssignmentsOrder" }, { "$ref": "#/components/parameters/CardDefinitionAssignmentsCursor" } ], "responses": { "200": { "description": "Paginated list of card definition assignments", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CardDefinitionAssignmentListResponse" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/programs/{id}/card-definitions/batch": { "post": { "operationId": "batchProcessCardDefinitions", "summary": "Batch assign/unassign card definitions", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nAssigns and/or unassigns card definitions to/from a program in a single batch.\nProgram must be in DRAFT status.\n", "tags": [ "Programs", "Programs" ], "parameters": [ { "$ref": "#/components/parameters/ProgramId" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CardDefinitionsBatchRequest" } } } }, "responses": { "200": { "description": "Batch processing result", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CardDefinitionsBatchResponse" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "404": { "$ref": "#/components/responses/NotFound" }, "409": { "$ref": "#/components/responses/Conflict" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/programs/{id}/earning-rules": { "get": { "operationId": "listProgramEarningRules", "summary": "List earning rule assignments for a program", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nReturns a cursor-paginated list of earning rule assignments\nfor the specified program.\n", "tags": [ "Programs", "Programs" ], "parameters": [ { "$ref": "#/components/parameters/ProgramId" }, { "$ref": "#/components/parameters/QueryLimit" }, { "$ref": "#/components/parameters/EarningRuleAssignmentsOrder" }, { "$ref": "#/components/parameters/EarningRuleAssignmentsCursor" } ], "responses": { "200": { "description": "Paginated list of earning rule assignments", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/EarningRuleAssignmentListResponse" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/programs/{id}/earning-rules/batch": { "post": { "operationId": "batchProcessEarningRules", "summary": "Batch assign/unassign earning rules", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nAssigns and/or unassigns earning rules to/from a program in a single batch.\n", "tags": [ "Programs", "Programs" ], "parameters": [ { "$ref": "#/components/parameters/ProgramId" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/EarningRulesBatchRequest" } } } }, "responses": { "200": { "description": "Batch processing result", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/EarningRulesBatchResponse" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "404": { "$ref": "#/components/responses/NotFound" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/programs/{id}/tier-structures": { "get": { "operationId": "listProgramTierStructures", "summary": "List tier structure assignments for a program", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nReturns a cursor-paginated list of tier structure assignments\nfor the specified program.\n", "tags": [ "Programs", "Programs" ], "parameters": [ { "$ref": "#/components/parameters/ProgramId" }, { "$ref": "#/components/parameters/QueryLimit" }, { "$ref": "#/components/parameters/TierStructureAssignmentsOrder" }, { "$ref": "#/components/parameters/TierStructureAssignmentsCursor" } ], "responses": { "200": { "description": "Paginated list of tier structure assignments", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TierStructureAssignmentListResponse" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/programs/{id}/tier-structures/batch": { "post": { "operationId": "batchProcessTierStructures", "summary": "Batch assign/unassign tier structures", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nAssigns and/or unassigns tier structures to/from a program in a single batch.\nUnassign operations require the program to be in DRAFT status.\n", "tags": [ "Programs", "Programs" ], "parameters": [ { "$ref": "#/components/parameters/ProgramId" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TierStructuresBatchRequest" } } } }, "responses": { "200": { "description": "Batch processing result", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TierStructuresBatchResponse" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "404": { "$ref": "#/components/responses/NotFound" }, "409": { "$ref": "#/components/responses/Conflict" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/programs/{programId}/rewards": { "get": { "operationId": "listProgramRewards", "summary": "List reward assignments for a program", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nReturns a cursor-paginated list of reward assignments\nfor the specified program.\n", "tags": [ "Programs", "Programs" ], "parameters": [ { "name": "programId", "in": "path", "required": true, "description": "Unique program identifier", "schema": { "type": "string", "pattern": "^lprg_[a-f0-9]+$" } }, { "$ref": "#/components/parameters/QueryLimit" }, { "$ref": "#/components/parameters/RewardAssignmentsOrder" }, { "$ref": "#/components/parameters/RewardAssignmentsCursor" } ], "responses": { "200": { "description": "Paginated list of reward assignments", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RewardAssignmentListResponse" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/programs/{programId}/rewards/batch": { "post": { "operationId": "batchProcessRewards", "summary": "Batch assign/unassign rewards", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nAssigns and/or unassigns rewards to/from a program in a single batch.\n", "tags": [ "Programs", "Programs" ], "parameters": [ { "name": "programId", "in": "path", "required": true, "description": "Unique program identifier", "schema": { "type": "string", "pattern": "^lprg_[a-f0-9]+$" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RewardsBatchRequest" } } } }, "responses": { "200": { "description": "Batch processing result", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RewardsBatchResponse" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "404": { "$ref": "#/components/responses/NotFound" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/programs/{programId}/members": { "post": { "operationId": "createMember", "summary": "Create member", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nCreates a new member in the specified program. The customer must exist and the program must be in ACTIVE status.\nCards are automatically created for the member based on the program's card definition assignments.\nReturns the member with their assigned cards.\n\n**Note:** Card code generation is asynchronous. Cards will appear in the response, but the `code` field may be `null` immediately after creation. The code is generated asynchronously and becomes available shortly after.\n", "tags": [ "Programs" ], "parameters": [ { "$ref": "#/components/parameters/MemberProgramId" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MemberCreateRequest" } } } }, "responses": { "200": { "description": "Member created successfully", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MemberWithCardsResponse" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "404": { "$ref": "#/components/responses/NotFound" }, "409": { "description": "Member already exists for this customer and program", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "423": { "description": "Program is not in ACTIVE status", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "$ref": "#/components/responses/InternalServerError" } } }, "get": { "operationId": "listMembers", "summary": "List members", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nLists members of a program with optional filtering and cursor-based pagination.\nSupports filtering by id, status, customer_id, and created_at.\n", "tags": [ "Programs" ], "parameters": [ { "$ref": "#/components/parameters/MemberProgramId" }, { "name": "limit", "in": "query", "description": "Number of results to return (1-100, default 10)", "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 10 } }, { "name": "order", "in": "query", "description": "Sort order for results", "schema": { "oneOf": [ { "type": "string", "enum": [ "-created_at", "created_at", "status", "-status", "customer_id", "-customer_id" ] }, { "type": "array", "items": { "type": "string" } } ] } }, { "name": "cursor", "in": "query", "description": "Cursor token for pagination (from previous response)", "schema": { "type": "string" } }, { "name": "filters[junction]", "in": "query", "description": "Logical junction for combining filters", "schema": { "type": "string", "enum": [ "AND", "OR" ] } }, { "name": "filters[id][conditions][$is]", "in": "query", "description": "Filter by exact member ID", "schema": { "type": "string" } }, { "name": "filters[id][conditions][$in]", "in": "query", "description": "Filter by member ID in list", "schema": { "type": "array", "items": { "type": "string" }, "maxItems": 100 } }, { "name": "filters[status][conditions][$is]", "in": "query", "description": "Filter by exact status", "schema": { "type": "string", "enum": [ "ACTIVE", "INACTIVE" ] } }, { "name": "filters[status][conditions][$in]", "in": "query", "description": "Filter by status in list", "schema": { "type": "array", "items": { "type": "string", "enum": [ "ACTIVE", "INACTIVE" ] } } }, { "name": "filters[customer_id][conditions][$is]", "in": "query", "description": "Filter by exact customer ID", "schema": { "type": "string" } }, { "name": "filters[customer_id][conditions][$in]", "in": "query", "description": "Filter by customer ID in list", "schema": { "type": "array", "items": { "type": "string" }, "maxItems": 100 } }, { "name": "filters[created_at][conditions][$before]", "in": "query", "description": "Filter by created_at before date (ISO 8601)", "schema": { "type": "string", "format": "date" } }, { "name": "filters[created_at][conditions][$after]", "in": "query", "description": "Filter by created_at after date (ISO 8601)", "schema": { "type": "string", "format": "date" } } ], "responses": { "200": { "description": "List of members", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MemberListResponse" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/programs/{programId}/members/{memberId}": { "get": { "operationId": "getMember", "summary": "Get member", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nRetrieves a single member by ID within a program, including their assigned cards with balances.\n\n**Note:** Card code generation is asynchronous. The card `code` field may be `null` if code generation has not completed yet (e.g. shortly after member creation).\n", "tags": [ "Programs" ], "parameters": [ { "$ref": "#/components/parameters/MemberProgramId" }, { "$ref": "#/components/parameters/MemberId" } ], "responses": { "200": { "description": "Member details", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MemberWithCardsResponse" } } } }, "404": { "$ref": "#/components/responses/NotFound" }, "500": { "$ref": "#/components/responses/InternalServerError" } } }, "delete": { "operationId": "deleteMember", "summary": "Delete member", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nSoft-deletes a member and all their associated cards within the program.\nThe program must exist. Returns the deleted member's data.\n", "tags": [ "Programs" ], "parameters": [ { "$ref": "#/components/parameters/MemberProgramId" }, { "$ref": "#/components/parameters/MemberId" } ], "responses": { "200": { "description": "Member deleted successfully", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MemberResponse" } } } }, "404": { "$ref": "#/components/responses/NotFound" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/programs/{programId}/members/{memberId}/activate": { "post": { "operationId": "activateMember", "summary": "Activate member", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nActivates an inactive member. The program must exist and the member must be in a state\nthat allows activation (i.e., INACTIVE). Fails if the member is already ACTIVE or DELETED.\n", "tags": [ "Programs" ], "parameters": [ { "$ref": "#/components/parameters/MemberProgramId" }, { "$ref": "#/components/parameters/MemberId" } ], "responses": { "200": { "description": "Member activated successfully", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MemberResponse" } } } }, "404": { "$ref": "#/components/responses/NotFound" }, "409": { "description": "Invalid state transition (member cannot be activated from current state)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/programs/{programId}/members/{memberId}/deactivate": { "post": { "operationId": "deactivateMember", "summary": "Deactivate member", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nDeactivates an active member. The program must exist and the member must be in a state\nthat allows deactivation (i.e., ACTIVE). Fails if the member is already INACTIVE or DELETED.\n", "tags": [ "Programs" ], "parameters": [ { "$ref": "#/components/parameters/MemberProgramId" }, { "$ref": "#/components/parameters/MemberId" } ], "responses": { "200": { "description": "Member deactivated successfully", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MemberResponse" } } } }, "404": { "$ref": "#/components/responses/NotFound" }, "409": { "description": "Invalid state transition (member cannot be deactivated from current state)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/programs/{programId}/members/{memberId}/activities": { "get": { "operationId": "listMemberActivities", "summary": "List member activities", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nLists activities for a specific member with optional filtering by id, type, and created_at.\nUses cursor-based pagination.\n\nActivity types include:\n- `vl.member.created`\n- `vl.member.deleted`\n- `vl.member.activated`\n- `vl.member.deactivated`\n- `vl.member.card.assigned`\n- `vl.member.card.unassigned`\n", "tags": [ "Programs" ], "parameters": [ { "$ref": "#/components/parameters/MemberProgramId" }, { "$ref": "#/components/parameters/MemberId" }, { "name": "limit", "in": "query", "description": "Number of results to return (1-100, default 10)", "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 10 } }, { "name": "order", "in": "query", "description": "Sort order for results", "schema": { "type": "string", "enum": [ "created_at", "-created_at" ] } }, { "name": "cursor", "in": "query", "description": "Cursor token for pagination", "schema": { "type": "string" } }, { "name": "filters[junction]", "in": "query", "schema": { "type": "string", "enum": [ "AND", "OR" ] } }, { "name": "filters[id][conditions][$is]", "in": "query", "schema": { "type": "string" } }, { "name": "filters[id][conditions][$in]", "in": "query", "schema": { "type": "array", "items": { "type": "string" }, "maxItems": 100 } }, { "name": "filters[type][conditions][$is]", "in": "query", "schema": { "type": "string", "enum": [ "vl.member.created", "vl.member.deleted", "vl.member.activated", "vl.member.deactivated", "vl.member.card.assigned", "vl.member.card.unassigned" ] } }, { "name": "filters[type][conditions][$in]", "in": "query", "schema": { "type": "array", "items": { "type": "string" } } }, { "name": "filters[created_at][conditions][$before]", "in": "query", "schema": { "type": "string", "format": "date" } }, { "name": "filters[created_at][conditions][$after]", "in": "query", "schema": { "type": "string", "format": "date" } } ], "responses": { "200": { "description": "List of member activities", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ActivityListResponse" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "404": { "$ref": "#/components/responses/NotFound" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/programs/{programId}/members/{memberId}/cards/{cardId}/points": { "post": { "operationId": "adjustCardPoints", "summary": "Adjust card points", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nManually adjusts points on a member's card. Positive values add points (ADMIN_CREDIT),\nnegative values subtract points (ADMIN_DEBIT). A value of zero results in no change.\n\nBoth the program and member must be in ACTIVE status. The card must be assigned to the member\nwithin the program.\n\nCreates a card transaction in PENDING status that is processed asynchronously.\n", "tags": [ "Programs" ], "parameters": [ { "$ref": "#/components/parameters/MemberProgramId" }, { "$ref": "#/components/parameters/MemberId" }, { "$ref": "#/components/parameters/CardId" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PointsAdjustmentRequest" } } } }, "responses": { "200": { "description": "Points adjustment result", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PointsAdjustmentResponse" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "404": { "$ref": "#/components/responses/NotFound" }, "423": { "description": "Program or member is not in ACTIVE status", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/programs/{programId}/members/{memberId}/cards/{cardId}/activities": { "get": { "operationId": "listCardActivities", "summary": "List card activities", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nLists activities for a specific card with optional filtering by id, type, and created_at.\nUses cursor-based pagination.\n\nActivity types include:\n- `vl.card.created`\n- `vl.card.assigned`\n- `vl.card.unassigned`\n- `vl.card.code_generation.succeeded`\n- `vl.card.code_generation.failed`\n", "tags": [ "Programs" ], "parameters": [ { "$ref": "#/components/parameters/MemberProgramId" }, { "$ref": "#/components/parameters/MemberId" }, { "$ref": "#/components/parameters/CardId" }, { "name": "limit", "in": "query", "description": "Number of results to return (1-100, default 10)", "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 10 } }, { "name": "order", "in": "query", "description": "Sort order for results", "schema": { "type": "string", "enum": [ "created_at", "-created_at" ] } }, { "name": "cursor", "in": "query", "description": "Cursor token for pagination", "schema": { "type": "string" } }, { "name": "filters[junction]", "in": "query", "schema": { "type": "string", "enum": [ "AND", "OR" ] } }, { "name": "filters[id][conditions][$is]", "in": "query", "schema": { "type": "string" } }, { "name": "filters[id][conditions][$in]", "in": "query", "schema": { "type": "array", "items": { "type": "string" }, "maxItems": 100 } }, { "name": "filters[type][conditions][$is]", "in": "query", "schema": { "type": "string", "enum": [ "vl.card.created", "vl.card.assigned", "vl.card.unassigned", "vl.card.code_generation.succeeded", "vl.card.code_generation.failed" ] } }, { "name": "filters[type][conditions][$in]", "in": "query", "schema": { "type": "array", "items": { "type": "string" } } }, { "name": "filters[created_at][conditions][$before]", "in": "query", "schema": { "type": "string", "format": "date" } }, { "name": "filters[created_at][conditions][$after]", "in": "query", "schema": { "type": "string", "format": "date" } } ], "responses": { "200": { "description": "List of card activities", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ActivityListResponse" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "404": { "$ref": "#/components/responses/NotFound" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/programs/{programId}/members/{memberId}/cards/{cardId}/pending-points": { "get": { "operationId": "listPendingPoints", "summary": "List pending points buckets", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nLists pending points buckets for a specific card. Only returns PENDING buckets\nwith future activation dates. If the card definition does not have pending points enabled,\nreturns an empty list.\n", "tags": [ "Programs" ], "parameters": [ { "$ref": "#/components/parameters/MemberProgramId" }, { "$ref": "#/components/parameters/MemberId" }, { "$ref": "#/components/parameters/CardId" }, { "name": "limit", "in": "query", "description": "Number of results to return (1-100, default 10)", "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 10 } }, { "name": "order", "in": "query", "description": "Sort order for results", "schema": { "oneOf": [ { "type": "string", "enum": [ "date", "-date" ] }, { "type": "array", "items": { "type": "string", "enum": [ "date", "-date" ] } } ] } }, { "name": "cursor", "in": "query", "description": "Cursor token for pagination", "schema": { "type": "string" } } ], "responses": { "200": { "description": "List of pending points buckets", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PendingPointsBucketListResponse" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "404": { "$ref": "#/components/responses/NotFound" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/programs/{programId}/members/{memberId}/cards/{cardId}/pending-points/{bucketId}/activate": { "post": { "operationId": "activatePendingPoints", "summary": "Activate pending points", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nManually activates a pending points bucket, converting pending points to active points.\nThe bucket must be in PENDING status and have a future activation date.\nBoth the program and member must be ACTIVE. The card definition must have pending points enabled.\n\nCreates a PENDING_POINTS_ACTIVATED transaction processed asynchronously.\n", "tags": [ "Programs" ], "parameters": [ { "$ref": "#/components/parameters/MemberProgramId" }, { "$ref": "#/components/parameters/MemberId" }, { "$ref": "#/components/parameters/CardId" }, { "$ref": "#/components/parameters/BucketId" } ], "responses": { "200": { "description": "Pending points activation result", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PointsActivationResponse" } } } }, "404": { "$ref": "#/components/responses/NotFound" }, "423": { "description": "One of:\n- Program or member is not in ACTIVE status\n- Pending points not enabled on card definition\n- Bucket is not in PENDING status\n- Bucket activation date is not in the future\n", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/programs/{programId}/members/{memberId}/cards/{cardId}/pending-points/{bucketId}/cancel": { "post": { "operationId": "cancelPendingPoints", "summary": "Cancel pending points", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nManually cancels a pending points bucket, preventing the points from ever being activated.\nThe bucket must be in PENDING status and have a future activation date.\nBoth the program and member must be ACTIVE. The card definition must have pending points enabled.\n\nCreates a PENDING_POINTS_CANCELED transaction processed asynchronously.\n", "tags": [ "Programs" ], "parameters": [ { "$ref": "#/components/parameters/MemberProgramId" }, { "$ref": "#/components/parameters/MemberId" }, { "$ref": "#/components/parameters/CardId" }, { "$ref": "#/components/parameters/BucketId" } ], "responses": { "200": { "description": "Pending points cancellation result", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PointsCancellationResponse" } } } }, "404": { "$ref": "#/components/responses/NotFound" }, "423": { "description": "One of:\n- Program or member is not in ACTIVE status\n- Pending points not enabled on card definition\n- Bucket is not in PENDING status\n- Bucket activation date is not in the future\n", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/programs/{programId}/members/{memberId}/cards/{cardId}/expiring-points": { "get": { "operationId": "listExpiringPoints", "summary": "List expiring points buckets", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nLists active points expiration buckets for a specific card. Only returns ACTIVE buckets\nwith future expiration dates. If the card definition does not have points expiration enabled,\nreturns an empty list.\n", "tags": [ "Programs" ], "parameters": [ { "$ref": "#/components/parameters/MemberProgramId" }, { "$ref": "#/components/parameters/MemberId" }, { "$ref": "#/components/parameters/CardId" }, { "name": "limit", "in": "query", "description": "Number of results to return (1-100, default 10)", "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 10 } }, { "name": "order", "in": "query", "description": "Sort order for results", "schema": { "oneOf": [ { "type": "string", "enum": [ "expiration_date", "-expiration_date" ] }, { "type": "array", "items": { "type": "string", "enum": [ "expiration_date", "-expiration_date" ] } } ] } }, { "name": "cursor", "in": "query", "description": "Cursor token for pagination", "schema": { "type": "string" } } ], "responses": { "200": { "description": "List of expiring points buckets", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExpiringPointsBucketListResponse" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "404": { "$ref": "#/components/responses/NotFound" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/programs/{programId}/members/{memberId}/cards/{cardId}/expiring-points/{bucketId}/expire": { "post": { "operationId": "expirePoints", "summary": "Expire points", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nManually expires an active points bucket. The bucket must be in ACTIVE status and\nhave a future expiration date. Both the program and member must be ACTIVE.\nThe card definition must have points expiration enabled.\n\nCreates an ADMIN_POINTS_EXPIRATION transaction processed asynchronously.\n", "tags": [ "Programs" ], "parameters": [ { "$ref": "#/components/parameters/MemberProgramId" }, { "$ref": "#/components/parameters/MemberId" }, { "$ref": "#/components/parameters/CardId" }, { "$ref": "#/components/parameters/BucketId" } ], "responses": { "200": { "description": "Points expiration result", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PointsExpirationResponse" } } } }, "404": { "$ref": "#/components/responses/NotFound" }, "423": { "description": "One of:\n- Program or member is not in ACTIVE status\n- Points expiration not enabled on card definition\n- Bucket is not in ACTIVE status\n- Bucket expiration date is not in the future\n", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/programs/{programId}/members/{memberId}/cards/{cardId}/transactions": { "get": { "operationId": "listCardTransactions", "summary": "List card transactions", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nLists transactions for a specific card within a member and program.\nUses cursor-based pagination. Returns all transaction types and statuses.\n", "tags": [ "Programs" ], "parameters": [ { "$ref": "#/components/parameters/MemberProgramId" }, { "$ref": "#/components/parameters/MemberId" }, { "$ref": "#/components/parameters/CardId" }, { "name": "limit", "in": "query", "description": "Number of results to return (1-100, default 10)", "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 10 } }, { "name": "order", "in": "query", "description": "Sort order for results", "schema": { "oneOf": [ { "type": "string", "enum": [ "-created_at", "created_at" ] }, { "type": "array", "items": { "type": "string", "enum": [ "-created_at", "created_at" ] } } ] } }, { "name": "cursor", "in": "query", "description": "Cursor token for pagination", "schema": { "type": "string" } } ], "responses": { "200": { "description": "List of card transactions", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CardTransactionListResponse" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "404": { "$ref": "#/components/responses/NotFound" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/programs/{programId}/members/{memberId}/rewards/purchases": { "post": { "operationId": "purchaseReward", "summary": "Purchase reward", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nInitiates a reward purchase for a member. Evaluates the reward cost, checks card balance,\nand creates a POINTS_SPENT_ON_REWARD transaction in PENDING status.\n\nThe operation is asynchronous - the transaction is processed after the response.\nReturns HTTP 202 Accepted.\n\nRequirements:\n- Program must be ACTIVE\n- Member must be ACTIVE\n- Reward must be assigned to the program with available stock\n- Member's card must have sufficient balance for the reward cost\n", "tags": [ "Programs" ], "parameters": [ { "$ref": "#/components/parameters/MemberProgramId" }, { "$ref": "#/components/parameters/MemberId" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RewardPurchaseRequest" } } } }, "responses": { "202": { "description": "Reward purchase initiated (processed asynchronously)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RewardPurchaseResponse" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "404": { "$ref": "#/components/responses/NotFound" }, "423": { "description": "One of:\n- Program or member is not in ACTIVE status\n- Reward is out of stock\n- No matching reward cost for customer context\n- Insufficient card balance\n", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "$ref": "#/components/responses/InternalServerError" } } }, "get": { "operationId": "listRewardPurchases", "summary": "List reward purchases", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nLists reward purchase transactions for a specific member within a program.\nOnly returns transactions of type PURCHASE. Supports filtering by id and created_at.\nUses cursor-based pagination.\n", "tags": [ "Programs" ], "parameters": [ { "$ref": "#/components/parameters/MemberProgramId" }, { "$ref": "#/components/parameters/MemberId" }, { "name": "limit", "in": "query", "description": "Number of results to return (1-100, default 10)", "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 10 } }, { "name": "order", "in": "query", "description": "Sort order for results", "schema": { "oneOf": [ { "type": "string", "enum": [ "-created_at", "created_at" ] }, { "type": "array", "items": { "type": "string", "enum": [ "-created_at", "created_at" ] } } ] } }, { "name": "cursor", "in": "query", "description": "Cursor token for pagination", "schema": { "type": "string" } }, { "name": "filters[junction]", "in": "query", "schema": { "type": "string", "enum": [ "AND", "OR" ] } }, { "name": "filters[id][conditions][$is]", "in": "query", "schema": { "type": "string" } }, { "name": "filters[id][conditions][$in]", "in": "query", "schema": { "type": "array", "items": { "type": "string" }, "maxItems": 100 } }, { "name": "filters[created_at][conditions][$before]", "in": "query", "schema": { "type": "string", "format": "date" } }, { "name": "filters[created_at][conditions][$after]", "in": "query", "schema": { "type": "string", "format": "date" } } ], "responses": { "200": { "description": "List of reward purchase transactions", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RewardTransactionListResponse" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "404": { "$ref": "#/components/responses/NotFound" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/examine/earning-rules": { "post": { "summary": "Examine Earnings", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nPerforms a dry-run estimation of points and incentives a customer (or member) would earn for a given event, without actually triggering any earning rule processing or modifying balances.", "operationId": "examineLoyaltyEarnings", "tags": [ "Examine" ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LoyaltiesExamineEarningRulesRequestBody" } } } }, "responses": { "200": { "description": "Successful dry-run estimation.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LoyaltiesExamineEarningRulesResponseBody" } } } }, "400": { "description": "Invalid payload (e.g., mutual exclusivity violation).", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "Customer or member not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/v2/loyalties/earning-rules": { "post": { "operationId": "createEarningRule", "summary": "Create Earning Rule", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nCreates a new earning rule. The rule defines a trigger event, validation rules,\nand effects (points or incentives) to award when triggered.\n\nRequires `name`, `trigger`, and `earnings` (with at least one effect per earning).\nStatus defaults to `DRAFT` if not specified.\n", "tags": [ "Earning Rules" ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/EarningRuleCreateRequest" } } } }, "responses": { "200": { "description": "Earning rule created successfully.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/EarningRuleResponse" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "404": { "$ref": "#/components/responses/NotFound" }, "500": { "$ref": "#/components/responses/InternalServerError" } } }, "get": { "operationId": "listEarningRules", "summary": "List Earning Rules", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nLists earning rules with optional filtering, ordering, and cursor-based pagination.\nDeleted earning rules are excluded.\n", "tags": [ "Earning Rules" ], "parameters": [ { "name": "filters[junction]", "in": "query", "schema": { "type": "string", "enum": [ "AND", "OR" ] }, "description": "Logical junction for combining filter conditions." }, { "name": "filters[id][conditions][$is]", "in": "query", "schema": { "type": "string" }, "description": "Filter by exact earning rule ID." }, { "name": "filters[id][conditions][$is_not]", "in": "query", "schema": { "type": "string" }, "description": "Exclude earning rule by ID." }, { "name": "filters[id][conditions][$in]", "in": "query", "schema": { "type": "array", "items": { "type": "string" } }, "description": "Filter by earning rule IDs (up to 100)." }, { "name": "filters[id][conditions][$not_in]", "in": "query", "schema": { "type": "array", "items": { "type": "string" } }, "description": "Exclude earning rule IDs (up to 100)." }, { "name": "filters[name][conditions][$is]", "in": "query", "schema": { "type": "string" }, "description": "Filter by exact name." }, { "name": "filters[name][conditions][$contains]", "in": "query", "schema": { "type": "string" }, "description": "Filter by name containing substring." }, { "name": "filters[name][conditions][$starts_with]", "in": "query", "schema": { "type": "string" }, "description": "Filter by name starting with prefix." }, { "name": "filters[status][conditions][$is]", "in": "query", "schema": { "type": "string", "enum": [ "ACTIVE", "INACTIVE", "DRAFT" ] }, "description": "Filter by exact status." }, { "name": "filters[status][conditions][$in]", "in": "query", "schema": { "type": "array", "items": { "type": "string", "enum": [ "ACTIVE", "INACTIVE", "DRAFT" ] } }, "description": "Filter by statuses." }, { "name": "filters[created_at][conditions][$before]", "in": "query", "schema": { "type": "string", "format": "date-time" }, "description": "Filter by creation date before." }, { "name": "filters[created_at][conditions][$after]", "in": "query", "schema": { "type": "string", "format": "date-time" }, "description": "Filter by creation date after." }, { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 10 }, "description": "Maximum number of results to return." }, { "name": "order", "in": "query", "schema": { "oneOf": [ { "type": "string", "enum": [ "-created_at", "created_at", "name", "-name" ] }, { "type": "array", "items": { "type": "string", "enum": [ "-created_at", "created_at", "name", "-name" ] } } ] }, "description": "Sort order. Prefix with `-` for descending. Default is `-created_at`." }, { "name": "cursor", "in": "query", "schema": { "type": "string" }, "description": "Cursor for pagination (obtained from previous response)." } ], "responses": { "200": { "description": "List of earning rules.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/EarningRuleListResponse" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/earning-rules/{id}": { "parameters": [ { "$ref": "#/components/parameters/EarningRuleId" } ], "get": { "operationId": "getEarningRule", "summary": "Get Earning Rule", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nRetrieves a single earning rule by its unique ID.", "tags": [ "Earning Rules" ], "responses": { "200": { "description": "Earning rule details.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/EarningRuleResponse" } } } }, "404": { "$ref": "#/components/responses/NotFound" }, "500": { "$ref": "#/components/responses/InternalServerError" } } }, "put": { "operationId": "updateEarningRule", "summary": "Update Earning Rule", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nUpdates an existing earning rule. All provided fields replace the existing values.\nFields not provided retain their current values (merge semantics).\n\nWhen the earning rule is in `DRAFT` status, all properties can be updated.\nFor `ACTIVE` or `INACTIVE` status, only these properties are allowed:\n`name`, `earnings`, `error`, `validity_hours`, `start_date`, `end_date`, `trigger_limits`, `metadata`.\n", "tags": [ "Earning Rules" ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/EarningRuleUpdateRequest" } } } }, "responses": { "200": { "description": "Earning rule updated successfully.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/EarningRuleResponse" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "404": { "$ref": "#/components/responses/NotFound" }, "500": { "$ref": "#/components/responses/InternalServerError" } } }, "delete": { "operationId": "deleteEarningRule", "summary": "Delete Earning Rule", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nDeletes an earning rule. Cannot delete an earning rule that is assigned to a program.\nReturns a `409 Conflict` if the rule is connected to a program.\n", "tags": [ "Earning Rules" ], "responses": { "200": { "description": "Earning rule deleted successfully.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/EarningRuleResponse" } } } }, "404": { "$ref": "#/components/responses/NotFound" }, "409": { "$ref": "#/components/responses/Conflict" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/earning-rules/{id}/activate": { "parameters": [ { "$ref": "#/components/parameters/EarningRuleId" } ], "post": { "operationId": "activateEarningRule", "summary": "Activate Earning Rule", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nTransitions the earning rule to `ACTIVE` status.\n\n**Allowed transitions:** `DRAFT` \u2192 `ACTIVE`, `INACTIVE` \u2192 `ACTIVE`.\n\nValidates that all referenced card definitions and incentives exist and are active.\n", "tags": [ "Earning Rules" ], "responses": { "200": { "description": "Earning rule activated.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/EarningRuleResponse" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "404": { "$ref": "#/components/responses/NotFound" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/earning-rules/{id}/deactivate": { "parameters": [ { "$ref": "#/components/parameters/EarningRuleId" } ], "post": { "operationId": "deactivateEarningRule", "summary": "Deactivate Earning Rule", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nTransitions the earning rule to `INACTIVE` status.\n\n**Allowed transitions:** `ACTIVE` \u2192 `INACTIVE`.\n", "tags": [ "Earning Rules" ], "responses": { "200": { "description": "Earning rule deactivated.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/EarningRuleResponse" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "404": { "$ref": "#/components/responses/NotFound" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/earning-rules/{id}/draft": { "parameters": [ { "$ref": "#/components/parameters/EarningRuleId" } ], "post": { "operationId": "draftEarningRule", "summary": "Move Earning Rule to Draft", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nTransitions the earning rule back to `DRAFT` status.\n\n**Allowed transitions:** `ACTIVE` \u2192 `DRAFT`.\n\nCannot draft an earning rule that is assigned to a non-draft program (returns `409 Conflict`).\n", "tags": [ "Earning Rules" ], "responses": { "200": { "description": "Earning rule moved to draft.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/EarningRuleResponse" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "404": { "$ref": "#/components/responses/NotFound" }, "409": { "$ref": "#/components/responses/Conflict" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/earning-rules/{id}/activities": { "parameters": [ { "$ref": "#/components/parameters/EarningRuleId" } ], "get": { "operationId": "listEarningRuleActivities", "summary": "List Earning Rule Activities", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nLists activity log entries for a specific earning rule with optional filtering,\nordering, and cursor-based pagination.\n", "tags": [ "Earning Rules" ], "parameters": [ { "name": "filters[junction]", "in": "query", "schema": { "type": "string", "enum": [ "AND", "OR" ] } }, { "name": "filters[id][conditions][$is]", "in": "query", "schema": { "type": "string" }, "description": "Filter by exact activity ID." }, { "name": "filters[type][conditions][$is]", "in": "query", "schema": { "type": "string", "enum": [ "vl.earning_rule.created", "vl.earning_rule.updated", "vl.earning_rule.deleted", "vl.earning_rule.activated", "vl.earning_rule.deactivated", "vl.earning_rule.drafted", "vl.earning_rule.assigned", "vl.earning_rule.unassigned" ] }, "description": "Filter by activity type." }, { "name": "filters[created_at][conditions][$before]", "in": "query", "schema": { "type": "string", "format": "date-time" }, "description": "Filter by creation date before." }, { "name": "filters[created_at][conditions][$after]", "in": "query", "schema": { "type": "string", "format": "date-time" }, "description": "Filter by creation date after." }, { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 10 } }, { "name": "order", "in": "query", "schema": { "oneOf": [ { "type": "string", "enum": [ "created_at", "-created_at" ] }, { "type": "array", "items": { "type": "string", "enum": [ "created_at", "-created_at" ] } } ] }, "description": "Sort order. Default is `-created_at`." }, { "name": "cursor", "in": "query", "schema": { "type": "string" }, "description": "Cursor for pagination." } ], "responses": { "200": { "description": "List of earning rule activities.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/EarningRuleActivitiesListResponse" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "404": { "$ref": "#/components/responses/NotFound" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/tier-structures": { "post": { "operationId": "createTierStructure", "summary": "Create Tier Structure", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nCreates a new tier structure. The `card_definition_id` must reference an existing card definition.\n\nWhen `type` is `POINT_EARNED`, the `point_earned` object is required.\nWhen `type` is `POINT_BALANCE`, the `point_earned` field must be null or omitted.\n\nDefaults: `expiration` defaults to `NO_EXPIRATION`, `downgrade` defaults to `NO_DOWNGRADE`,\n`status` defaults to `DRAFT`.\n", "tags": [ "Tier Structures" ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TierStructureCreateRequest" } } } }, "responses": { "200": { "description": "Created tier structure", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TierStructure" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "404": { "$ref": "#/components/responses/NotFound" }, "500": { "$ref": "#/components/responses/InternalServerError" } } }, "get": { "operationId": "listTierStructures", "summary": "List Tier Structures", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nReturns a paginated, cursor-based list of tier structures with optional filtering and ordering.\n", "tags": [ "Tier Structures" ], "parameters": [ { "name": "filters[junction]", "in": "query", "required": false, "schema": { "type": "string", "enum": [ "AND", "OR" ] }, "description": "Logical junction for combining filter conditions." }, { "name": "filters[id][conditions][$is]", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Filter by exact tier structure ID." }, { "name": "filters[id][conditions][$is_not]", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Exclude tier structures with this ID." }, { "name": "filters[id][conditions][$in]", "in": "query", "required": false, "schema": { "type": "array", "items": { "type": "string" }, "maxItems": 100 }, "description": "Filter by multiple tier structure IDs." }, { "name": "filters[id][conditions][$not_in]", "in": "query", "required": false, "schema": { "type": "array", "items": { "type": "string" }, "maxItems": 100 }, "description": "Exclude tier structures with these IDs." }, { "name": "filters[name][conditions][$is]", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Filter by exact name." }, { "name": "filters[name][conditions][$is_not]", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Exclude by exact name." }, { "name": "filters[name][conditions][$contains]", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Filter by name containing substring." }, { "name": "filters[name][conditions][$not_contain]", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Filter by name not containing substring." }, { "name": "filters[name][conditions][$starts_with]", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Filter by name starting with." }, { "name": "filters[name][conditions][$ends_with]", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Filter by name ending with." }, { "name": "filters[name][conditions][$in]", "in": "query", "required": false, "schema": { "type": "array", "items": { "type": "string" }, "maxItems": 10 }, "description": "Filter by multiple names." }, { "name": "filters[name][conditions][$not_in]", "in": "query", "required": false, "schema": { "type": "array", "items": { "type": "string" }, "maxItems": 10 }, "description": "Exclude tier structures with these names." }, { "name": "filters[name][conditions][$has_value]", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Filter for records where name has a value." }, { "name": "filters[name][conditions][$is_unknown]", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Filter for records where name is unknown." }, { "name": "filters[type][conditions][$is]", "in": "query", "required": false, "schema": { "type": "string", "enum": [ "POINT_BALANCE", "POINT_EARNED" ] }, "description": "Filter by exact tier structure type." }, { "name": "filters[type][conditions][$is_not]", "in": "query", "required": false, "schema": { "type": "string", "enum": [ "POINT_BALANCE", "POINT_EARNED" ] }, "description": "Exclude by tier structure type." }, { "name": "filters[type][conditions][$in]", "in": "query", "required": false, "schema": { "type": "array", "items": { "type": "string", "enum": [ "POINT_BALANCE", "POINT_EARNED" ] }, "maxItems": 10 }, "description": "Filter by multiple tier structure types." }, { "name": "filters[type][conditions][$not_in]", "in": "query", "required": false, "schema": { "type": "array", "items": { "type": "string", "enum": [ "POINT_BALANCE", "POINT_EARNED" ] }, "maxItems": 10 }, "description": "Exclude by multiple tier structure types." }, { "name": "filters[status][conditions][$is]", "in": "query", "required": false, "schema": { "type": "string", "enum": [ "DRAFT", "ACTIVE", "INACTIVE", "DELETED" ] }, "description": "Filter by exact status." }, { "name": "filters[status][conditions][$is_not]", "in": "query", "required": false, "schema": { "type": "string", "enum": [ "DRAFT", "ACTIVE", "INACTIVE", "DELETED" ] }, "description": "Exclude by status." }, { "name": "filters[status][conditions][$in]", "in": "query", "required": false, "schema": { "type": "array", "items": { "type": "string", "enum": [ "DRAFT", "ACTIVE", "INACTIVE", "DELETED" ] }, "maxItems": 10 }, "description": "Filter by multiple statuses." }, { "name": "filters[status][conditions][$not_in]", "in": "query", "required": false, "schema": { "type": "array", "items": { "type": "string", "enum": [ "DRAFT", "ACTIVE", "INACTIVE", "DELETED" ] }, "maxItems": 10 }, "description": "Exclude by multiple statuses." }, { "name": "filters[created_at][conditions][$before]", "in": "query", "required": false, "schema": { "type": "string", "format": "date-time" }, "description": "Filter for records created before this date." }, { "name": "filters[created_at][conditions][$after]", "in": "query", "required": false, "schema": { "type": "string", "format": "date-time" }, "description": "Filter for records created after this date." }, { "name": "filters[created_at][conditions][$is]", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 0 }, "description": "Filter for records created exactly N days ago." }, { "name": "filters[created_at][conditions][$more_than]", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 0 }, "description": "Filter for records created more than N days ago." }, { "name": "filters[created_at][conditions][$less_than]", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 0 }, "description": "Filter for records created less than N days ago." }, { "name": "filters[created_at][conditions][$has_value]", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Filter for records where created_at has a value." }, { "name": "filters[created_at][conditions][$is_unknown]", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Filter for records where created_at is unknown." }, { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 10 }, "description": "Maximum number of results to return (1-100)." }, { "name": "order", "in": "query", "required": false, "schema": { "type": "array", "items": { "type": "string", "enum": [ "-created_at", "created_at", "name", "-name", "type", "-type", "status", "-status" ] } }, "description": "Sort order. Prefix with `-` for descending. Default: `-created_at`." }, { "name": "cursor", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Cursor for pagination. Obtained from a previous list response." } ], "responses": { "200": { "description": "List of tier structures", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TierStructureListResponse" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/tier-structures/{id}": { "parameters": [ { "$ref": "#/components/parameters/TierStructureId" } ], "get": { "operationId": "getTierStructure", "summary": "Get Tier Structure", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nReturns a single tier structure by ID.", "tags": [ "Tier Structures" ], "responses": { "200": { "description": "Tier structure details", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TierStructure" } } } }, "404": { "$ref": "#/components/responses/NotFound" }, "500": { "$ref": "#/components/responses/InternalServerError" } } }, "put": { "operationId": "updateTierStructure", "summary": "Update Tier Structure", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nUpdates an existing tier structure. All fields are optional; omitted fields retain their current values.\n\nWhen the tier structure is not in `DRAFT` status, only `name` and `metadata` may be updated.\n\nIf `type` changes to `POINT_EARNED`, `point_earned` is required.\nIf `type` changes to `POINT_BALANCE`, `point_earned` must be null.\n", "tags": [ "Tier Structures" ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TierStructureUpdateRequest" } } } }, "responses": { "200": { "description": "Updated tier structure", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TierStructure" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "404": { "$ref": "#/components/responses/NotFound" }, "500": { "$ref": "#/components/responses/InternalServerError" } } }, "delete": { "operationId": "deleteTierStructure", "summary": "Delete Tier Structure", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nSoft-deletes a tier structure and all its tiers.\nCannot delete a tier structure that is assigned to a program.\n", "tags": [ "Tier Structures" ], "responses": { "200": { "description": "Deleted tier structure", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TierStructure" } } } }, "404": { "$ref": "#/components/responses/NotFound" }, "409": { "description": "Tier structure is in use by a program and cannot be deleted.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/tier-structures/{id}/activate": { "parameters": [ { "$ref": "#/components/parameters/TierStructureId" } ], "post": { "operationId": "activateTierStructure", "summary": "Activate Tier Structure", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nTransitions a tier structure to `ACTIVE` status.\nAllowed from: `DRAFT`, `INACTIVE`.\nCannot activate if the program already has an active/draft tier structure assignment at its limit.\n", "tags": [ "Tier Structures" ], "responses": { "200": { "description": "Activated tier structure", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TierStructure" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "404": { "$ref": "#/components/responses/NotFound" }, "409": { "description": "Invalid state transition or assignment limit exceeded.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/tier-structures/{id}/deactivate": { "parameters": [ { "$ref": "#/components/parameters/TierStructureId" } ], "post": { "operationId": "deactivateTierStructure", "summary": "Deactivate Tier Structure", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nTransitions a tier structure to `INACTIVE` status.\nAllowed from: `ACTIVE`.\n", "tags": [ "Tier Structures" ], "responses": { "200": { "description": "Deactivated tier structure", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TierStructure" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "404": { "$ref": "#/components/responses/NotFound" }, "409": { "description": "Invalid state transition.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/tier-structures/{id}/draft": { "parameters": [ { "$ref": "#/components/parameters/TierStructureId" } ], "post": { "operationId": "draftTierStructure", "summary": "Draft Tier Structure", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nTransitions a tier structure back to `DRAFT` status.\nAllowed from: `ACTIVE`.\nCannot draft a tier structure connected to a non-draft program.\n", "tags": [ "Tier Structures" ], "responses": { "200": { "description": "Drafted tier structure", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TierStructure" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "404": { "$ref": "#/components/responses/NotFound" }, "409": { "description": "Invalid state transition or tier structure is connected to a non-draft program.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/tier-structures/{id}/activities": { "parameters": [ { "$ref": "#/components/parameters/TierStructureId" } ], "get": { "operationId": "listTierStructureActivities", "summary": "List Tier Structure Activities", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nReturns a paginated, cursor-based list of activities (audit log) for a tier structure.\nIncludes events for the tier structure itself and its nested tiers.\n", "tags": [ "Tier Structures" ], "parameters": [ { "name": "filters[junction]", "in": "query", "required": false, "schema": { "type": "string", "enum": [ "AND", "OR" ] }, "description": "Logical junction for combining filter conditions." }, { "name": "filters[id][conditions][$is]", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Filter by exact activity ID." }, { "name": "filters[id][conditions][$is_not]", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Exclude activities with this ID." }, { "name": "filters[id][conditions][$in]", "in": "query", "required": false, "schema": { "type": "array", "items": { "type": "string" }, "maxItems": 100 }, "description": "Filter by multiple activity IDs." }, { "name": "filters[id][conditions][$not_in]", "in": "query", "required": false, "schema": { "type": "array", "items": { "type": "string" }, "maxItems": 100 }, "description": "Exclude activities with these IDs." }, { "name": "filters[type][conditions][$is]", "in": "query", "required": false, "schema": { "type": "string", "enum": [ "vl.tier_structure.created", "vl.tier_structure.updated", "vl.tier_structure.deleted", "vl.tier_structure.activated", "vl.tier_structure.deactivated", "vl.tier_structure.drafted", "vl.tier_structure.assigned", "vl.tier_structure.unassigned", "vl.tier_structure.tier.created", "vl.tier_structure.tier.updated", "vl.tier_structure.tier.deleted" ] }, "description": "Filter by exact activity type." }, { "name": "filters[type][conditions][$is_not]", "in": "query", "required": false, "schema": { "type": "string", "enum": [ "vl.tier_structure.created", "vl.tier_structure.updated", "vl.tier_structure.deleted", "vl.tier_structure.activated", "vl.tier_structure.deactivated", "vl.tier_structure.drafted", "vl.tier_structure.assigned", "vl.tier_structure.unassigned", "vl.tier_structure.tier.created", "vl.tier_structure.tier.updated", "vl.tier_structure.tier.deleted" ] }, "description": "Exclude activities with this type." }, { "name": "filters[type][conditions][$in]", "in": "query", "required": false, "schema": { "type": "array", "items": { "type": "string", "enum": [ "vl.tier_structure.created", "vl.tier_structure.updated", "vl.tier_structure.deleted", "vl.tier_structure.activated", "vl.tier_structure.deactivated", "vl.tier_structure.drafted", "vl.tier_structure.assigned", "vl.tier_structure.unassigned", "vl.tier_structure.tier.created", "vl.tier_structure.tier.updated", "vl.tier_structure.tier.deleted" ] }, "maxItems": 10 }, "description": "Filter by multiple activity types." }, { "name": "filters[type][conditions][$not_in]", "in": "query", "required": false, "schema": { "type": "array", "items": { "type": "string", "enum": [ "vl.tier_structure.created", "vl.tier_structure.updated", "vl.tier_structure.deleted", "vl.tier_structure.activated", "vl.tier_structure.deactivated", "vl.tier_structure.drafted", "vl.tier_structure.assigned", "vl.tier_structure.unassigned", "vl.tier_structure.tier.created", "vl.tier_structure.tier.updated", "vl.tier_structure.tier.deleted" ] }, "maxItems": 10 }, "description": "Exclude activities with these types." }, { "name": "filters[created_at][conditions][$before]", "in": "query", "required": false, "schema": { "type": "string", "format": "date-time" }, "description": "Filter for activities created before this date." }, { "name": "filters[created_at][conditions][$after]", "in": "query", "required": false, "schema": { "type": "string", "format": "date-time" }, "description": "Filter for activities created after this date." }, { "name": "filters[created_at][conditions][$is]", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 0 }, "description": "Filter for activities created exactly N days ago." }, { "name": "filters[created_at][conditions][$more_than]", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 0 }, "description": "Filter for activities created more than N days ago." }, { "name": "filters[created_at][conditions][$less_than]", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 0 }, "description": "Filter for activities created less than N days ago." }, { "name": "filters[created_at][conditions][$has_value]", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Filter for records where created_at has a value." }, { "name": "filters[created_at][conditions][$is_unknown]", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Filter for records where created_at is unknown." }, { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 10 }, "description": "Maximum number of results to return (1-100)." }, { "name": "order", "in": "query", "required": false, "schema": { "type": "array", "items": { "type": "string", "enum": [ "created_at", "-created_at" ] } }, "description": "Sort order. Prefix with `-` for descending. Default: `-created_at`." }, { "name": "cursor", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Cursor for pagination. Obtained from a previous list response." } ], "responses": { "200": { "description": "List of tier structure activities", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TierStructureActivityListResponse" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "404": { "$ref": "#/components/responses/NotFound" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/tier-structures/{id}/tiers": { "parameters": [ { "$ref": "#/components/parameters/TierStructureId" } ], "post": { "operationId": "createTier", "summary": "Create Tier", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nCreates a new tier within the specified tier structure.\n\nMaximum of 10 tiers per tier structure.\n\nWhen `qualification_rules.type` is `POINTS`, `min_value` is required and point ranges\nmust not overlap with existing tiers.\nWhen `qualification_rules.type` is `SEGMENT`, `segment.id` is required and must\nreference a valid segment.\n\n`downgrade.type` defaults to `INHERIT` if omitted.\n", "tags": [ "Tier Structures" ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TierCreateRequest" } } } }, "responses": { "200": { "description": "Created tier", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Tier" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "403": { "description": "Tier overlaps with an existing tier's point range.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "$ref": "#/components/responses/NotFound" }, "409": { "description": "Maximum number of tiers per tier structure exceeded.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "$ref": "#/components/responses/InternalServerError" } } }, "get": { "operationId": "listTiers", "summary": "List Tiers", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nReturns a paginated, cursor-based list of tiers belonging to the specified tier structure.\n", "tags": [ "Tier Structures" ], "parameters": [ { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 10 }, "description": "Maximum number of results to return (1-100)." }, { "name": "order", "in": "query", "required": false, "schema": { "type": "array", "items": { "type": "string", "enum": [ "created_at", "-created_at", "name", "-name" ] } }, "description": "Sort order. Prefix with `-` for descending. Default: `-created_at`." }, { "name": "cursor", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Cursor for pagination. Obtained from a previous list response." } ], "responses": { "200": { "description": "List of tiers", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TierListResponse" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/tier-structures/{id}/tiers/{tierId}": { "parameters": [ { "$ref": "#/components/parameters/TierStructureId" }, { "$ref": "#/components/parameters/TierId" } ], "put": { "operationId": "updateTier", "summary": "Update Tier", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nUpdates an existing tier. All fields are optional; omitted fields retain their current values.\n\nThe tier must belong to the specified tier structure.\n\nWhen changing `qualification_rules.type` to `POINTS`, `min_value` is required and\nthe new point range must not overlap with other tiers.\nWhen changing to `SEGMENT`, `segment.id` is required.\n", "tags": [ "Tier Structures" ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TierUpdateRequest" } } } }, "responses": { "200": { "description": "Updated tier", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Tier" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "403": { "description": "Tier overlaps with an existing tier's point range.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "$ref": "#/components/responses/NotFound" }, "500": { "$ref": "#/components/responses/InternalServerError" } } }, "delete": { "operationId": "deleteTier", "summary": "Delete Tier", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nSoft-deletes a tier. The tier must belong to the specified tier structure.\n", "tags": [ "Tier Structures" ], "responses": { "200": { "description": "Deleted tier", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Tier" } } } }, "404": { "$ref": "#/components/responses/NotFound" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/incentives": { "get": { "operationId": "listIncentives", "summary": "List incentives", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nReturns a paginated, cursor-based list of incentives. Supports filtering by id, name, status, type, and created_at. Results can be ordered by created_at, name, or type.\n", "tags": [ "Incentives" ], "parameters": [ { "$ref": "#/components/parameters/IncentiveListLimit" }, { "$ref": "#/components/parameters/IncentiveListOrder" }, { "$ref": "#/components/parameters/IncentiveListCursor" }, { "name": "filters[junction]", "in": "query", "schema": { "$ref": "#/components/schemas/FiltersJunction" } }, { "name": "filters[id][conditions][$is]", "in": "query", "schema": { "type": "string", "pattern": "^linc_[a-f0-9]+$" } }, { "name": "filters[id][conditions][$is_not]", "in": "query", "schema": { "type": "string", "pattern": "^linc_[a-f0-9]+$" } }, { "name": "filters[id][conditions][$in]", "in": "query", "schema": { "type": "array", "items": { "type": "string", "pattern": "^linc_[a-f0-9]+$" }, "minItems": 1, "maxItems": 100 } }, { "name": "filters[id][conditions][$not_in]", "in": "query", "schema": { "type": "array", "items": { "type": "string", "pattern": "^linc_[a-f0-9]+$" }, "minItems": 1, "maxItems": 100 } }, { "name": "filters[name][conditions][$is]", "in": "query", "schema": { "type": "string" } }, { "name": "filters[name][conditions][$is_not]", "in": "query", "schema": { "type": "string" } }, { "name": "filters[name][conditions][$contains]", "in": "query", "schema": { "type": "string" } }, { "name": "filters[name][conditions][$not_contain]", "in": "query", "schema": { "type": "string" } }, { "name": "filters[name][conditions][$starts_with]", "in": "query", "schema": { "type": "string" } }, { "name": "filters[name][conditions][$ends_with]", "in": "query", "schema": { "type": "string" } }, { "name": "filters[name][conditions][$in]", "in": "query", "schema": { "type": "array", "items": { "type": "string" }, "minItems": 1, "maxItems": 10 } }, { "name": "filters[name][conditions][$not_in]", "in": "query", "schema": { "type": "array", "items": { "type": "string" }, "minItems": 1, "maxItems": 10 } }, { "name": "filters[status][conditions][$is]", "in": "query", "schema": { "type": "string", "enum": [ "ACTIVE", "DRAFT" ] } }, { "name": "filters[status][conditions][$is_not]", "in": "query", "schema": { "type": "string", "enum": [ "ACTIVE", "DRAFT" ] } }, { "name": "filters[status][conditions][$in]", "in": "query", "schema": { "type": "array", "items": { "type": "string", "enum": [ "ACTIVE", "DRAFT" ] }, "minItems": 1, "maxItems": 10 } }, { "name": "filters[status][conditions][$not_in]", "in": "query", "schema": { "type": "array", "items": { "type": "string", "enum": [ "ACTIVE", "DRAFT" ] }, "minItems": 1, "maxItems": 10 } }, { "name": "filters[type][conditions][$is]", "in": "query", "schema": { "$ref": "#/components/schemas/IncentiveType" } }, { "name": "filters[type][conditions][$is_not]", "in": "query", "schema": { "$ref": "#/components/schemas/IncentiveType" } }, { "name": "filters[type][conditions][$in]", "in": "query", "schema": { "type": "array", "items": { "$ref": "#/components/schemas/IncentiveType" }, "minItems": 1, "maxItems": 10 } }, { "name": "filters[type][conditions][$not_in]", "in": "query", "schema": { "type": "array", "items": { "$ref": "#/components/schemas/IncentiveType" }, "minItems": 1, "maxItems": 10 } }, { "name": "filters[created_at][conditions][$before]", "in": "query", "schema": { "type": "string", "format": "date" } }, { "name": "filters[created_at][conditions][$after]", "in": "query", "schema": { "type": "string", "format": "date" } } ], "responses": { "200": { "description": "A paginated list of incentives.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/IncentiveListResponse" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "500": { "$ref": "#/components/responses/InternalServerError" } } }, "post": { "operationId": "createIncentive", "summary": "Create an incentive", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nCreates a new incentive. The `type` field determines which detail object (`points`, `points_proportional`, `material`, or `digital`) is required. Exactly one detail object must be provided matching the type.\n", "tags": [ "Incentives" ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/IncentiveCreateRequest" } } } }, "responses": { "200": { "description": "The created incentive.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/IncentiveDTO" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "404": { "$ref": "#/components/responses/NotFound" }, "409": { "$ref": "#/components/responses/Conflict" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/incentives/{id}": { "get": { "operationId": "getIncentive", "summary": "Get an incentive", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nReturns a single incentive by its ID.", "tags": [ "Incentives" ], "parameters": [ { "$ref": "#/components/parameters/IncentiveId" } ], "responses": { "200": { "description": "The incentive.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/IncentiveDTO" } } } }, "404": { "$ref": "#/components/responses/NotFound" }, "500": { "$ref": "#/components/responses/InternalServerError" } } }, "put": { "operationId": "updateIncentive", "summary": "Update an incentive", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nUpdates an existing incentive. In DRAFT status all properties can be updated. In ACTIVE status only `name` and `stock` can be changed. At least one property must be provided.\n", "tags": [ "Incentives" ], "parameters": [ { "$ref": "#/components/parameters/IncentiveId" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/IncentiveUpdateRequest" } } } }, "responses": { "200": { "description": "The updated incentive.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/IncentiveDTO" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "404": { "$ref": "#/components/responses/NotFound" }, "409": { "$ref": "#/components/responses/Conflict" }, "500": { "$ref": "#/components/responses/InternalServerError" } } }, "delete": { "operationId": "deleteIncentive", "summary": "Delete an incentive", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nSoft-deletes an incentive. Fails if the incentive is currently referenced by any earning rule.\n", "tags": [ "Incentives" ], "parameters": [ { "$ref": "#/components/parameters/IncentiveId" } ], "responses": { "200": { "description": "The deleted incentive (with status DELETED).", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/IncentiveDTO" } } } }, "404": { "$ref": "#/components/responses/NotFound" }, "409": { "$ref": "#/components/responses/ResourceInUse" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/incentives/{id}/activate": { "post": { "operationId": "activateIncentive", "summary": "Activate an incentive", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nTransitions an incentive from DRAFT to ACTIVE. The only valid transition is DRAFT -> ACTIVE. Connected card definitions must exist and be ACTIVE.\n", "tags": [ "Incentives" ], "parameters": [ { "$ref": "#/components/parameters/IncentiveId" } ], "responses": { "200": { "description": "The activated incentive.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/IncentiveDTO" } } } }, "400": { "$ref": "#/components/responses/InvalidStateTransition" }, "404": { "$ref": "#/components/responses/NotFound" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/incentives/{id}/draft": { "post": { "operationId": "draftIncentive", "summary": "Move an incentive to draft", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nTransitions an incentive from ACTIVE to DRAFT. The only valid transition is ACTIVE -> DRAFT. Fails if the incentive is assigned to any active earning rule.\n", "tags": [ "Incentives" ], "parameters": [ { "$ref": "#/components/parameters/IncentiveId" } ], "responses": { "200": { "description": "The drafted incentive.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/IncentiveDTO" } } } }, "400": { "$ref": "#/components/responses/InvalidStateTransition" }, "404": { "$ref": "#/components/responses/NotFound" }, "409": { "$ref": "#/components/responses/ResourceLocked" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/incentives/{id}/activities": { "get": { "operationId": "listIncentiveActivities", "summary": "List incentive activities", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nReturns a paginated, cursor-based list of activity entries for a specific incentive. Supports filtering by activity id, type, and created_at.\n", "tags": [ "Incentives" ], "parameters": [ { "$ref": "#/components/parameters/IncentiveId" }, { "$ref": "#/components/parameters/IncentiveActivitiesLimit" }, { "$ref": "#/components/parameters/IncentiveActivitiesOrder" }, { "$ref": "#/components/parameters/IncentiveActivitiesCursor" }, { "name": "filters[junction]", "in": "query", "schema": { "$ref": "#/components/schemas/FiltersJunction" } }, { "name": "filters[id][conditions][$is]", "in": "query", "schema": { "type": "string", "pattern": "^lainc_[a-f0-9]+$" } }, { "name": "filters[id][conditions][$is_not]", "in": "query", "schema": { "type": "string", "pattern": "^lainc_[a-f0-9]+$" } }, { "name": "filters[id][conditions][$in]", "in": "query", "schema": { "type": "array", "items": { "type": "string", "pattern": "^lainc_[a-f0-9]+$" }, "minItems": 1, "maxItems": 100 } }, { "name": "filters[id][conditions][$not_in]", "in": "query", "schema": { "type": "array", "items": { "type": "string", "pattern": "^lainc_[a-f0-9]+$" }, "minItems": 1, "maxItems": 100 } }, { "name": "filters[type][conditions][$is]", "in": "query", "schema": { "$ref": "#/components/schemas/IncentiveActivityType" } }, { "name": "filters[type][conditions][$is_not]", "in": "query", "schema": { "$ref": "#/components/schemas/IncentiveActivityType" } }, { "name": "filters[type][conditions][$in]", "in": "query", "schema": { "type": "array", "items": { "$ref": "#/components/schemas/IncentiveActivityType" }, "minItems": 1, "maxItems": 10 } }, { "name": "filters[type][conditions][$not_in]", "in": "query", "schema": { "type": "array", "items": { "$ref": "#/components/schemas/IncentiveActivityType" }, "minItems": 1, "maxItems": 10 } }, { "name": "filters[created_at][conditions][$before]", "in": "query", "schema": { "type": "string", "format": "date" } }, { "name": "filters[created_at][conditions][$after]", "in": "query", "schema": { "type": "string", "format": "date" } } ], "responses": { "200": { "description": "A paginated list of incentive activities.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/IncentiveActivityListResponse" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "404": { "$ref": "#/components/responses/NotFound" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/rewards": { "get": { "operationId": "listRewards", "summary": "List rewards", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nReturns a cursor-paginated, filterable list of rewards.", "tags": [ "Rewards" ], "parameters": [ { "$ref": "#/components/parameters/RewardQueryLimit" }, { "name": "order", "in": "query", "required": false, "description": "Sort order. Prefix with `-` for descending. Supports multiple values.", "schema": { "oneOf": [ { "type": "string", "enum": [ "-created_at", "created_at", "name", "-name" ] }, { "type": "array", "items": { "type": "string", "enum": [ "-created_at", "created_at", "name", "-name" ] } } ] } }, { "$ref": "#/components/parameters/RewardQueryCursor" }, { "name": "filters", "in": "query", "required": false, "description": "Filter criteria. Passed via bracket notation in query string, e.g.\n`filters[junction]=AND&filters[id][conditions][$is]=rw_xxx`.\n", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/VLRewardsFilters" } } } } ], "responses": { "200": { "description": "Paginated list of rewards.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/VLRewardListResponse" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "500": { "$ref": "#/components/responses/InternalServerError" } } }, "post": { "operationId": "createReward", "summary": "Create a reward", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nCreates a new reward. `name` and `type` are required.\nDepending on `type`, either `material` or `digital` must be provided (not both).\nReferenced campaigns (for digital rewards) or products/SKUs (for material rewards)\nmust exist.\n", "tags": [ "Rewards" ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/VLRewardCreateAPIParams" } } } }, "responses": { "200": { "description": "Created reward.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/VLRewardDTO" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "404": { "description": "Referenced resource not found (campaign, product, or SKU).", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/rewards/{id}": { "get": { "operationId": "getReward", "summary": "Get a reward", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nRetrieves a single reward by ID.", "tags": [ "Rewards" ], "parameters": [ { "$ref": "#/components/parameters/RewardId" } ], "responses": { "200": { "description": "Reward details.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/VLRewardDTO" } } } }, "404": { "$ref": "#/components/responses/NotFound" }, "500": { "$ref": "#/components/responses/InternalServerError" } } }, "put": { "operationId": "updateReward", "summary": "Update a reward", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nUpdates an existing reward. All properties are optional.\nIn DRAFT status all properties can be updated.\nIn ACTIVE or INACTIVE status only `name` and `metadata` are allowed.\nWhen changing `type`, the matching sub-configuration must be supplied\nand the previous one is reset to null.\n", "tags": [ "Rewards" ], "parameters": [ { "$ref": "#/components/parameters/RewardId" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/VLRewardUpdateAPIParams" } } } }, "responses": { "200": { "description": "Updated reward.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/VLRewardDTO" } } } }, "400": { "description": "Invalid payload or restricted property update in non-draft status.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "Reward or referenced resource not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "$ref": "#/components/responses/InternalServerError" } } }, "delete": { "operationId": "deleteReward", "summary": "Delete a reward", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nSoft-deletes a reward. Fails if the reward is currently assigned to any program.", "tags": [ "Rewards" ], "parameters": [ { "$ref": "#/components/parameters/RewardId" } ], "responses": { "200": { "description": "Deleted reward (status set to DELETED).", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/VLRewardDTO" } } } }, "400": { "description": "Reward is in use by one or more programs.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ResourceInUseErrorResponse" } } } }, "404": { "$ref": "#/components/responses/NotFound" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/rewards/{id}/activate": { "post": { "operationId": "activateReward", "summary": "Activate a reward", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nTransitions a reward to ACTIVE status. Valid from DRAFT or INACTIVE.", "tags": [ "Rewards" ], "parameters": [ { "$ref": "#/components/parameters/RewardId" } ], "responses": { "200": { "description": "Activated reward.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/VLRewardDTO" } } } }, "400": { "description": "Invalid state transition.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "$ref": "#/components/responses/NotFound" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/rewards/{id}/deactivate": { "post": { "operationId": "deactivateReward", "summary": "Deactivate a reward", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nTransitions a reward to INACTIVE status. Valid only from ACTIVE.", "tags": [ "Rewards" ], "parameters": [ { "$ref": "#/components/parameters/RewardId" } ], "responses": { "200": { "description": "Deactivated reward.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/VLRewardDTO" } } } }, "400": { "description": "Invalid state transition.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "$ref": "#/components/responses/NotFound" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/rewards/{id}/draft": { "post": { "operationId": "draftReward", "summary": "Move reward to draft", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nTransitions a reward back to DRAFT status. Valid only from ACTIVE.\nFails with 423 if the reward is assigned to a non-draft program.\n", "tags": [ "Rewards" ], "parameters": [ { "$ref": "#/components/parameters/RewardId" } ], "responses": { "200": { "description": "Drafted reward.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/VLRewardDTO" } } } }, "400": { "description": "Invalid state transition.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "$ref": "#/components/responses/NotFound" }, "423": { "description": "Reward is locked — assigned to a non-draft program.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "$ref": "#/components/responses/InternalServerError" } } } }, "/v2/loyalties/rewards/{id}/activities": { "get": { "operationId": "listRewardActivities", "summary": "List reward activities", "description": "\u26a0\ufe0f **BETA endpoint**\n\nThis is a work-in-progress documentation of a BETA endpoint. The parameters, fields, request and response bodies, and other data may subject to change. If you want to share feedback or improvements, contact Voucherify support or your Technical Account Manager.\n\nReturns a cursor-paginated audit log of activities for a specific reward.", "tags": [ "Rewards" ], "parameters": [ { "$ref": "#/components/parameters/RewardId" }, { "$ref": "#/components/parameters/RewardQueryLimit" }, { "name": "order", "in": "query", "required": false, "description": "Sort order for activities.", "schema": { "oneOf": [ { "type": "string", "enum": [ "created_at", "-created_at" ] }, { "type": "array", "items": { "type": "string", "enum": [ "created_at", "-created_at" ] } } ] } }, { "$ref": "#/components/parameters/RewardQueryCursor" }, { "name": "filters", "in": "query", "required": false, "description": "Filter criteria. Passed via bracket notation in query string.\n", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/VLRewardActivitiesFilters" } } } } ], "responses": { "200": { "description": "Paginated list of reward activities.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/VLRewardActivityListResponse" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "404": { "$ref": "#/components/responses/NotFound" }, "500": { "$ref": "#/components/responses/InternalServerError" } } } } }, "components": { "securitySchemes": { "bearerAuth": { "type": "http", "scheme": "bearer", "bearerFormat": "JWT" }, "X-App-Id": { "type": "apiKey", "name": "X-App-Id", "in": "header" }, "X-App-Token": { "type": "apiKey", "name": "X-App-Token", "in": "header" } }, "parameters": { "CardDefinitionId": { "name": "id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Unique card definition identifier." }, "ProgramId": { "name": "id", "in": "path", "required": true, "description": "Unique program identifier", "schema": { "type": "string", "pattern": "^lprg_[a-f0-9]+$" } }, "QueryLimit": { "name": "limit", "in": "query", "required": false, "description": "Maximum number of results to return (1-100, default 10)", "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 10 } }, "ProgramsOrder": { "name": "order", "in": "query", "required": false, "description": "Sort order for results", "schema": { "oneOf": [ { "type": "string", "enum": [ "-created_at", "created_at", "name", "-name" ] }, { "type": "array", "items": { "type": "string", "enum": [ "-created_at", "created_at", "name", "-name" ] } } ] } }, "ProgramsCursor": { "name": "cursor", "in": "query", "required": false, "description": "Cursor for pagination (from previous response)", "schema": { "type": "string", "pattern": "^lcrsprg_[a-f0-9]+$" } }, "ProgramsFilterId": { "name": "filters[id][conditions]", "in": "query", "required": false, "description": "Filter by program id. Supports conditions `$is`, `$is_not`, `$in`, `$not_in`.", "schema": { "type": "object" } }, "ProgramsFilterName": { "name": "filters[name][conditions]", "in": "query", "required": false, "description": "Filter by program name. Supports conditions `$is`, `$is_not`, `$contains`, `$not_contain`, `$starts_with`, `$ends_with`, `$in`, `$not_in`, `$has_value`, `$is_unknown`.", "schema": { "type": "object" } }, "ProgramsFilterStatus": { "name": "filters[status][conditions]", "in": "query", "required": false, "description": "Filter by program status. Supports conditions `$is`, `$is_not`, `$in`, `$not_in`. Values are `ACTIVE`, `INACTIVE`, `DRAFT`.", "schema": { "type": "object" } }, "ProgramsFilterCreatedAt": { "name": "filters[created_at][conditions]", "in": "query", "required": false, "description": "Filter by creation date. Supports conditions `$before`, `$after`, `$is`, `$more_than`, `$less_than`, `$has_value`, `$is_unknown`.", "schema": { "type": "object" } }, "ProgramsFilterJunction": { "name": "filters[junction]", "in": "query", "required": false, "description": "Logical junction for combining filters", "schema": { "type": "string", "enum": [ "AND", "OR" ] } }, "ProgramActivitiesOrder": { "name": "order", "in": "query", "required": false, "description": "Sort order for activities", "schema": { "oneOf": [ { "type": "string", "enum": [ "created_at", "-created_at" ] }, { "type": "array", "items": { "type": "string", "enum": [ "created_at", "-created_at" ] } } ] } }, "ProgramActivitiesCursor": { "name": "cursor", "in": "query", "required": false, "description": "Cursor for pagination (from previous response)", "schema": { "type": "string", "pattern": "^lcrsapr_[a-f0-9]+$" } }, "ProgramActivitiesFilterId": { "name": "filters[id][conditions]", "in": "query", "required": false, "description": "Filter by activity id. Supports conditions `$is`, `$is_not`, `$in`, `$not_in`.", "schema": { "type": "object" } }, "ProgramActivitiesFilterType": { "name": "filters[type][conditions]", "in": "query", "required": false, "description": "Filter by activity type. Supports conditions `$is`, `$is_not`, `$in`, `$not_in`.\nValid values: `vl.program.created`, `vl.program.updated`, `vl.program.deleted`,\n`vl.program.activated`, `vl.program.deactivated`,\n`vl.program.card_definition.assigned`, `vl.program.card_definition.unassigned`,\n`vl.program.earning_rule.assigned`, `vl.program.earning_rule.unassigned`,\n`vl.program.reward.assigned`, `vl.program.reward.unassigned`,\n`vl.program.tier_structure.assigned`, `vl.program.tier_structure.unassigned`\n", "schema": { "type": "object" } }, "ProgramActivitiesFilterCreatedAt": { "name": "filters[created_at][conditions]", "in": "query", "required": false, "description": "Filter by activity creation date.", "schema": { "type": "object" } }, "ProgramActivitiesFilterJunction": { "name": "filters[junction]", "in": "query", "required": false, "description": "Logical junction for combining activity filters", "schema": { "type": "string", "enum": [ "AND", "OR" ] } }, "CardDefinitionAssignmentsOrder": { "name": "order", "in": "query", "required": false, "description": "Sort order for card definition assignments", "schema": { "oneOf": [ { "type": "string", "enum": [ "-created_at", "created_at" ] }, { "type": "array", "items": { "type": "string", "enum": [ "-created_at", "created_at" ] } } ] } }, "CardDefinitionAssignmentsCursor": { "name": "cursor", "in": "query", "required": false, "description": "Cursor for pagination", "schema": { "type": "string", "pattern": "^lcrscdefa_[a-f0-9]+$" } }, "EarningRuleAssignmentsOrder": { "name": "order", "in": "query", "required": false, "description": "Sort order for earning rule assignments", "schema": { "oneOf": [ { "type": "string", "enum": [ "-created_at", "created_at" ] }, { "type": "array", "items": { "type": "string", "enum": [ "-created_at", "created_at" ] } } ] } }, "EarningRuleAssignmentsCursor": { "name": "cursor", "in": "query", "required": false, "description": "Cursor for pagination", "schema": { "type": "string", "pattern": "^lcrserna_[a-f0-9]+$" } }, "TierStructureAssignmentsOrder": { "name": "order", "in": "query", "required": false, "description": "Sort order for tier structure assignments", "schema": { "oneOf": [ { "type": "string", "enum": [ "-created_at", "created_at" ] }, { "type": "array", "items": { "type": "string", "enum": [ "-created_at", "created_at" ] } } ] } }, "TierStructureAssignmentsCursor": { "name": "cursor", "in": "query", "required": false, "description": "Cursor for pagination", "schema": { "type": "string", "pattern": "^lcrstsa_[a-f0-9]+$" } }, "RewardAssignmentsOrder": { "name": "order", "in": "query", "required": false, "description": "Sort order for reward assignments", "schema": { "oneOf": [ { "type": "string", "enum": [ "-created_at", "created_at" ] }, { "type": "array", "items": { "type": "string", "enum": [ "-created_at", "created_at" ] } } ] } }, "RewardAssignmentsCursor": { "name": "cursor", "in": "query", "required": false, "description": "Cursor for pagination", "schema": { "type": "string", "pattern": "^lcrsrewa_[a-f0-9]+$" } }, "MemberProgramId": { "name": "programId", "in": "path", "required": true, "description": "Unique program identifier", "schema": { "type": "string" } }, "MemberId": { "name": "memberId", "in": "path", "required": true, "description": "Unique member identifier", "schema": { "type": "string" } }, "CardId": { "name": "cardId", "in": "path", "required": true, "description": "Unique card identifier", "schema": { "type": "string" } }, "BucketId": { "name": "bucketId", "in": "path", "required": true, "description": "Unique bucket identifier (pending points or expiring points)", "schema": { "type": "string" } }, "EarningRuleId": { "name": "id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Unique earning rule identifier." }, "TierStructureId": { "name": "id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Unique tier structure identifier." }, "TierId": { "name": "tierId", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Unique tier identifier." }, "IncentiveId": { "name": "id", "in": "path", "required": true, "description": "Unique incentive identifier (prefix: `linc_`).", "schema": { "type": "string", "pattern": "^linc_[a-f0-9]+$", "example": "linc_abc123def456" } }, "IncentiveListLimit": { "name": "limit", "in": "query", "description": "Number of results per page (1–100, default 10).", "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 10 } }, "IncentiveListOrder": { "name": "order", "in": "query", "description": "Sort order. Prefix with `-` for descending. Accepted fields: `created_at`, `name`, `type`.\n", "schema": { "oneOf": [ { "type": "string", "enum": [ "-created_at", "created_at", "name", "-name", "-type", "type" ] }, { "type": "array", "items": { "type": "string", "enum": [ "-created_at", "created_at", "name", "-name", "-type", "type" ] } } ] } }, "IncentiveListCursor": { "name": "cursor", "in": "query", "description": "Cursor token for the next page (prefix: `lcrsinc_`).", "schema": { "type": "string", "pattern": "^lcrsinc_[a-f0-9]+$" } }, "IncentiveActivitiesLimit": { "name": "limit", "in": "query", "description": "Number of results per page (1–100, default 10).", "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 10 } }, "IncentiveActivitiesOrder": { "name": "order", "in": "query", "description": "Sort order for activities. Default: `-created_at`.", "schema": { "oneOf": [ { "type": "string", "enum": [ "created_at", "-created_at" ] }, { "type": "array", "items": { "type": "string", "enum": [ "created_at", "-created_at" ] } } ] } }, "IncentiveActivitiesCursor": { "name": "cursor", "in": "query", "description": "Cursor token for the next page of activities (prefix: `lcrsainc_`).", "schema": { "type": "string", "pattern": "^lcrsainc_[a-f0-9]+$" } }, "RewardId": { "name": "id", "in": "path", "required": true, "description": "Unique reward identifier.", "schema": { "type": "string" } }, "RewardQueryLimit": { "name": "limit", "in": "query", "required": false, "description": "Maximum number of results to return (1–100, default 10).", "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 10 } }, "RewardQueryCursor": { "name": "cursor", "in": "query", "required": false, "description": "Pagination cursor returned from a previous response.", "schema": { "type": "string" } } }, "responses": { "BadRequest": { "description": "Validation error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "NotFound": { "description": "Resource not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "ResourceLocked": { "description": "Resource is locked (in use by another resource)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "InternalServerError": { "description": "Internal server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "Conflict": { "description": "Resource locked or invalid state transition", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "example": { "code": 409, "key": "non_draft_program", "message": "Invalid vl_program status", "details": "Cannot modify card definition assignment when program status is not DRAFT" } } } }, "ResourceInUse": { "description": "Resource is in use and cannot be deleted.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ResourceInUseErrorResponse" }, "example": { "code": 409, "key": "resource_in_use", "message": "Resource in use", "resource_id": "linc_abc123", "resource_type": "vl_incentive", "related_object_ids": [ "lern_def456" ], "related_object_type": "earning_rule" } } } }, "InvalidStateTransition": { "description": "The requested state transition is not valid from the current state.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "example": { "code": 400, "key": "invalid_state_transition", "message": "Invalid state transition", "details": "Cannot activate incentive from current state: 'ACTIVE'", "request_id": "v-abc123" } } } } }, "schemas": { "CardDefinitionListResponse": { "type": "object", "properties": { "object": { "type": "string", "const": "list" }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/CardDefinitionResponse" } }, "cursor": { "oneOf": [ { "$ref": "#/components/schemas/PaginationCursor" }, { "type": "null" } ] } }, "required": [ "object", "data", "cursor" ] }, "CardDefinitionActivityListResponse": { "type": "object", "properties": { "object": { "type": "string", "const": "list" }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/CardDefinitionActivityResponse" } }, "cursor": { "oneOf": [ { "$ref": "#/components/schemas/PaginationCursor" }, { "type": "null" } ] } }, "required": [ "object", "data", "cursor" ] }, "PaginationCursor": { "type": "object", "description": "Cursor for fetching the next page of results.", "properties": { "next": { "type": "string", "description": "Cursor token to pass as the `cursor` query parameter for the next page." }, "expires_at": { "type": "string", "format": "date-time", "description": "ISO 8601 timestamp when this cursor expires." } }, "required": [ "next", "expires_at" ] }, "CardDefinitionResponse": { "type": "object", "description": "Full card definition DTO returned by all CRUD endpoints.", "properties": { "id": { "type": "string" }, "name": { "type": "string" }, "type": { "type": "string", "enum": [ "INDIVIDUAL" ] }, "status": { "type": "string", "enum": [ "DRAFT", "ACTIVE", "INACTIVE", "DELETED" ] }, "code_config": { "$ref": "#/components/schemas/CodeConfigDTO" }, "points_expiration": { "$ref": "#/components/schemas/PointsExpirationDTO" }, "pending_points": { "$ref": "#/components/schemas/PendingPointsDTO" }, "earning_limits": { "$ref": "#/components/schemas/EarningLimitsDTO" }, "spending_limits": { "$ref": "#/components/schemas/SpendingLimitsDTO" }, "refunds": { "$ref": "#/components/schemas/RefundsDTO" }, "balance_settings": { "$ref": "#/components/schemas/BalanceSettingsDTO" }, "metadata": { "type": "object", "additionalProperties": true }, "created_at": { "type": "string", "format": "date-time" }, "updated_at": { "type": [ "string", "null" ], "format": "date-time" }, "object": { "type": "string", "const": "card_definition" } }, "required": [ "id", "name", "type", "status", "code_config", "points_expiration", "pending_points", "earning_limits", "spending_limits", "refunds", "balance_settings", "metadata", "created_at", "object" ] }, "CodeConfigDTO": { "type": "object", "properties": { "pattern": { "type": "string", "description": "Code pattern using `#` as placeholder for random characters. Default: 10 `#` characters." }, "length": { "type": "integer", "description": "Number of random characters in the pattern." }, "charset": { "type": "string", "description": "Characters used for code generation. Default: alphanumeric (0-9a-zA-Z)." }, "prefix": { "type": "string", "description": "Prefix prepended to generated codes." }, "postfix": { "type": "string", "description": "Postfix appended to generated codes." } }, "required": [ "pattern", "length", "charset", "prefix", "postfix" ] }, "PointsExpirationDTO": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "NO_EXPIRATION", "ROLLING_EXPIRATION", "CALENDAR_EXPIRATION", "SLIDING_EXPIRATION" ] }, "rolling_expiration": { "oneOf": [ { "$ref": "#/components/schemas/RollingExpirationDTO" }, { "type": "null" } ] }, "calendar_expiration": { "oneOf": [ { "$ref": "#/components/schemas/CalendarExpirationDTO" }, { "type": "null" } ] }, "sliding_expiration": { "oneOf": [ { "$ref": "#/components/schemas/SlidingExpirationDTO" }, { "type": "null" } ] } }, "required": [ "type" ] }, "RollingExpirationDTO": { "type": "object", "properties": { "period": { "$ref": "#/components/schemas/PeriodValueUnitDTO" }, "rounding": { "oneOf": [ { "$ref": "#/components/schemas/RollingRoundingDTO" }, { "type": "null" } ] } }, "required": [ "period" ] }, "RollingRoundingDTO": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "END_OF_MONTH", "END_OF_QUARTER", "END_OF_HALF_YEAR", "END_OF_YEAR", "END_OF_PARTICULAR_MONTH" ] }, "value": { "type": [ "integer", "null" ], "description": "Required and between 1-12 when type is `END_OF_PARTICULAR_MONTH`. Must be null otherwise.", "minimum": 1, "maximum": 12 } }, "required": [ "type" ] }, "CalendarExpirationDTO": { "type": "object", "properties": { "expiration_dates": { "type": "array", "items": { "$ref": "#/components/schemas/DayMonthDTO" } } }, "required": [ "expiration_dates" ] }, "SlidingExpirationDTO": { "type": "object", "properties": { "earning_activity": { "type": "boolean" }, "spending_activity": { "type": "boolean" }, "custom_activity": { "type": "boolean" }, "custom_activity_types": { "type": "array", "items": { "type": "string" }, "description": "Custom event type IDs that reset the sliding window." }, "period": { "$ref": "#/components/schemas/PeriodValueUnitDTO" } }, "required": [ "earning_activity", "spending_activity", "custom_activity", "custom_activity_types", "period" ] }, "PendingPointsDTO": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "IMMEDIATE", "PERIOD_BASED", "FIXED_DATES", "EVENT_BASED" ] }, "period_based": { "oneOf": [ { "$ref": "#/components/schemas/PendingPointsPeriodBasedDTO" }, { "type": "null" } ] }, "fixed_dates": { "oneOf": [ { "$ref": "#/components/schemas/PendingPointsFixedDatesDTO" }, { "type": "null" } ] }, "event_based": { "oneOf": [ { "$ref": "#/components/schemas/PendingPointsEventBasedDTO" }, { "type": "null" } ] } }, "required": [ "type" ] }, "PendingPointsPeriodBasedDTO": { "type": "object", "properties": { "period": { "$ref": "#/components/schemas/PeriodValueUnitDTO" } }, "required": [ "period" ] }, "PendingPointsFixedDatesDTO": { "type": "object", "properties": { "dates": { "type": "array", "items": { "$ref": "#/components/schemas/DayMonthDTO" } } }, "required": [ "dates" ] }, "PendingPointsEventBasedDTO": { "type": "object", "properties": { "event_types": { "type": "array", "items": { "type": "string" }, "description": "Custom event type IDs that trigger point activation." }, "cancel_period": { "$ref": "#/components/schemas/PeriodValueUnitDTO" } }, "required": [ "event_types", "cancel_period" ] }, "EarningLimitsDTO": { "type": "object", "properties": { "global": { "$ref": "#/components/schemas/EarningLimitsGlobalDTO" }, "transactions": { "$ref": "#/components/schemas/EarningLimitsTransactionsDTO" } }, "required": [ "global", "transactions" ] }, "EarningLimitsGlobalDTO": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "NO_LIMIT", "LIMITED" ] }, "limits": { "type": "array", "items": { "$ref": "#/components/schemas/EarningLimitsGlobalLimitDTO" } } }, "required": [ "type", "limits" ] }, "EarningLimitsGlobalLimitDTO": { "type": "object", "description": "Discriminated by `type`. Either `BALANCE_BASED` (with `max`) or `TIME_BASED` (with `period` and `points`).", "properties": { "type": { "type": "string", "enum": [ "BALANCE_BASED", "TIME_BASED" ] }, "max": { "type": "integer", "minimum": 1, "description": "Maximum balance. Present when type is `BALANCE_BASED`." }, "period": { "$ref": "#/components/schemas/EarningLimitsTimeBasedPeriodDTO" }, "points": { "$ref": "#/components/schemas/PointsMaxDTO" } }, "required": [ "type" ] }, "EarningLimitsTimeBasedPeriodDTO": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "CURRENT_PERIOD" ] }, "current_period": { "oneOf": [ { "$ref": "#/components/schemas/CurrentPeriodDTO" }, { "type": "null" } ] } }, "required": [ "type" ] }, "CurrentPeriodDTO": { "type": "object", "properties": { "unit": { "type": "string", "enum": [ "DAY", "WEEK", "MONTH", "QUARTER", "YEAR" ] } }, "required": [ "unit" ] }, "PointsMaxDTO": { "type": "object", "properties": { "max": { "type": "integer", "minimum": 1, "maximum": 2147483647 } }, "required": [ "max" ] }, "EarningLimitsTransactionsDTO": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "NO_LIMIT", "LIMITED" ] }, "limits": { "type": "array", "items": { "$ref": "#/components/schemas/EarningLimitsTransactionsLimitDTO" } } }, "required": [ "type", "limits" ] }, "EarningLimitsTransactionsLimitDTO": { "type": "object", "description": "Discriminated by `type`. Either `POINTS` (with `max`) or `SPENDING` (with `min_amount`).", "properties": { "type": { "type": "string", "enum": [ "POINTS", "SPENDING" ] }, "max": { "type": "integer", "minimum": 1, "description": "Maximum points per transaction. Present when type is `POINTS`." }, "min_amount": { "type": "integer", "minimum": 1, "description": "Minimum spending amount required to earn points. Present when type is `SPENDING`." } }, "required": [ "type" ] }, "SpendingLimitsDTO": { "type": "object", "properties": { "global": { "$ref": "#/components/schemas/SpendingLimitsGlobalDTO" }, "transactions": { "$ref": "#/components/schemas/SpendingLimitsTransactionsDTO" } }, "required": [ "global", "transactions" ] }, "SpendingLimitsGlobalDTO": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "NO_LIMIT", "LIMITED" ] }, "limits": { "type": "array", "items": { "$ref": "#/components/schemas/SpendingLimitsGlobalLimitDTO" } } }, "required": [ "type", "limits" ] }, "SpendingLimitsGlobalLimitDTO": { "type": "object", "description": "Discriminated by `type`. Either `SPENDING_BASED` (with `max`) or `TIME_BASED` (with `period` and `points`).", "properties": { "type": { "type": "string", "enum": [ "SPENDING_BASED", "TIME_BASED" ] }, "max": { "type": "integer", "minimum": 1, "description": "Maximum spending points. Present when type is `SPENDING_BASED`." }, "period": { "$ref": "#/components/schemas/SpendingLimitsTimeBasedPeriodDTO" }, "points": { "$ref": "#/components/schemas/PointsMaxDTO" } }, "required": [ "type" ] }, "SpendingLimitsTimeBasedPeriodDTO": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "CURRENT_PERIOD" ] }, "current_period": { "oneOf": [ { "$ref": "#/components/schemas/SpendingCurrentPeriodDTO" }, { "type": "null" } ] } }, "required": [ "type" ] }, "SpendingCurrentPeriodDTO": { "type": "object", "properties": { "unit": { "type": "string", "enum": [ "DAY", "WEEK", "MONTH", "QUARTER", "YEAR" ] } }, "required": [ "unit" ] }, "SpendingLimitsTransactionsDTO": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "NO_LIMIT", "LIMITED" ] }, "limits": { "type": "array", "items": { "$ref": "#/components/schemas/SpendingLimitsTransactionsLimitDTO" } } }, "required": [ "type", "limits" ] }, "SpendingLimitsTransactionsLimitDTO": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "POINTS" ] }, "max": { "type": "integer", "minimum": 1, "description": "Maximum points per spending transaction." } }, "required": [ "type", "max" ] }, "RefundsDTO": { "type": "object", "properties": { "spent_points": { "$ref": "#/components/schemas/RefundsSpentPointsDTO" }, "earned_points": { "$ref": "#/components/schemas/RefundsEarnedPointsDTO" } }, "required": [ "spent_points", "earned_points" ] }, "RefundsSpentPointsDTO": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "NONE", "REFUNDABLE" ] }, "methods": { "type": "array", "items": { "$ref": "#/components/schemas/RefundsSpentPointsMethodDTO" } } }, "required": [ "type", "methods" ] }, "RefundsSpentPointsMethodDTO": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "RETURN_POINTS" ] }, "mode": { "type": "string", "enum": [ "REFUND_ALL", "REFUND_ITEM", "REFUND_AMOUNT" ] } }, "required": [ "type", "mode" ] }, "RefundsEarnedPointsDTO": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "NONE", "REFUNDABLE" ] }, "methods": { "type": "array", "items": { "$ref": "#/components/schemas/RefundsEarnedPointsMethodDTO" } } }, "required": [ "type", "methods" ] }, "RefundsEarnedPointsMethodDTO": { "type": "object", "description": "Discriminated by `type`. `REVOKE_FROM_PENDING` has no extra fields. `REVOKE_FROM_BALANCE` includes `mode`.", "properties": { "type": { "type": "string", "enum": [ "REVOKE_FROM_PENDING", "REVOKE_FROM_BALANCE" ] }, "mode": { "type": "string", "enum": [ "REVOKE_TO_ZERO", "REVOKE_BELOW_ZERO" ], "description": "Present only when type is `REVOKE_FROM_BALANCE`." } }, "required": [ "type" ] }, "BalanceSettingsDTO": { "type": "object", "properties": { "allow_negative": { "type": "boolean", "description": "Whether the card balance can go below zero. Can only be `true` when `points_expiration.type` is `NO_EXPIRATION`." } }, "required": [ "allow_negative" ] }, "PeriodValueUnitDTO": { "type": "object", "properties": { "value": { "type": "integer", "minimum": 1 }, "unit": { "type": "string", "enum": [ "DAY", "MONTH", "YEAR" ] } }, "required": [ "value", "unit" ] }, "DayMonthDTO": { "type": "object", "properties": { "day": { "type": "integer", "minimum": 1, "maximum": 31 }, "month": { "type": "integer", "minimum": 1, "maximum": 12 } }, "required": [ "day", "month" ] }, "CardDefinitionActivityResponse": { "type": "object", "properties": { "id": { "type": "string" }, "card_definition_id": { "type": "string" }, "type": { "type": "string", "enum": [ "vl.card_definition.created", "vl.card_definition.updated", "vl.card_definition.deleted", "vl.card_definition.activated", "vl.card_definition.deactivated", "vl.card_definition.drafted", "vl.card_definition.assigned", "vl.card_definition.unassigned" ] }, "data": { "type": "object", "description": "Activity-specific data payload. Always includes `card_definition`. For `assigned`/`unassigned` types, also includes `program` and `program_card_definition`.", "properties": { "card_definition": { "$ref": "#/components/schemas/CardDefinitionResponse" } }, "required": [ "card_definition" ] }, "created_at": { "type": "string", "format": "date-time" }, "group_id": { "type": "string" }, "source": { "oneOf": [ { "$ref": "#/components/schemas/ActivitySource" }, { "type": "null" } ] } }, "required": [ "id", "card_definition_id", "type", "data", "created_at" ] }, "ActivitySource": { "type": "object", "description": "Source information for an activity.", "properties": { "channel": { "type": "string", "enum": [ "USER_PORTAL", "API", "CLIENT_API", "INTERNAL" ], "description": "Channel through which the activity was triggered." }, "user": { "type": "object", "properties": { "id": { "type": "string", "description": "User identifier." } } }, "api_key": { "type": "object", "properties": { "name": { "type": "string" }, "app_id": { "type": "string" }, "client_app_id": { "type": "string" } } } } }, "CardDefinitionCreateRequest": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 200 }, "type": { "type": "string", "enum": [ "INDIVIDUAL" ] }, "status": { "type": [ "string", "null" ], "enum": [ "DRAFT", "ACTIVE", null ], "default": "DRAFT", "description": "Initial status. Defaults to `DRAFT` if not provided." }, "code_config": { "oneOf": [ { "$ref": "#/components/schemas/CodeConfigRequest" }, { "type": "null" } ], "description": "Code generation configuration. Defaults to 10-character alphanumeric pattern if not provided." }, "points_expiration": { "oneOf": [ { "$ref": "#/components/schemas/PointsExpirationRequest" }, { "type": "null" } ], "description": "Points expiration policy. Defaults to `NO_EXPIRATION`." }, "pending_points": { "oneOf": [ { "$ref": "#/components/schemas/PendingPointsRequest" }, { "type": "null" } ], "description": "Pending points policy. Defaults to `IMMEDIATE`." }, "earning_limits": { "oneOf": [ { "$ref": "#/components/schemas/EarningLimitsRequest" }, { "type": "null" } ], "description": "Earning limits configuration. Defaults to no limits." }, "spending_limits": { "oneOf": [ { "$ref": "#/components/schemas/SpendingLimitsRequest" }, { "type": "null" } ], "description": "Spending limits configuration. Defaults to no limits." }, "refunds": { "oneOf": [ { "$ref": "#/components/schemas/RefundsRequest" }, { "type": "null" } ], "description": "Refund policies. Defaults to no refunds." }, "balance_settings": { "oneOf": [ { "$ref": "#/components/schemas/BalanceSettingsRequest" }, { "type": "null" } ], "description": "Balance settings. Defaults to `allow_negative: false`." }, "metadata": { "oneOf": [ { "type": "object", "additionalProperties": true }, { "type": "null" } ] } }, "required": [ "name", "type" ], "additionalProperties": false }, "CardDefinitionUpdateRequest": { "type": "object", "description": "All properties are optional. At least one must be provided. When status is not `DRAFT`, only `name` and `metadata` can be updated.", "properties": { "name": { "type": [ "string", "null" ], "minLength": 1, "maxLength": 200 }, "code_config": { "oneOf": [ { "$ref": "#/components/schemas/CodeConfigRequest" }, { "type": "null" } ] }, "points_expiration": { "oneOf": [ { "$ref": "#/components/schemas/PointsExpirationRequest" }, { "type": "null" } ] }, "pending_points": { "oneOf": [ { "$ref": "#/components/schemas/PendingPointsRequest" }, { "type": "null" } ] }, "earning_limits": { "oneOf": [ { "$ref": "#/components/schemas/EarningLimitsRequest" }, { "type": "null" } ] }, "spending_limits": { "oneOf": [ { "$ref": "#/components/schemas/SpendingLimitsRequest" }, { "type": "null" } ] }, "refunds": { "oneOf": [ { "$ref": "#/components/schemas/RefundsRequest" }, { "type": "null" } ] }, "balance_settings": { "oneOf": [ { "$ref": "#/components/schemas/BalanceSettingsRequest" }, { "type": "null" } ] }, "metadata": { "oneOf": [ { "type": "object", "additionalProperties": true }, { "type": "null" } ] } }, "additionalProperties": false }, "CodeConfigRequest": { "type": "object", "description": "Code generation configuration. If not provided on create, defaults to a 10-character alphanumeric pattern.", "properties": { "length": { "type": [ "integer", "null" ], "description": "Number of random characters. Mutually derived with `pattern`." }, "charset": { "type": [ "string", "null" ], "description": "Character set for code generation." }, "prefix": { "type": [ "string", "null" ] }, "postfix": { "type": [ "string", "null" ] }, "pattern": { "type": [ "string", "null" ], "description": "Code pattern with `#` placeholders for random characters." } }, "additionalProperties": false }, "PointsExpirationRequest": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "NO_EXPIRATION", "ROLLING_EXPIRATION", "CALENDAR_EXPIRATION", "SLIDING_EXPIRATION" ] }, "rolling_expiration": { "oneOf": [ { "$ref": "#/components/schemas/RollingExpirationRequest" }, { "type": "null" } ], "description": "Required when type is `ROLLING_EXPIRATION`. Must be null otherwise." }, "calendar_expiration": { "oneOf": [ { "$ref": "#/components/schemas/CalendarExpirationRequest" }, { "type": "null" } ], "description": "Required when type is `CALENDAR_EXPIRATION`. Must be null otherwise." }, "sliding_expiration": { "oneOf": [ { "$ref": "#/components/schemas/SlidingExpirationRequest" }, { "type": "null" } ], "description": "Required when type is `SLIDING_EXPIRATION`. Must be null otherwise." } }, "required": [ "type" ], "additionalProperties": false }, "RollingExpirationRequest": { "type": "object", "properties": { "period": { "$ref": "#/components/schemas/RollingExpirationPeriodRequest" }, "rounding": { "oneOf": [ { "$ref": "#/components/schemas/RollingRoundingRequest" }, { "type": "null" } ] } }, "required": [ "period" ], "additionalProperties": false }, "RollingExpirationPeriodRequest": { "type": "object", "description": "Max values vary by unit: DAY=90, MONTH=12, YEAR=5.", "properties": { "unit": { "type": "string", "enum": [ "DAY", "MONTH", "YEAR" ] }, "value": { "type": "integer", "minimum": 1 } }, "required": [ "unit", "value" ], "additionalProperties": false }, "RollingRoundingRequest": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "END_OF_MONTH", "END_OF_QUARTER", "END_OF_HALF_YEAR", "END_OF_YEAR", "END_OF_PARTICULAR_MONTH" ] }, "value": { "oneOf": [ { "type": "integer", "minimum": 1, "maximum": 12 }, { "type": "null" } ], "description": "Required (1-12) when type is `END_OF_PARTICULAR_MONTH`. Must be null for other types." } }, "required": [ "type" ], "additionalProperties": false }, "CalendarExpirationRequest": { "type": "object", "properties": { "expiration_dates": { "type": "array", "items": { "$ref": "#/components/schemas/DayMonthRequest" }, "minItems": 1, "maxItems": 20 } }, "required": [ "expiration_dates" ], "additionalProperties": false }, "SlidingExpirationRequest": { "type": "object", "description": "At least one of `earning_activity`, `spending_activity`, or `custom_activity` must be `true`. When `custom_activity` is `true`, `custom_activity_types` is required with 1-10 unique items.", "properties": { "earning_activity": { "type": "boolean" }, "spending_activity": { "type": "boolean" }, "custom_activity": { "type": "boolean" }, "custom_activity_types": { "oneOf": [ { "type": "array", "items": { "type": "string" }, "minItems": 1, "maxItems": 10 }, { "type": "null" } ] }, "period": { "$ref": "#/components/schemas/SlidingExpirationPeriodRequest" } }, "required": [ "period" ], "additionalProperties": false }, "SlidingExpirationPeriodRequest": { "type": "object", "description": "Max values vary by unit: DAY=90, MONTH=12, YEAR=1.", "properties": { "value": { "type": "integer", "minimum": 1 }, "unit": { "type": "string", "enum": [ "DAY", "MONTH", "YEAR" ] } }, "required": [ "value", "unit" ], "additionalProperties": false }, "PendingPointsRequest": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "IMMEDIATE", "PERIOD_BASED", "FIXED_DATES", "EVENT_BASED" ] }, "period_based": { "oneOf": [ { "$ref": "#/components/schemas/PendingPointsPeriodBasedRequest" }, { "type": "null" } ], "description": "Required when type is `PERIOD_BASED`. Must be null otherwise." }, "fixed_dates": { "oneOf": [ { "$ref": "#/components/schemas/PendingPointsFixedDatesRequest" }, { "type": "null" } ], "description": "Required when type is `FIXED_DATES`. Must be null otherwise." }, "event_based": { "oneOf": [ { "$ref": "#/components/schemas/PendingPointsEventBasedRequest" }, { "type": "null" } ], "description": "Required when type is `EVENT_BASED`. Must be null otherwise." } }, "required": [ "type" ], "additionalProperties": false }, "PendingPointsPeriodBasedRequest": { "type": "object", "properties": { "period": { "$ref": "#/components/schemas/PendingPointsPeriodRequest" } }, "required": [ "period" ], "additionalProperties": false }, "PendingPointsPeriodRequest": { "type": "object", "description": "Max values vary by unit: DAY=90, MONTH=12, YEAR=1.", "properties": { "unit": { "type": "string", "enum": [ "DAY", "MONTH", "YEAR" ] }, "value": { "type": "integer", "minimum": 1 } }, "required": [ "unit", "value" ], "additionalProperties": false }, "PendingPointsFixedDatesRequest": { "type": "object", "properties": { "dates": { "type": "array", "items": { "$ref": "#/components/schemas/DayMonthRequest" }, "minItems": 1, "maxItems": 20 } }, "required": [ "dates" ], "additionalProperties": false }, "PendingPointsEventBasedRequest": { "type": "object", "properties": { "event_types": { "type": "array", "items": { "type": "string" }, "minItems": 1, "maxItems": 10, "description": "Unique custom event type IDs." }, "cancel_period": { "$ref": "#/components/schemas/EventBasedCancelPeriodRequest" } }, "required": [ "event_types", "cancel_period" ], "additionalProperties": false }, "EventBasedCancelPeriodRequest": { "type": "object", "description": "Max values vary by unit: DAY=90, MONTH=12, YEAR=1.", "properties": { "value": { "type": "integer", "minimum": 1 }, "unit": { "type": "string", "enum": [ "DAY", "MONTH", "YEAR" ] } }, "required": [ "value", "unit" ], "additionalProperties": false }, "EarningLimitsRequest": { "type": "object", "properties": { "global": { "$ref": "#/components/schemas/EarningLimitsGlobalRequest" }, "transactions": { "$ref": "#/components/schemas/EarningLimitsTransactionsRequest" } }, "required": [ "global", "transactions" ], "additionalProperties": false }, "EarningLimitsGlobalRequest": { "type": "object", "description": "When `NO_LIMIT`, limits must be empty or null. When `LIMITED`, exactly 1 limit is required.", "properties": { "type": { "type": "string", "enum": [ "NO_LIMIT", "LIMITED" ] }, "limits": { "oneOf": [ { "type": "null" }, { "type": "array", "items": { "$ref": "#/components/schemas/EarningLimitsGlobalLimitRequest" }, "minItems": 0, "maxItems": 1 } ] } }, "required": [ "type" ], "additionalProperties": false }, "EarningLimitsGlobalLimitRequest": { "type": "object", "description": "Discriminated union on `type`. `BALANCE_BASED` requires `max`. `TIME_BASED` requires `period` and `points`.", "properties": { "type": { "type": "string", "enum": [ "BALANCE_BASED", "TIME_BASED" ] }, "max": { "type": "integer", "minimum": 1, "description": "Required when type is `BALANCE_BASED`." }, "period": { "$ref": "#/components/schemas/EarningLimitsGlobalTimeBasedPeriodRequest" }, "points": { "$ref": "#/components/schemas/EarningLimitsGlobalTimeBasedPointsRequest" } }, "required": [ "type" ] }, "EarningLimitsGlobalTimeBasedPeriodRequest": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "CURRENT_PERIOD" ] }, "current_period": { "oneOf": [ { "$ref": "#/components/schemas/EarningLimitsCurrentPeriodRequest" }, { "type": "null" } ], "description": "Required when type is `CURRENT_PERIOD`." } }, "required": [ "type" ], "additionalProperties": false }, "EarningLimitsCurrentPeriodRequest": { "type": "object", "properties": { "unit": { "type": "string", "enum": [ "DAY", "WEEK", "MONTH", "QUARTER", "YEAR" ] } }, "required": [ "unit" ], "additionalProperties": false }, "EarningLimitsGlobalTimeBasedPointsRequest": { "type": "object", "properties": { "max": { "type": "integer", "minimum": 1, "maximum": 2147483647 } }, "required": [ "max" ], "additionalProperties": false }, "EarningLimitsTransactionsRequest": { "type": "object", "description": "When `NO_LIMIT`, limits must be empty or null. When `LIMITED`, at least 1 limit is required with unique types.", "properties": { "type": { "type": "string", "enum": [ "NO_LIMIT", "LIMITED" ] }, "limits": { "oneOf": [ { "type": "null" }, { "type": "array", "items": { "$ref": "#/components/schemas/EarningLimitsTransactionsLimitRequest" }, "minItems": 0 } ] } }, "required": [ "type" ], "additionalProperties": false }, "EarningLimitsTransactionsLimitRequest": { "type": "object", "description": "Discriminated union on `type`. `POINTS` requires `max`. `SPENDING` requires `min_amount`.", "properties": { "type": { "type": "string", "enum": [ "POINTS", "SPENDING" ] }, "max": { "type": "integer", "minimum": 1, "description": "Required when type is `POINTS`." }, "min_amount": { "type": "integer", "minimum": 1, "description": "Required when type is `SPENDING`." } }, "required": [ "type" ] }, "LoyaltiesExamineEarningRulesRequestBody": { "type": "object", "required": [ "event", "customer_identification" ], "properties": { "event": { "type": "string", "description": "Trigger event. Currently supported: `customer.order.paid` or `order.paid`.", "example": "customer.order.paid" }, "customer_identification": { "$ref": "#/components/schemas/VLExamineCustomerIdentification" }, "customer_order_paid": { "$ref": "#/components/schemas/VLExamineCustomerOrderPaid" } } }, "VLExamineCustomerIdentification": { "type": "object", "description": "Discriminated union identifying who is being evaluated.", "required": [ "type" ], "properties": { "type": { "type": "string", "enum": [ "customer_id", "customer_source_id", "member_id" ], "description": "Determines which ID field is evaluated and required." }, "customer_id": { "type": "string", "description": "Internal customer ID (cust_*). Evaluates all programs." }, "customer_source_id": { "type": "string", "description": "External customer source ID. Evaluates all programs." }, "member_id": { "type": "string", "description": "Internal member ID (mloy_*). Scopes to a single program." } } }, "VLExamineCustomerOrderPaid": { "type": "object", "description": "Event-specific payload for customer.order.paid containing context for rule evaluation.", "properties": { "customer": { "type": "object", "properties": { "metadata": { "type": "object", "description": "Customer metadata overlay (merged onto the resolved customer, not persisted)." } } }, "member": { "type": "object", "description": "Member metadata overlay. Only allowed when customer_identification.type is member_id.", "properties": { "metadata": { "type": "object" } } }, "order": { "$ref": "#/components/schemas/VLExamineOrderParams" } } }, "VLExamineOrderParams": { "type": "object", "properties": { "amount": { "type": "integer", "description": "Post-discount order amount (cents)." }, "initial_amount": { "type": "integer", "description": "Pre-discount order amount (cents)." }, "discount_amount": { "type": "integer", "description": "Total discount amount (cents)." }, "metadata": { "type": "object", "description": "Order metadata for rule evaluation." }, "items": { "type": "array", "items": { "$ref": "#/components/schemas/VLExamineOrderItemParams" } } } }, "VLExamineOrderItemParams": { "type": "object", "properties": { "id": { "type": "string" }, "source_id": { "type": "string" }, "product_id": { "type": "string" }, "sku_id": { "type": "string" }, "related_object": { "type": "string", "enum": [ "product", "sku" ] }, "amount": { "type": "integer" }, "discount_amount": { "type": "integer" }, "quantity": { "type": "integer" }, "price": { "type": "integer" }, "product": { "type": "object", "properties": { "id": { "type": "string" }, "source_id": { "type": "string" }, "price": { "type": "integer" } } }, "sku": { "type": "object", "properties": { "id": { "type": "string" }, "source_id": { "type": "string" }, "price": { "type": "integer" } } }, "metadata": { "type": "object" } } }, "LoyaltiesExamineEarningRulesResponseBody": { "type": "object", "properties": { "event": { "type": "string", "description": "The trigger event that was examined." }, "memberships": { "type": "array", "description": "List of earning opportunities per active membership.", "items": { "$ref": "#/components/schemas/VLExamineMemberEarningOpportunity" } }, "object": { "type": "string", "example": "earnings_examine_result" } } }, "VLExamineMemberEarningOpportunity": { "type": "object", "properties": { "member": { "$ref": "#/components/schemas/MemberResponse" }, "program": { "$ref": "#/components/schemas/ProgramResponse" }, "cards": { "type": "array", "description": "Per-card point estimations.", "items": { "$ref": "#/components/schemas/VLExamineCardEstimation" } }, "incentives": { "type": "array", "description": "Fulfillable incentives (digital, material).", "items": { "$ref": "#/components/schemas/LoyaltyIncentive" } }, "object": { "type": "string", "example": "member_earning_opportunity" } } }, "VLExamineCardEstimation": { "type": "object", "properties": { "card": { "$ref": "#/components/schemas/VLCardReference" }, "points_estimation": { "type": "integer", "description": "Total estimated points for this card (fixed + proportional + incentive points combined)." } } }, "VLCardReference": { "type": "object", "properties": { "id": { "type": "string" }, "card_definition_id": { "type": "string", "description": "Card definition identifier" }, "card_type": { "type": "string", "description": "Type of the card definition" }, "code": { "type": "string", "description": "Card code." }, "object": { "type": "string", "const": "card" } } }, "LoyaltyIncentive": { "type": "object", "properties": { "id": { "type": "string" }, "name": { "type": "string" }, "type": { "type": "string", "enum": [ "DIGITAL", "MATERIAL", "POINTS" ] }, "status": { "type": "string" }, "object": { "type": "string", "example": "incentive" } } }, "SpendingLimitsRequest": { "type": "object", "properties": { "global": { "$ref": "#/components/schemas/SpendingLimitsGlobalRequest" }, "transactions": { "$ref": "#/components/schemas/SpendingLimitsTransactionsRequest" } }, "required": [ "global", "transactions" ], "additionalProperties": false }, "SpendingLimitsGlobalRequest": { "type": "object", "description": "When `NO_LIMIT`, limits must be empty or null. When `LIMITED`, at least 1 limit is required with unique types.", "properties": { "type": { "type": "string", "enum": [ "NO_LIMIT", "LIMITED" ] }, "limits": { "oneOf": [ { "type": "null" }, { "type": "array", "items": { "$ref": "#/components/schemas/SpendingLimitsGlobalLimitRequest" }, "minItems": 0, "maxItems": 1 } ] } }, "required": [ "type" ], "additionalProperties": false }, "SpendingLimitsGlobalLimitRequest": { "type": "object", "description": "Discriminated union on `type`. `SPENDING_BASED` requires `max`. `TIME_BASED` requires `period` and `points`.", "properties": { "type": { "type": "string", "enum": [ "SPENDING_BASED", "TIME_BASED" ] }, "max": { "type": "integer", "minimum": 1, "description": "Required when type is `SPENDING_BASED`." }, "period": { "$ref": "#/components/schemas/SpendingLimitsGlobalTimeBasedPeriodRequest" }, "points": { "$ref": "#/components/schemas/SpendingLimitsGlobalTimeBasedPointsRequest" } }, "required": [ "type" ] }, "SpendingLimitsGlobalTimeBasedPeriodRequest": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "CURRENT_PERIOD" ] }, "current_period": { "oneOf": [ { "$ref": "#/components/schemas/SpendingLimitsCurrentPeriodRequest" }, { "type": "null" } ], "description": "Required when type is `CURRENT_PERIOD`." } }, "required": [ "type" ], "additionalProperties": false }, "SpendingLimitsCurrentPeriodRequest": { "type": "object", "properties": { "unit": { "type": "string", "enum": [ "DAY", "WEEK", "MONTH", "QUARTER", "YEAR" ] } }, "required": [ "unit" ], "additionalProperties": false }, "SpendingLimitsGlobalTimeBasedPointsRequest": { "type": "object", "properties": { "max": { "type": "integer", "minimum": 1, "maximum": 2147483647 } }, "required": [ "max" ], "additionalProperties": false }, "SpendingLimitsTransactionsRequest": { "type": "object", "description": "When `NO_LIMIT`, limits must be empty or null. When `LIMITED`, exactly 1 limit is required.", "properties": { "type": { "type": "string", "enum": [ "NO_LIMIT", "LIMITED" ] }, "limits": { "oneOf": [ { "type": "null" }, { "type": "array", "items": { "$ref": "#/components/schemas/SpendingLimitsTransactionsLimitRequest" }, "minItems": 0, "maxItems": 1 } ] } }, "required": [ "type" ], "additionalProperties": false }, "SpendingLimitsTransactionsLimitRequest": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "POINTS" ] }, "max": { "type": "integer", "minimum": 1 } }, "required": [ "type", "max" ], "additionalProperties": false }, "RefundsRequest": { "type": "object", "properties": { "spent_points": { "$ref": "#/components/schemas/RefundsSpentPointsRequest" }, "earned_points": { "$ref": "#/components/schemas/RefundsEarnedPointsRequest" } }, "required": [ "spent_points", "earned_points" ], "additionalProperties": false }, "RefundsSpentPointsRequest": { "type": "object", "description": "When `NONE`, methods must be empty or null. When `REFUNDABLE`, exactly 1 method of type `RETURN_POINTS` is required.", "properties": { "type": { "type": "string", "enum": [ "NONE", "REFUNDABLE" ] }, "methods": { "oneOf": [ { "type": "null" }, { "type": "array", "items": { "$ref": "#/components/schemas/RefundsSpentPointsMethodRequest" }, "minItems": 0, "maxItems": 1 } ] } }, "required": [ "type" ], "additionalProperties": false }, "RefundsSpentPointsMethodRequest": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "RETURN_POINTS" ] }, "mode": { "type": "string", "enum": [ "REFUND_ALL", "REFUND_ITEM", "REFUND_AMOUNT" ] } }, "required": [ "type", "mode" ], "additionalProperties": false }, "RefundsEarnedPointsRequest": { "type": "object", "description": "When `NONE`, methods must be empty or null. When `REFUNDABLE`, exactly 1 method is required.\n`REVOKE_FROM_PENDING` requires pending points to be enabled (type not `IMMEDIATE`).\n`REVOKE_FROM_BALANCE` with mode `REVOKE_BELOW_ZERO` requires `balance_settings.allow_negative: true`.\n", "properties": { "type": { "type": "string", "enum": [ "NONE", "REFUNDABLE" ] }, "methods": { "oneOf": [ { "type": "null" }, { "type": "array", "items": { "$ref": "#/components/schemas/RefundsEarnedPointsMethodRequest" }, "minItems": 0, "maxItems": 1 } ] } }, "required": [ "type" ], "additionalProperties": false }, "RefundsEarnedPointsMethodRequest": { "type": "object", "description": "Discriminated union on `type`. `REVOKE_FROM_PENDING` needs no extra fields. `REVOKE_FROM_BALANCE` requires `mode`.", "properties": { "type": { "type": "string", "enum": [ "REVOKE_FROM_PENDING", "REVOKE_FROM_BALANCE" ] }, "mode": { "type": "string", "enum": [ "REVOKE_TO_ZERO", "REVOKE_BELOW_ZERO" ], "description": "Required when type is `REVOKE_FROM_BALANCE`." } }, "required": [ "type" ] }, "BalanceSettingsRequest": { "type": "object", "properties": { "allow_negative": { "type": "boolean", "description": "Can only be `true` when `points_expiration.type` is `NO_EXPIRATION`." } }, "required": [ "allow_negative" ], "additionalProperties": false }, "DayMonthRequest": { "type": "object", "description": "Day/month pair. Day range depends on month (Feb max 29, Apr/Jun/Sep/Nov max 30, others max 31).", "properties": { "day": { "type": "integer", "minimum": 1, "maximum": 31 }, "month": { "type": "integer", "minimum": 1, "maximum": 12 } }, "required": [ "day", "month" ], "additionalProperties": false }, "ErrorResponse": { "type": "object", "description": "Standard error response.", "properties": { "code": { "type": "integer", "description": "HTTP status code." }, "key": { "type": "string", "description": "Machine-readable error key." }, "message": { "type": "string", "description": "Human-readable error message." }, "details": { "type": "string", "description": "Additional error details." }, "request_id": { "type": [ "string", "null" ], "description": "Request identifier for tracing." }, "resource_id": { "type": "string", "description": "Related resource identifier (when applicable)." }, "resource_type": { "type": "string", "description": "Related resource type (when applicable)." } }, "required": [ "code", "key", "message" ] }, "ProgramStatus": { "type": "string", "enum": [ "DRAFT", "ACTIVE", "INACTIVE", "DELETED" ] }, "ProgramCreateStatus": { "description": "Status allowed at creation time", "type": "string", "enum": [ "DRAFT", "ACTIVE" ] }, "Metadata": { "type": "object", "description": "Custom key-value metadata.", "additionalProperties": true }, "ProgramCreateRequest": { "type": "object", "required": [ "name" ], "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 200, "description": "Program name" }, "status": { "oneOf": [ { "$ref": "#/components/schemas/ProgramCreateStatus" }, { "type": "null" } ], "description": "Initial status (defaults to DRAFT if not provided)" }, "start_date": { "type": [ "string", "null" ], "format": "date-time", "description": "Program start date (ISO 8601)" }, "end_date": { "type": [ "string", "null" ], "format": "date-time", "description": "Program end date (ISO 8601)" }, "metadata": { "oneOf": [ { "$ref": "#/components/schemas/Metadata" }, { "type": "null" } ], "description": "Custom metadata key-value pairs" }, "card_definitions": { "oneOf": [ { "type": "array", "items": { "$ref": "#/components/schemas/CardDefinitionAssignRef" }, "minItems": 1, "maxItems": 10 }, { "type": "null" } ], "description": "Card definitions to assign on creation" }, "earning_rules": { "oneOf": [ { "type": "array", "items": { "$ref": "#/components/schemas/EarningRuleAssignRef" }, "minItems": 1, "maxItems": 10 }, { "type": "null" } ], "description": "Earning rules to assign on creation" }, "rewards": { "oneOf": [ { "type": "array", "items": { "$ref": "#/components/schemas/RewardAssignRef" }, "minItems": 1, "maxItems": 10 }, { "type": "null" } ], "description": "Rewards to assign on creation" }, "tier_structures": { "oneOf": [ { "type": "array", "items": { "$ref": "#/components/schemas/TierStructureAssignRef" }, "minItems": 1, "maxItems": 10 }, { "type": "null" } ], "description": "Tier structures to assign on creation" } }, "additionalProperties": false }, "ProgramUpdateRequest": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 200, "description": "Program name" }, "start_date": { "type": [ "string", "null" ], "format": "date-time", "description": "Program start date (ISO 8601). Only updatable in DRAFT status." }, "end_date": { "type": [ "string", "null" ], "format": "date-time", "description": "Program end date (ISO 8601). Only updatable in DRAFT status." }, "metadata": { "oneOf": [ { "$ref": "#/components/schemas/Metadata" }, { "type": "null" } ], "description": "Custom metadata (merged with existing on update)" } }, "additionalProperties": false }, "ProgramResponse": { "type": "object", "description": "Program DTO returned by toDTO()", "properties": { "id": { "type": "string", "pattern": "^lprg_[a-f0-9]+$", "description": "Unique program identifier" }, "name": { "type": "string", "description": "Program name" }, "status": { "$ref": "#/components/schemas/ProgramStatus" }, "start_date": { "type": [ "string", "null" ], "format": "date-time", "description": "Program start date" }, "end_date": { "type": [ "string", "null" ], "format": "date-time", "description": "Program end date" }, "metadata": { "$ref": "#/components/schemas/Metadata" }, "created_at": { "type": "string", "format": "date-time", "description": "Creation timestamp (ISO 8601)" }, "updated_at": { "type": [ "string", "null" ], "format": "date-time", "description": "Last update timestamp (ISO 8601)" }, "object": { "type": "string", "const": "program" } } }, "ProgramCreateResponse": { "type": "object", "description": "Extended program DTO returned by toCreateDTO(params). Includes the\nprogram fields plus arrays of attached resource references.\n", "allOf": [ { "$ref": "#/components/schemas/ProgramResponse" }, { "type": "object", "properties": { "card_definitions": { "type": [ "array", "null" ], "items": { "$ref": "#/components/schemas/ProgramCreateCardDefinitionRef" }, "description": "Card definitions attached during creation" }, "earning_rules": { "type": [ "array", "null" ], "items": { "$ref": "#/components/schemas/ProgramCreateEarningRuleRef" }, "description": "Earning rules attached during creation" }, "rewards": { "type": [ "array", "null" ], "items": { "$ref": "#/components/schemas/ProgramCreateRewardRef" }, "description": "Rewards attached during creation" }, "tier_structures": { "type": [ "array", "null" ], "items": { "$ref": "#/components/schemas/ProgramCreateTierStructureRef" }, "description": "Tier structures attached during creation" } } } ] }, "ProgramCreateCardDefinitionRef": { "type": "object", "properties": { "id": { "type": "string", "pattern": "^lcdef_[a-f0-9]+$", "description": "Card definition id" } } }, "ProgramCreateEarningRuleRef": { "type": "object", "properties": { "id": { "type": "string", "pattern": "^lern_[a-f0-9]+$", "description": "Earning rule id" } } }, "ProgramCreateRewardRef": { "type": "object", "properties": { "id": { "type": "string", "pattern": "^lrew_[a-f0-9]+$", "description": "Reward id" }, "costs": { "type": [ "array", "null" ], "items": { "$ref": "#/components/schemas/RewardAssignmentCostsDTO" }, "description": "Costs associated with the reward" }, "stock": { "type": "integer", "description": "Available stock for the reward" } } }, "ProgramCreateTierStructureRef": { "type": "object", "properties": { "id": { "type": "string", "pattern": "^lts_[a-f0-9]+$", "description": "Tier structure id" } } }, "ProgramListResponse": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/ProgramResponse" } }, "cursor": { "oneOf": [ { "$ref": "#/components/schemas/PaginationCursor" }, { "type": "null" } ] }, "object": { "type": "string", "const": "list" } } }, "CardDefinitionAssignRef": { "type": "object", "required": [ "id" ], "properties": { "id": { "type": "string", "pattern": "^lcdef_[a-f0-9]+$", "description": "Card definition id to assign" } }, "additionalProperties": false }, "CardDefinitionUnassignRef": { "type": "object", "required": [ "id" ], "properties": { "id": { "type": "string", "pattern": "^lcdef_[a-f0-9]+$", "description": "Card definition id to unassign" } }, "additionalProperties": false }, "EarningRuleAssignRef": { "type": "object", "required": [ "id" ], "properties": { "id": { "type": "string", "pattern": "^lern_[a-f0-9]+$", "description": "Earning rule id to assign" } }, "additionalProperties": false }, "EarningRuleUnassignRef": { "type": "object", "required": [ "id" ], "properties": { "id": { "type": "string", "pattern": "^lern_[a-f0-9]+$", "description": "Earning rule id to unassign" } }, "additionalProperties": false }, "TierStructureAssignRef": { "type": "object", "required": [ "id" ], "properties": { "id": { "type": "string", "pattern": "^lts_[a-f0-9]+$", "description": "Tier structure id to assign" } }, "additionalProperties": false }, "TierStructureUnassignRef": { "type": "object", "required": [ "id" ], "properties": { "id": { "type": "string", "pattern": "^lts_[a-f0-9]+$", "description": "Tier structure id to unassign" } }, "additionalProperties": false }, "RewardAssignRef": { "type": "object", "required": [ "id", "costs", "stock" ], "properties": { "id": { "type": "string", "pattern": "^lrew_[a-f0-9]+$", "description": "Reward id to assign" }, "costs": { "type": "array", "items": { "$ref": "#/components/schemas/RewardAssignmentCostsRequest" }, "minItems": 1, "maxItems": 10, "description": "Cost definitions for this reward assignment" }, "stock": { "type": "integer", "minimum": 0, "maximum": 2147483647, "description": "Available stock for the reward" } }, "additionalProperties": false }, "RewardUnassignRef": { "type": "object", "required": [ "id" ], "properties": { "id": { "type": "string", "pattern": "^lrew_[a-f0-9]+$", "description": "Reward id to unassign" } }, "additionalProperties": false }, "RewardAssignmentCostsRequest": { "type": "object", "required": [ "spending" ], "properties": { "rules": { "$ref": "#/components/schemas/RewardAssignmentCostsRulesRequest" }, "spending": { "type": "array", "items": { "$ref": "#/components/schemas/RewardAssignmentCostsSpendingRequest" }, "minItems": 1, "maxItems": 1, "description": "Spending definitions (currently limited to 1)" } }, "additionalProperties": false }, "RewardAssignmentCostsSpendingRequest": { "type": "object", "required": [ "points", "card_definition_id" ], "properties": { "points": { "type": "integer", "minimum": 1, "maximum": 2147483647, "description": "Number of points required" }, "card_definition_id": { "type": "string", "pattern": "^lcdef_[a-f0-9]+$", "description": "Card definition to deduct points from" } }, "additionalProperties": false }, "RewardAssignmentCostsRulesRequest": { "type": "object", "required": [ "logic" ], "properties": { "logic": { "type": "string", "description": "Logical formula combining rule definitions (e.g. \"1 AND 2\")" } }, "additionalProperties": true, "description": "Rule group object. Keys are numeric identifiers (e.g. \"1\", \"2\") pointing\nto RewardRulesDefinition objects. The `logic` key defines how rules combine.\n" }, "RewardRulesDefinition": { "type": "object", "properties": { "name": { "type": "string", "enum": [ "customer_segment" ], "description": "Rule definition name" }, "property": { "type": [ "string", "null" ], "description": "Property to evaluate" }, "error": { "oneOf": [ { "$ref": "#/components/schemas/RewardRulesError" }, { "type": "null" } ], "description": "Custom error message when rule fails" }, "rules": { "description": "Nested rule group for complex conditions" }, "conditions": { "$ref": "#/components/schemas/RewardRulesConditions" } }, "additionalProperties": false }, "RewardRulesError": { "type": "object", "required": [ "message" ], "properties": { "message": { "type": "string", "minLength": 1, "maxLength": 200, "description": "Error message shown when rule fails" } }, "additionalProperties": false }, "RewardRulesConditions": { "type": "object", "description": "Conditions object with operator keys (`$is`, `$is_not`).\nEach operator maps to an array of values (strings, objects, integers, or booleans).\n", "additionalProperties": false, "properties": { "$is": { "type": "array", "items": { "oneOf": [ { "$ref": "#/components/schemas/RewardRulesConditionObject" }, { "type": "string" }, { "type": "integer" }, { "type": "boolean" } ] }, "minItems": 1 }, "$is_not": { "type": "array", "items": { "oneOf": [ { "$ref": "#/components/schemas/RewardRulesConditionObject" }, { "type": "string" }, { "type": "integer" }, { "type": "boolean" } ] }, "minItems": 1 } } }, "RewardRulesConditionObject": { "type": "object", "properties": { "id": { "type": "string" }, "object": { "type": "string" }, "source_id": { "type": [ "string", "null" ] }, "type": { "type": [ "string", "null" ] } }, "additionalProperties": false }, "RewardAssignmentCostsDTO": { "type": "object", "properties": { "rules": { "description": "Rule group (present only when rules are defined and have definitions)" }, "spending": { "type": [ "array", "null" ], "items": { "$ref": "#/components/schemas/RewardAssignmentSpendingDTO" } } } }, "RewardAssignmentSpendingDTO": { "type": "object", "properties": { "points": { "type": "integer", "description": "Number of points required" }, "card_definition_id": { "type": "string", "description": "Card definition to deduct points from" } } }, "ProgramCardDefinitionDTO": { "type": "object", "description": "Card definition assignment DTO (VLProgramCardDefinitionDTO)", "properties": { "card_type": { "type": "string", "description": "Type of the card definition" }, "card_definition_id": { "type": "string", "pattern": "^lcdef_[a-f0-9]+$", "description": "Card definition identifier" }, "created_at": { "type": "string", "format": "date-time", "description": "Assignment creation timestamp" }, "object": { "type": "string", "const": "program_card_definition" } } }, "CardDefinitionAssignmentListResponse": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/ProgramCardDefinitionDTO" } }, "cursor": { "oneOf": [ { "$ref": "#/components/schemas/PaginationCursor" }, { "type": "null" } ] }, "object": { "type": "string", "const": "list" } } }, "ProgramEarningRuleDTO": { "type": "object", "description": "Earning rule assignment DTO (VLProgramEarningRuleDTO)", "properties": { "earning_rule_id": { "type": "string", "pattern": "^lern_[a-f0-9]+$", "description": "Earning rule identifier" }, "created_at": { "type": "string", "format": "date-time", "description": "Assignment creation timestamp" }, "object": { "type": "string", "const": "program_earning_rule" } } }, "EarningRuleAssignmentListResponse": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/ProgramEarningRuleDTO" } }, "cursor": { "oneOf": [ { "$ref": "#/components/schemas/PaginationCursor" }, { "type": "null" } ] }, "object": { "type": "string", "const": "list" } } }, "ProgramTierStructureDTO": { "type": "object", "description": "Tier structure assignment DTO (VLProgramTierStructureDTO)", "properties": { "tier_structure_id": { "type": "string", "pattern": "^lts_[a-f0-9]+$", "description": "Tier structure identifier" }, "created_at": { "type": "string", "format": "date-time", "description": "Assignment creation timestamp" }, "object": { "type": "string", "const": "program_tier_structure" } } }, "TierStructureAssignmentListResponse": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/ProgramTierStructureDTO" } }, "cursor": { "oneOf": [ { "$ref": "#/components/schemas/PaginationCursor" }, { "type": "null" } ] }, "object": { "type": "string", "const": "list" } } }, "ProgramRewardDTO": { "type": "object", "description": "Reward assignment DTO (VLProgramRewardDTO)", "properties": { "reward_id": { "type": "string", "pattern": "^lrew_[a-f0-9]+$", "description": "Reward identifier" }, "costs": { "type": [ "array", "null" ], "items": { "$ref": "#/components/schemas/RewardAssignmentCostsDTO" }, "description": "Cost definitions for this reward assignment" }, "stock": { "type": "integer", "description": "Available stock" }, "redeemed": { "type": "integer", "description": "Number of times redeemed" }, "created_at": { "type": "string", "format": "date-time", "description": "Assignment creation timestamp" }, "object": { "type": "string", "const": "program_reward" } } }, "RewardAssignmentListResponse": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/ProgramRewardDTO" } }, "cursor": { "oneOf": [ { "$ref": "#/components/schemas/PaginationCursor" }, { "type": "null" } ] }, "object": { "type": "string", "const": "list" } } }, "CardDefinitionsBatchRequest": { "type": "object", "properties": { "assign": { "oneOf": [ { "type": "array", "items": { "$ref": "#/components/schemas/CardDefinitionAssignRef" }, "maxItems": 10 }, { "type": "null" } ], "description": "Card definitions to assign" }, "unassign": { "oneOf": [ { "type": "array", "items": { "$ref": "#/components/schemas/CardDefinitionUnassignRef" }, "maxItems": 10 }, { "type": "null" } ], "description": "Card definitions to unassign" } }, "additionalProperties": false }, "CardDefinitionsBatchResponse": { "type": "object", "properties": { "assigned": { "type": [ "array", "null" ], "items": { "$ref": "#/components/schemas/ProgramCardDefinitionDTO" }, "description": "Successfully assigned card definitions (null if no assign operations)" }, "unassigned": { "type": [ "array", "null" ], "items": { "$ref": "#/components/schemas/ProgramCardDefinitionDTO" }, "description": "Successfully unassigned card definitions (null if no unassign operations)" } } }, "EarningRulesBatchRequest": { "type": "object", "properties": { "assign": { "type": [ "array", "null" ], "items": { "$ref": "#/components/schemas/EarningRuleAssignRef" }, "maxItems": 10, "description": "Earning rules to assign" }, "unassign": { "type": [ "array", "null" ], "items": { "$ref": "#/components/schemas/EarningRuleUnassignRef" }, "maxItems": 10, "description": "Earning rules to unassign" } }, "additionalProperties": false }, "EarningRulesBatchResponse": { "type": "object", "properties": { "assigned": { "type": [ "array", "null" ], "items": { "$ref": "#/components/schemas/ProgramEarningRuleDTO" }, "description": "Successfully assigned earning rules (null if no assign operations)" }, "unassigned": { "type": [ "array", "null" ], "items": { "$ref": "#/components/schemas/ProgramEarningRuleDTO" }, "description": "Successfully unassigned earning rules (null if no unassign operations)" } } }, "TierStructuresBatchRequest": { "type": "object", "properties": { "assign": { "type": [ "array", "null" ], "items": { "$ref": "#/components/schemas/TierStructureAssignRef" }, "maxItems": 10, "description": "Tier structures to assign" }, "unassign": { "type": [ "array", "null" ], "items": { "$ref": "#/components/schemas/TierStructureUnassignRef" }, "maxItems": 10, "description": "Tier structures to unassign" } }, "additionalProperties": false }, "TierStructuresBatchResponse": { "type": "object", "properties": { "assigned": { "type": [ "array", "null" ], "items": { "$ref": "#/components/schemas/ProgramTierStructureDTO" }, "description": "Successfully assigned tier structures (null if no assign operations)" }, "unassigned": { "type": [ "array", "null" ], "items": { "$ref": "#/components/schemas/ProgramTierStructureDTO" }, "description": "Successfully unassigned tier structures (null if no unassign operations)" } } }, "RewardsBatchRequest": { "type": "object", "properties": { "assign": { "type": [ "array", "null" ], "items": { "$ref": "#/components/schemas/RewardAssignRef" }, "maxItems": 10, "description": "Rewards to assign" }, "unassign": { "type": [ "array", "null" ], "items": { "$ref": "#/components/schemas/RewardUnassignRef" }, "maxItems": 10, "description": "Rewards to unassign" } }, "additionalProperties": false }, "RewardsBatchResponse": { "type": "object", "properties": { "assigned": { "type": [ "array", "null" ], "items": { "$ref": "#/components/schemas/ProgramRewardDTO" }, "description": "Successfully assigned rewards (null if no assign operations)" }, "unassigned": { "type": [ "array", "null" ], "items": { "$ref": "#/components/schemas/ProgramRewardDTO" }, "description": "Successfully unassigned rewards (null if no unassign operations)" } } }, "ProgramActivityType": { "type": "string", "enum": [ "vl.program.created", "vl.program.updated", "vl.program.deleted", "vl.program.activated", "vl.program.deactivated", "vl.program.card_definition.assigned", "vl.program.card_definition.unassigned", "vl.program.earning_rule.assigned", "vl.program.earning_rule.unassigned", "vl.program.reward.assigned", "vl.program.reward.unassigned", "vl.program.tier_structure.assigned", "vl.program.tier_structure.unassigned" ] }, "ProgramActivityDTO": { "type": "object", "description": "Program activity DTO (VLProgramActivityDTO extends VLBaseActivityDTO)", "properties": { "id": { "type": "string", "pattern": "^laprg_[a-f0-9]+$", "description": "Unique activity identifier" }, "type": { "$ref": "#/components/schemas/ProgramActivityType" }, "data": { "type": "object", "description": "Activity payload (varies by type, typically contains the program DTO snapshot)", "properties": { "program": { "$ref": "#/components/schemas/ProgramResponse" } } }, "created_at": { "type": "string", "format": "date-time", "description": "Activity timestamp" }, "group_id": { "type": "string", "description": "Group identifier for correlated activities" }, "source": { "$ref": "#/components/schemas/ActivitySource" }, "program_id": { "type": "string", "pattern": "^lprg_[a-f0-9]+$", "description": "Program this activity belongs to" } } }, "ProgramActivityListResponse": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/ProgramActivityDTO" } }, "cursor": { "oneOf": [ { "$ref": "#/components/schemas/PaginationCursor" }, { "type": "null" } ] }, "object": { "type": "string", "const": "list" } } }, "MemberCreateRequest": { "type": "object", "required": [ "customer_id" ], "properties": { "customer_id": { "type": "string", "description": "ID of an existing customer to enroll as a member", "pattern": "^cust_[A-Za-z0-9]+$" }, "status": { "type": [ "string", "null" ], "enum": [ "ACTIVE", "INACTIVE", null ], "default": "ACTIVE", "description": "Initial member status (defaults to ACTIVE)" }, "metadata": { "oneOf": [ { "$ref": "#/components/schemas/Metadata" }, { "type": "null" } ], "description": "Custom key-value metadata" } }, "additionalProperties": false }, "PointsAdjustmentRequest": { "type": "object", "required": [ "points" ], "properties": { "points": { "type": "integer", "minimum": -2147483648, "maximum": 2147483647, "description": "Points to adjust. Positive values add points (ADMIN_CREDIT),\nnegative values subtract points (ADMIN_DEBIT). Zero results in no change.\n" }, "reason": { "type": "string", "maxLength": 255, "description": "Optional reason for the adjustment" } }, "additionalProperties": false }, "RewardPurchaseRequest": { "type": "object", "required": [ "reward_id" ], "properties": { "reward_id": { "type": "string", "description": "ID of the reward to purchase (must be assigned to the program)" } }, "additionalProperties": false }, "MemberResponse": { "type": "object", "properties": { "id": { "type": "string", "description": "Unique member identifier" }, "customer_id": { "type": "string", "description": "Associated customer identifier" }, "program_id": { "type": "string", "description": "Program the member belongs to" }, "status": { "type": "string", "enum": [ "ACTIVE", "INACTIVE", "DELETED" ], "description": "Current member status" }, "metadata": { "type": "object", "description": "Custom key-value metadata", "additionalProperties": true }, "created_at": { "type": "string", "format": "date-time", "description": "ISO 8601 creation timestamp" }, "updated_at": { "type": [ "string", "null" ], "format": "date-time", "description": "ISO 8601 last update timestamp" }, "object": { "type": "string", "const": "member" } } }, "MemberWithCardsResponse": { "allOf": [ { "$ref": "#/components/schemas/MemberResponse" }, { "type": "object", "properties": { "cards": { "type": [ "array", "null" ], "items": { "$ref": "#/components/schemas/MemberCard" }, "description": "Cards assigned to this member" } } } ] }, "MemberCard": { "type": "object", "description": "A card assignment with card details for a member", "properties": { "member_role": { "type": "string", "description": "Role of the member for this card assignment" }, "created_at": { "type": "string", "format": "date-time", "description": "ISO 8601 timestamp when the card was assigned" }, "card": { "oneOf": [ { "$ref": "#/components/schemas/CardSimple" }, { "type": "null" } ] }, "object": { "type": "string", "const": "member_card" } } }, "CardSimple": { "type": "object", "description": "Simplified card representation (used in member card listings)", "properties": { "id": { "type": "string" }, "card_definition_id": { "type": "string" }, "card_type": { "type": "string" }, "code": { "type": [ "string", "null" ], "description": "Card code. May be `null` when code generation is still pending — codes are generated asynchronously after member creation." }, "lifetime_bucket": { "$ref": "#/components/schemas/CardLifetimeBucket" }, "balance": { "$ref": "#/components/schemas/CardBalance" }, "next_expiration": { "oneOf": [ { "$ref": "#/components/schemas/CardNextExpiration" }, { "type": "null" } ] }, "next_activation": { "oneOf": [ { "$ref": "#/components/schemas/CardNextActivation" }, { "type": "null" } ] }, "object": { "type": "string", "const": "card" } } }, "CardFull": { "type": "object", "description": "Full card representation", "properties": { "id": { "type": "string" }, "program_id": { "type": "string" }, "card_definition_id": { "type": "string" }, "card_type": { "type": "string" }, "code": { "type": [ "string", "null" ], "description": "Card code. May be `null` when code generation is still pending — codes are generated asynchronously after member creation." }, "lifetime_bucket": { "$ref": "#/components/schemas/CardLifetimeBucket" }, "balance": { "$ref": "#/components/schemas/CardBalance" }, "customer_id": { "type": "string" }, "member_id": { "type": "string" }, "created_at": { "type": "string", "format": "date-time" }, "updated_at": { "type": [ "string", "null" ], "format": "date-time" }, "object": { "type": "string", "const": "card" } } }, "CardLifetimeBucket": { "type": "object", "description": "Lifetime aggregated point counters for a card", "properties": { "points": { "$ref": "#/components/schemas/CardLifetimeBucketPoints" }, "pending_points": { "$ref": "#/components/schemas/CardLifetimeBucketPendingPoints" } } }, "CardLifetimeBucketPoints": { "type": "object", "description": "Lifetime point counters broken down by type", "properties": { "total": { "type": "integer", "description": "Total accumulated points (earned + added + activated from pending)" }, "earned": { "type": "integer", "description": "Points earned via earning rules" }, "added": { "type": "integer", "description": "Points added manually (ADMIN_CREDIT)" }, "subtracted": { "type": "integer", "description": "Points subtracted manually (ADMIN_DEBIT)" }, "expired": { "type": "integer", "description": "Points that have expired" }, "spent": { "type": "integer", "description": "Points spent on rewards" }, "refunded": { "type": "integer", "description": "Points refunded (earned by returned products)" }, "returned": { "type": "integer", "description": "Points returned (from returned reward purchases)" }, "locked": { "type": "integer", "description": "Points locked (by locked reward purchases)" }, "unlocked": { "type": "integer", "description": "Points unlocked (from unlocked reward purchases)" } } }, "CardLifetimeBucketPendingPoints": { "type": "object", "description": "Lifetime pending point counters", "properties": { "total": { "type": "integer", "description": "Total pending points added" }, "activated": { "type": "integer", "description": "Pending points that have been activated" }, "canceled": { "type": "integer", "description": "Pending points that have been canceled" } } }, "CardBalance": { "type": "object", "description": "Current available balance.\npoints = total - subtracted - expired - spent - refunded + returned - locked + unlocked\npending_points = max(total - activated - canceled, 0)\n", "properties": { "points": { "type": "integer", "description": "Current available points balance" }, "pending_points": { "type": "integer", "description": "Current available pending points balance" } } }, "CardNextExpiration": { "type": "object", "description": "Information about the next upcoming points expiration", "properties": { "points": { "type": "integer", "description": "Number of points expiring next" }, "date": { "type": "string", "format": "date", "description": "Date when points will expire (ISO 8601 date)" } } }, "CardNextActivation": { "type": "object", "description": "Information about the next upcoming pending points activation", "properties": { "points": { "type": "integer", "description": "Number of pending points activating next" }, "type": { "type": "string", "description": "Type of pending points activation" }, "date": { "type": [ "string", "null" ], "format": "date", "description": "Date when pending points will activate (not present for EVENT_BASED type)" }, "cancel_date": { "type": [ "string", "null" ], "format": "date", "description": "Date when pending points will be auto-canceled (only for EVENT_BASED type)" } } }, "MemberListResponse": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/MemberResponse" } }, "cursor": { "oneOf": [ { "$ref": "#/components/schemas/PaginationCursor" }, { "type": "null" } ] }, "object": { "type": "string", "const": "list" } } }, "Activity": { "type": "object", "description": "An activity log entry", "properties": { "id": { "type": "string", "description": "Unique activity identifier" }, "type": { "type": "string", "description": "Activity type. Member types: vl.member.created, vl.member.deleted,\nvl.member.activated, vl.member.deactivated, vl.member.card.assigned,\nvl.member.card.unassigned. Card types: vl.card.created, vl.card.assigned,\nvl.card.unassigned, vl.card.code_generation.succeeded, vl.card.code_generation.failed.\n" }, "data": { "type": "object", "description": "Activity-specific data payload", "additionalProperties": true }, "created_at": { "type": "string", "format": "date-time", "description": "ISO 8601 timestamp when the activity occurred" }, "group_id": { "type": [ "string", "null" ], "description": "Group identifier linking related activities" }, "source": { "oneOf": [ { "$ref": "#/components/schemas/ActivitySource" }, { "type": "null" } ] } } }, "ActivityListResponse": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/Activity" } }, "cursor": { "oneOf": [ { "$ref": "#/components/schemas/PaginationCursor" }, { "type": "null" } ] }, "object": { "type": "string", "const": "list" } } }, "PointsAdjustmentResponse": { "type": "object", "description": "Result of a manual points adjustment operation", "properties": { "status": { "type": "string", "enum": [ "TRANSACTION_CREATED", "NO_CHANGE" ], "description": "TRANSACTION_CREATED when points were adjusted.\nNO_CHANGE when amount was zero.\n" }, "message": { "type": "string", "description": "Human-readable result message", "examples": [ "Points addition transaction created", "Points subtraction transaction created", "Provided amount is zero, transaction was not created" ] }, "transaction": { "oneOf": [ { "$ref": "#/components/schemas/CardTransaction" }, { "type": "null" } ], "description": "The created transaction (null when status is NO_CHANGE)" } } }, "PointsActivationResponse": { "type": "object", "description": "Result of a pending points activation operation", "properties": { "status": { "type": "string", "enum": [ "TRANSACTION_CREATED", "NO_ACTIVATION" ] }, "message": { "type": "string", "description": "Human-readable result message", "examples": [ "Points activation transaction created" ] }, "transaction": { "oneOf": [ { "$ref": "#/components/schemas/CardTransaction" }, { "type": "null" } ] } } }, "PointsCancellationResponse": { "type": "object", "description": "Result of a pending points cancellation operation", "properties": { "status": { "type": "string", "enum": [ "TRANSACTION_CREATED", "NO_CANCELLATION" ] }, "message": { "type": "string", "description": "Human-readable result message", "examples": [ "Points cancellation transaction created" ] }, "transaction": { "oneOf": [ { "$ref": "#/components/schemas/CardTransaction" }, { "type": "null" } ] } } }, "PointsExpirationResponse": { "type": "object", "description": "Result of a manual points expiration operation", "properties": { "status": { "type": "string", "enum": [ "TRANSACTION_CREATED", "NO_EXPIRATION" ] }, "message": { "type": "string", "description": "Human-readable result message", "examples": [ "Points expiration transaction created" ] }, "transaction": { "oneOf": [ { "$ref": "#/components/schemas/CardTransaction" }, { "type": "null" } ] } } }, "RewardPurchaseResponse": { "type": "object", "description": "Result of a reward purchase operation", "properties": { "status": { "type": "string", "enum": [ "TRANSACTION_CREATED", "NO_SPENT_ON_REWARD" ] }, "message": { "type": "string", "description": "Human-readable result message", "examples": [ "Points spent on reward transaction created" ] }, "transaction": { "oneOf": [ { "$ref": "#/components/schemas/CardTransaction" }, { "type": "null" } ], "description": "The created card transaction for the reward purchase" } } }, "CardTransaction": { "type": "object", "description": "A card transaction recording a points operation", "properties": { "id": { "type": "string", "description": "Unique transaction identifier" }, "card_id": { "type": "string", "description": "Card this transaction belongs to" }, "program_id": { "type": "string", "description": "Program identifier" }, "member_id": { "type": "string", "description": "Member identifier" }, "card_definition_id": { "type": "string", "description": "Card definition identifier" }, "card_type": { "type": "string", "description": "Card type" }, "type": { "type": "string", "enum": [ "ADMIN_CREDIT", "ADMIN_DEBIT", "ADMIN_POINTS_EXPIRATION", "POINTS_EARNED", "POINTS_SPENT_ON_REWARD", "POINTS_REFUNDED", "POINTS_RETURNED", "POINTS_EXPIRED", "PENDING_POINTS_ADDED", "PENDING_POINTS_ACTIVATED", "PENDING_POINTS_CANCELED" ], "description": "Type of transaction" }, "details": { "$ref": "#/components/schemas/CardTransactionDetails" }, "status": { "type": "string", "enum": [ "PENDING", "PROCESSING", "APPROVED", "REJECTED" ], "description": "Transaction processing status" }, "created_at": { "type": "string", "format": "date-time", "description": "ISO 8601 creation timestamp" }, "updated_at": { "type": [ "string", "null" ], "format": "date-time", "description": "ISO 8601 last update timestamp" } } }, "CardTransactionDetails": { "type": "object", "description": "Transaction details vary by transaction type.\nAll types include `reason` (string or null), `metadata` (object), and optionally `rejection`.\n", "properties": { "reason": { "type": [ "string", "null" ], "description": "Reason for the transaction" }, "metadata": { "type": "object", "description": "Custom metadata", "additionalProperties": true }, "rejection": { "oneOf": [ { "$ref": "#/components/schemas/CardTransactionRejection" }, { "type": "null" } ], "description": "Rejection details (only present for REJECTED transactions)" }, "points": { "type": "object", "description": "Points details (present for most transaction types)", "properties": { "total": { "type": "integer", "description": "Total points in this transaction" }, "expiration_date": { "type": [ "string", "null" ], "format": "date", "description": "Points expiration date (ADMIN_CREDIT, POINTS_EARNED)" }, "expiration_type": { "type": [ "string", "null" ], "description": "Points expiration type (ADMIN_CREDIT, POINTS_EARNED)" }, "date": { "type": [ "string", "null" ], "format": "date", "description": "Activation/cancellation date (PENDING_POINTS_* types)" }, "type": { "type": [ "string", "null" ], "description": "Pending points type (PENDING_POINTS_* types)" } } }, "result": { "type": [ "object", "null" ], "description": "Result details (POINTS_SPENT_ON_REWARD)", "additionalProperties": true }, "reward_id": { "type": [ "string", "null" ], "description": "Associated reward ID (POINTS_SPENT_ON_REWARD)" }, "bucket": { "type": [ "object", "null" ], "description": "Associated points bucket details (ADMIN_POINTS_EXPIRATION)", "additionalProperties": true } } }, "CardTransactionRejection": { "type": "object", "description": "Details about why a transaction was rejected", "properties": { "reason": { "type": "string", "description": "Rejection reason" }, "details": { "type": "string", "description": "Detailed rejection information" } } }, "CardTransactionListResponse": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/CardTransaction" } }, "cursor": { "oneOf": [ { "$ref": "#/components/schemas/PaginationCursor" }, { "type": "null" } ] }, "object": { "type": "string", "const": "list" } } }, "PendingPointsBucket": { "type": "object", "description": "A bucket of pending points awaiting activation", "properties": { "id": { "type": "string", "description": "Unique bucket identifier" }, "card_id": { "type": "string", "description": "Card this bucket belongs to" }, "card_definition_id": { "type": "string", "description": "Card definition identifier" }, "program_id": { "type": "string", "description": "Program identifier" }, "card_type": { "type": "string", "description": "Card type" }, "member_id": { "type": "string", "description": "Member identifier" }, "points": { "type": "object", "properties": { "total": { "type": "integer", "description": "Total pending points in this bucket" } } }, "date": { "type": "string", "format": "date", "description": "Scheduled activation date (ISO 8601 date)" }, "type": { "type": "string", "description": "Pending points type (e.g., PERIOD_BASED, FIXED_DATES, EVENT_BASED)" }, "status": { "type": "string", "enum": [ "PENDING", "ACTIVATED", "CANCELED", "DELETED" ], "description": "Current bucket status" }, "created_at": { "type": "string", "format": "date-time", "description": "ISO 8601 creation timestamp" }, "updated_at": { "type": [ "string", "null" ], "format": "date-time", "description": "ISO 8601 last update timestamp" }, "object": { "type": "string", "const": "card_pending_points_bucket" } } }, "PendingPointsBucketListResponse": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/PendingPointsBucket" } }, "cursor": { "oneOf": [ { "$ref": "#/components/schemas/PaginationCursor" }, { "type": "null" } ] }, "object": { "type": "string", "const": "list" } } }, "ExpiringPointsBucket": { "type": "object", "description": "A bucket of points with a scheduled expiration date", "properties": { "id": { "type": "string", "description": "Unique bucket identifier" }, "card_id": { "type": "string", "description": "Card this bucket belongs to" }, "customer_id": { "type": "string", "description": "Customer identifier" }, "card_definition_id": { "type": "string", "description": "Card definition identifier" }, "program_id": { "type": "string", "description": "Program identifier" }, "card_type": { "type": "string", "description": "Card type" }, "member_id": { "type": "string", "description": "Member identifier" }, "points": { "type": "object", "properties": { "total": { "type": "integer", "description": "Total points in this expiration bucket" } } }, "expiration_date": { "type": "string", "format": "date", "description": "Date when points will expire (ISO 8601 date)" }, "expiration_type": { "type": "string", "description": "Type of expiration (e.g., ROLLING, CALENDAR, SLIDING)" }, "status": { "type": "string", "enum": [ "ACTIVE", "DELETED", "EXPIRED" ], "description": "Current bucket status" }, "created_at": { "type": "string", "format": "date-time", "description": "ISO 8601 creation timestamp" }, "updated_at": { "type": [ "string", "null" ], "format": "date-time", "description": "ISO 8601 last update timestamp" }, "object": { "type": "string", "const": "card_points_bucket" } } }, "ExpiringPointsBucketListResponse": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/ExpiringPointsBucket" } }, "cursor": { "oneOf": [ { "$ref": "#/components/schemas/PaginationCursor" }, { "type": "null" } ] }, "object": { "type": "string", "const": "list" } } }, "RewardTransaction": { "type": "object", "description": "A reward transaction recording a reward purchase", "properties": { "id": { "type": "string", "description": "Unique reward transaction identifier" }, "card_id": { "type": "string", "description": "Card used for the purchase" }, "card_transaction_id": { "type": "string", "description": "Associated card transaction identifier" }, "program_id": { "type": "string", "description": "Program identifier" }, "member_id": { "type": "string", "description": "Member identifier" }, "reward_id": { "type": "string", "description": "Purchased reward identifier" }, "status": { "type": "string", "enum": [ "PENDING", "APPROVED", "REJECTED" ], "description": "Transaction processing status" }, "type": { "type": "string", "enum": [ "PURCHASE" ], "description": "Transaction type (always PURCHASE for this endpoint)" }, "details": { "type": "object", "description": "Transaction-specific details", "additionalProperties": true }, "created_at": { "type": "string", "format": "date-time", "description": "ISO 8601 creation timestamp" }, "updated_at": { "type": [ "string", "null" ], "format": "date-time", "description": "ISO 8601 last update timestamp" }, "object": { "type": "string", "const": "reward_transaction" } } }, "RewardTransactionListResponse": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/RewardTransaction" } }, "cursor": { "oneOf": [ { "$ref": "#/components/schemas/PaginationCursor" }, { "type": "null" } ] }, "object": { "type": "string", "const": "list" } } }, "EarningRuleCreateRequest": { "type": "object", "required": [ "name", "trigger", "earnings" ], "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 200, "description": "Human-readable name for the earning rule." }, "status": { "type": "string", "enum": [ "DRAFT", "ACTIVE" ], "default": "DRAFT", "description": "Initial status. Defaults to `DRAFT`." }, "trigger": { "$ref": "#/components/schemas/EarningRuleTrigger" }, "earnings": { "type": "array", "minItems": 1, "items": { "$ref": "#/components/schemas/EarningRuleEarning" }, "description": "Array of earning definitions, each with optional rules and required effects." }, "error": { "oneOf": [ { "$ref": "#/components/schemas/EarningRuleError" }, { "type": "null" } ], "description": "Custom error message shown when earning rule conditions are not met." }, "validity_hours": { "oneOf": [ { "$ref": "#/components/schemas/EarningRuleValidityHours" }, { "type": "null" } ], "description": "Time-of-day restrictions for when the rule is active." }, "start_date": { "type": [ "string", "null" ], "format": "date-time", "description": "Start date for rule validity (ISO 8601)." }, "end_date": { "type": [ "string", "null" ], "format": "date-time", "description": "End date for rule validity (ISO 8601)." }, "trigger_limits": { "oneOf": [ { "$ref": "#/components/schemas/EarningRuleTriggerLimits" }, { "type": "null" } ], "description": "Cooldown and frequency limits for how often the rule can trigger per customer." }, "metadata": { "oneOf": [ { "type": "object", "additionalProperties": true }, { "type": "null" } ], "description": "Custom key-value metadata." } }, "additionalProperties": false }, "EarningRuleUpdateRequest": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 200 }, "trigger": { "$ref": "#/components/schemas/EarningRuleTrigger" }, "earnings": { "type": "array", "minItems": 1, "items": { "$ref": "#/components/schemas/EarningRuleEarning" } }, "error": { "oneOf": [ { "$ref": "#/components/schemas/EarningRuleError" }, { "type": "null" } ] }, "validity_hours": { "oneOf": [ { "$ref": "#/components/schemas/EarningRuleValidityHours" }, { "type": "null" } ] }, "start_date": { "type": [ "string", "null" ], "format": "date-time" }, "end_date": { "type": [ "string", "null" ], "format": "date-time" }, "trigger_limits": { "oneOf": [ { "$ref": "#/components/schemas/EarningRuleTriggerLimits" }, { "type": "null" } ] }, "metadata": { "oneOf": [ { "type": "object", "additionalProperties": true }, { "type": "null" } ] } }, "additionalProperties": false, "description": "All fields are optional. Provided fields replace existing values; omitted fields retain current values.\nWhen status is not `DRAFT`, only `name`, `earnings`, `error`, `validity_hours`, `start_date`,\n`end_date`, `trigger_limits`, and `metadata` may be updated.\n" }, "EarningRuleTrigger": { "type": "object", "required": [ "event" ], "properties": { "event": { "type": "string", "enum": [ "customer.order.paid", "customer.custom_event", "customer.segment.entered" ], "description": "The event that triggers this earning rule.\n- `customer.order.paid`: Triggered when a customer's order is paid.\n- `customer.custom_event`: Triggered by a custom event (requires `custom_event`).\n- `customer.segment.entered`: Triggered when a customer enters a segment (requires `segment`).\n" }, "custom_event": { "oneOf": [ { "$ref": "#/components/schemas/EarningRuleTriggerCustomEvent" }, { "type": "null" } ], "description": "Required when `event` is `customer.custom_event`. Must be `null` otherwise." }, "segment": { "oneOf": [ { "$ref": "#/components/schemas/EarningRuleTriggerSegment" }, { "type": "null" } ], "description": "Required when `event` is `customer.segment.entered`. Must be `null` otherwise." } }, "additionalProperties": false }, "EarningRuleTriggerCustomEvent": { "type": "object", "required": [ "schema_id" ], "properties": { "schema_id": { "type": "string", "description": "ID of the custom event schema." } }, "additionalProperties": false }, "EarningRuleTriggerSegment": { "type": "object", "required": [ "id" ], "properties": { "id": { "type": "string", "description": "ID of the segment." } }, "additionalProperties": false }, "EarningRuleEarning": { "type": "object", "required": [ "effects" ], "properties": { "name": { "type": [ "string", "null" ], "description": "Optional name for this earning definition." }, "rules": { "oneOf": [ { "$ref": "#/components/schemas/EarningRuleRulesGroup" }, { "type": "null" } ], "description": "Optional validation rules that must pass before effects are applied." }, "effects": { "type": "array", "minItems": 1, "items": { "$ref": "#/components/schemas/EarningRuleEffect" }, "description": "Effects to apply when rules pass (at least one required)." }, "tier_rules": { "description": "Defines earning rules based on member tiers. Has two modes: \n- `NO_REQUIREMENTS`: Member doesn't have to belong to a tier structure to receive earnings.\n- `ANY_OF`: Member has to belong to a defined tier structure to receive earnings.", "oneOf": [ { "$ref": "#/components/schemas/EarningRuleEarningsType" } ] } }, "additionalProperties": false }, "EarningRuleRulesGroup": { "type": "object", "required": [ "logic" ], "properties": { "logic": { "type": "string", "description": "Logical formula combining rule definitions by their numeric keys.\nSupports `AND`, `OR`, and parentheses. Example: `\"1 AND (2 OR 3)\"`.\n" } }, "additionalProperties": { "$ref": "#/components/schemas/EarningRuleDefinition" }, "description": "A rules group containing a `logic` formula key and numbered rule definitions.\nKeys other than `logic` must be positive integers (e.g., `\"1\"`, `\"2\"`, `\"3\"`).\nMinimum 2 properties (logic + at least one rule definition).\n" }, "EarningRuleDefinition": { "type": "object", "properties": { "name": { "type": "string", "enum": [ "customer.segment", "customer.metadata", "order.amount", "order.initial_amount", "order.total_amount", "order.metadata", "order.items.count", "order.items.price_any", "order.items.price_each", "order.items.every", "order.items.any", "order.items.none", "order.items.quantity", "order.items.aggregated_quantity", "order.items.price", "order.items.aggregated_amount", "order.items.cheapest", "order.items.most_expensive", "order.items.metadata", "custom_event.metadata" ], "description": "Rule definition name. Available names depend on the trigger event:\n- `customer.order.paid`: All names except `custom_event.metadata`.\n- `customer.custom_event`: `customer.segment`, `customer.metadata`, `custom_event.metadata`.\n- `customer.segment.entered`: `customer.segment`, `customer.metadata`.\n" }, "property": { "type": [ "string", "null" ], "description": "Required for metadata-based rules (`customer.metadata`, `custom_event.metadata`, `order.items.metadata`, `order.metadata`)." }, "schema_id": { "type": [ "string", "null" ], "description": "Optional reference to a metadata schema." }, "error": { "oneOf": [ { "$ref": "#/components/schemas/EarningRuleError" }, { "type": "null" } ] }, "rules": { "oneOf": [ { "$ref": "#/components/schemas/EarningRuleRulesGroup" }, { "type": "null" } ], "description": "Nested child rules (only allowed for `order.items.every`, `order.items.any`, `order.items.cheapest`, `order.items.most_expensive`)." }, "conditions": { "$ref": "#/components/schemas/EarningRuleConditions" } }, "additionalProperties": false }, "EarningRuleConditions": { "type": "object", "properties": { "$is": { "type": "array", "items": { "oneOf": [ { "$ref": "#/components/schemas/EarningRuleConditionObject" }, { "type": "string" }, { "type": "integer" }, { "type": "boolean" } ] }, "minItems": 1 }, "$is_not": { "type": "array", "items": { "oneOf": [ { "$ref": "#/components/schemas/EarningRuleConditionObject" }, { "type": "string" }, { "type": "integer" }, { "type": "boolean" } ] }, "minItems": 1 }, "$in": { "type": "array", "items": { "oneOf": [ { "$ref": "#/components/schemas/EarningRuleConditionObject" }, { "type": "string" }, { "type": "integer" }, { "type": "boolean" } ] }, "minItems": 1 }, "$not_in": { "type": "array", "items": { "oneOf": [ { "$ref": "#/components/schemas/EarningRuleConditionObject" }, { "type": "string" }, { "type": "integer" }, { "type": "boolean" } ] }, "minItems": 1 }, "$less_than": { "type": "array", "items": { "oneOf": [ { "$ref": "#/components/schemas/EarningRuleConditionObject" }, { "type": "string" }, { "type": "integer" }, { "type": "boolean" } ] }, "minItems": 1 }, "$less_than_or_equal": { "type": "array", "items": { "oneOf": [ { "$ref": "#/components/schemas/EarningRuleConditionObject" }, { "type": "string" }, { "type": "integer" }, { "type": "boolean" } ] }, "minItems": 1 }, "$more_than": { "type": "array", "items": { "oneOf": [ { "$ref": "#/components/schemas/EarningRuleConditionObject" }, { "type": "string" }, { "type": "integer" }, { "type": "boolean" } ] }, "minItems": 1 }, "$more_than_or_equal": { "type": "array", "items": { "oneOf": [ { "$ref": "#/components/schemas/EarningRuleConditionObject" }, { "type": "string" }, { "type": "integer" }, { "type": "boolean" } ] }, "minItems": 1 }, "$dow": { "type": "array", "items": { "type": "integer", "minimum": 0, "maximum": 6 }, "minItems": 1, "maxItems": 7, "description": "Day-of-week filter (0=Sunday, 6=Saturday)." }, "$from": { "type": "array", "items": { "oneOf": [ { "$ref": "#/components/schemas/EarningRuleConditionObject" }, { "type": "string" }, { "type": "integer" }, { "type": "boolean" } ] }, "minItems": 1 } }, "additionalProperties": false, "description": "Condition operators applied to the rule definition. Allowed operators depend on the rule name:\n- `customer.segment`: `$is`, `$is_not`\n- `order.items.every/any/none/cheapest/most_expensive`: `$is`, `$from`\n- `order.items.count`, `order.items.aggregated_quantity`, `order.items.quantity`: `$more_than`, `$is`, `$less_than`, `$less_than_or_equal`, `$more_than_or_equal`, `$in`, `$not_in`\n- `order.amount`, `order.initial_amount`, `order.total_amount`, `order.items.price_any`, `order.items.price_each`: `$more_than`, `$more_than_or_equal`, `$is`, `$less_than`, `$less_than_or_equal`\n- `order.items.aggregated_amount`, `order.items.price`: `$more_than_or_equal`, `$is`, `$less_than_or_equal`\n" }, "EarningRuleConditionObject": { "type": "object", "properties": { "id": { "type": "string" }, "object": { "type": "string" }, "source_id": { "type": [ "string", "null" ] }, "type": { "type": [ "string", "null" ] } }, "additionalProperties": false }, "EarningRuleEffect": { "type": "object", "required": [ "type" ], "properties": { "type": { "type": "string", "enum": [ "POINTS", "POINTS_PROPORTIONAL", "INCENTIVE" ], "description": "The type of effect:\n- `POINTS`: Awards a fixed number of points.\n- `POINTS_PROPORTIONAL`: Awards points proportional to order/customer values.\n- `INCENTIVE`: Awards a predefined incentive.\n" }, "points": { "oneOf": [ { "$ref": "#/components/schemas/EarningRuleEffectPoints" }, { "type": "null" } ], "description": "Required when `type` is `POINTS`. Must be `null` otherwise." }, "points_proportional": { "oneOf": [ { "$ref": "#/components/schemas/EarningRuleEffectPointsProportional" }, { "type": "null" } ], "description": "Required when `type` is `POINTS_PROPORTIONAL`. Must be `null` otherwise." }, "incentive": { "oneOf": [ { "$ref": "#/components/schemas/EarningRuleEffectIncentive" }, { "type": "null" } ], "description": "Required when `type` is `INCENTIVE`. Must be `null` otherwise." } }, "additionalProperties": false }, "EarningRuleEffectPoints": { "type": "object", "required": [ "value", "card_definition_id" ], "properties": { "value": { "type": "integer", "minimum": 0, "maximum": 9007199254740991, "description": "Fixed number of points to award." }, "card_definition_id": { "type": "string", "description": "ID of the card definition to award points to." }, "points_expiration": { "oneOf": [ { "$ref": "#/components/schemas/PointsExpiration" }, { "type": "null" } ], "description": "Optional effect-level expiration override for the awarded points." } }, "additionalProperties": false }, "EarningRuleEffectPointsProportional": { "type": "object", "required": [ "calculation_type", "card_definition_id" ], "properties": { "calculation_type": { "type": "string", "enum": [ "PRE_DISCOUNT_ORDER_AMOUNT", "POST_DISCOUNT_ORDER_AMOUNT", "PRE_DISCOUNT_ORDER_ITEMS_AMOUNT", "POST_DISCOUNT_ORDER_ITEMS_AMOUNT", "ORDER_ITEMS_QUANTITY", "ORDER_METADATA_VALUE", "CUSTOMER_METADATA_VALUE" ], "description": "Determines how proportional points are calculated:\n- `PRE_DISCOUNT_ORDER_AMOUNT`: Based on `order.amount` (before discounts).\n- `POST_DISCOUNT_ORDER_AMOUNT`: Based on `order.total_amount` (after discounts).\n- `ORDER_METADATA_VALUE`: Based on `order.metadata` (numeric metadata property).\n- `CUSTOMER_METADATA_VALUE`: Based on `customer.metadata` (numeric metadata property).\n- `PRE_DISCOUNT_ORDER_ITEMS_AMOUNT`: Based on `order_items.amount` (item amount before discounts).\n- `POST_DISCOUNT_ORDER_ITEMS_AMOUNT`: Based on `order_items.subtotal_amount` (item amount after discounts).\n- `ORDER_ITEMS_QUANTITY`: Based on `order_items.quantity`.\n" }, "card_definition_id": { "type": "string", "description": "ID of the card definition to award points to." }, "points_expiration": { "oneOf": [ { "$ref": "#/components/schemas/PointsExpiration" }, { "type": "null" } ], "description": "Optional effect-level expiration override." }, "order": { "$ref": "#/components/schemas/EarningRulePointsProportionalOrder" }, "customer": { "$ref": "#/components/schemas/EarningRulePointsProportionalCustomer" }, "order_items": { "$ref": "#/components/schemas/EarningRulePointsProportionalOrderItems" } }, "additionalProperties": false, "description": "Conditional requirements based on `calculation_type`:\n- `PRE_DISCOUNT_ORDER_AMOUNT`: `order` required with `amount`. `customer` and `order_items` must be null.\n- `POST_DISCOUNT_ORDER_AMOUNT`: `order` required with `total_amount`. `customer` and `order_items` must be null.\n- `ORDER_METADATA_VALUE`: `order` required with `metadata`. `customer` and `order_items` must be null.\n- `CUSTOMER_METADATA_VALUE`: `customer` required with `metadata`. `order` and `order_items` must be null.\n- `PRE_DISCOUNT_ORDER_ITEMS_AMOUNT`: `order_items` required with `amount`. `order` and `customer` must be null.\n- `POST_DISCOUNT_ORDER_ITEMS_AMOUNT`: `order_items` required with `subtotal_amount`. `order` and `customer` must be null.\n- `ORDER_ITEMS_QUANTITY`: `order_items` required with `quantity`. `order` and `customer` must be null.\n" }, "EarningRuleEffectIncentive": { "type": "object", "required": [ "id" ], "properties": { "id": { "type": "string", "description": "ID of the incentive to award." } }, "additionalProperties": false }, "EarningRulePointsProportionalOrder": { "type": "object", "properties": { "amount": { "$ref": "#/components/schemas/EarningRulePointsProportionalEvery" }, "total_amount": { "$ref": "#/components/schemas/EarningRulePointsProportionalEvery" }, "metadata": { "$ref": "#/components/schemas/EarningRulePointsProportionalMetadata" } }, "additionalProperties": false, "description": "Order-based proportional calculation. Provide the sub-property matching the `calculation_type`." }, "EarningRulePointsProportionalCustomer": { "type": "object", "required": [ "metadata" ], "properties": { "metadata": { "$ref": "#/components/schemas/EarningRulePointsProportionalMetadata" } }, "additionalProperties": false, "description": "Customer metadata-based proportional calculation." }, "EarningRulePointsProportionalOrderItems": { "type": "object", "properties": { "amount": { "$ref": "#/components/schemas/EarningRulePointsProportionalOrderItemsCalculation" }, "subtotal_amount": { "$ref": "#/components/schemas/EarningRulePointsProportionalOrderItemsCalculation" }, "quantity": { "$ref": "#/components/schemas/EarningRulePointsProportionalOrderItemsCalculation" } }, "additionalProperties": false, "description": "Order items-based proportional calculation. Provide the sub-property matching the `calculation_type`." }, "EarningRulePointsProportionalEvery": { "type": "object", "required": [ "every", "value" ], "properties": { "every": { "type": "integer", "minimum": 1, "maximum": 9007199254740991, "description": "The divisor (e.g., every 1000 cents spent)." }, "value": { "type": "integer", "minimum": 0, "maximum": 9007199254740991, "description": "Points awarded per `every` unit." } }, "additionalProperties": false }, "EarningRulePointsProportionalMetadata": { "type": "object", "required": [ "every", "value", "property" ], "properties": { "every": { "type": "integer", "minimum": 1, "maximum": 9007199254740991 }, "value": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "property": { "type": "string", "minLength": 1, "description": "The metadata property name to read the numeric value from." } }, "additionalProperties": false }, "EarningRulePointsProportionalOrderItemsCalculation": { "type": "object", "required": [ "every", "value", "applicable_to" ], "properties": { "every": { "type": "integer", "minimum": 1, "maximum": 9007199254740991 }, "value": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "applicable_to": { "type": "array", "minItems": 1, "items": { "$ref": "#/components/schemas/EarningRulePointsProportionalApplicableTo" }, "description": "Product, SKU, or collection criteria for filtering matching order items." } }, "additionalProperties": false }, "EarningRulePointsProportionalApplicableTo": { "type": "object", "required": [ "type" ], "properties": { "type": { "type": "string", "enum": [ "product", "sku", "products_collection" ], "description": "Type of applicable-to target:\n- `product`: Requires `product` sub-object with `id`.\n- `sku`: Requires `sku` sub-object with `id`.\n- `products_collection`: Requires `products_collection` sub-object with `id`.\n" }, "product": { "$ref": "#/components/schemas/EarningRulePointsProportionalApplicableToProduct" }, "sku": { "$ref": "#/components/schemas/EarningRulePointsProportionalApplicableToSku" }, "products_collection": { "$ref": "#/components/schemas/EarningRulePointsProportionalApplicableToProductsCollection" } }, "additionalProperties": false, "description": "Only the sub-object matching `type` should be provided; others must be null.\n" }, "EarningRulePointsProportionalApplicableToProduct": { "type": "object", "required": [ "id" ], "properties": { "id": { "type": "string", "description": "Product ID." } }, "additionalProperties": false }, "EarningRulePointsProportionalApplicableToSku": { "type": "object", "required": [ "id" ], "properties": { "id": { "type": "string", "description": "SKU ID." } }, "additionalProperties": false }, "EarningRulePointsProportionalApplicableToProductsCollection": { "type": "object", "required": [ "id" ], "properties": { "id": { "type": "string", "description": "Products collection ID." } }, "additionalProperties": false }, "EarningRuleEarningsType": { "oneOf": [ { "type": "object", "title": "No requirements", "properties": { "type": { "type": "string", "description": "Member doesn't have to belong to any tier structure to receive earnings.", "enum": [ "NO_REQUIREMENTS" ] } }, "required": [ "type" ] }, { "type": "object", "title": "Any of", "properties": { "type": { "type": "string", "description": "Member has to belong to a tier structure to receive earnings.", "enum": [ "ANY_OF" ] }, "any_of": { "type": "array", "description": "Defines tier structures and tiers to which a member has to belong to receive earnings. The member has to belong to any of the defined tier structures or tiers.", "items": { "type": "object", "properties": { "tier_structure_id": { "type": "string", "description": "Unique tier structure identifier." }, "tier_ids": { "type": "array", "description": "Array of unique tier identifiers.", "items": { "type": "string" } } }, "required": [ "tier_structure_id", "tier_ids" ] } } }, "required": [ "type", "any_of" ] } ] }, "PointsExpiration": { "type": "object", "required": [ "type" ], "properties": { "type": { "type": "string", "enum": [ "NO_EXPIRATION", "ROLLING_EXPIRATION", "CALENDAR_EXPIRATION", "SLIDING_EXPIRATION" ], "description": "Points expiration strategy:\n- `NO_EXPIRATION`: Points never expire. Other expiration sub-objects must be null.\n- `ROLLING_EXPIRATION`: Points expire after a rolling period. Requires `rolling_expiration`.\n- `CALENDAR_EXPIRATION`: Points expire on fixed calendar dates. Requires `calendar_expiration`.\n- `SLIDING_EXPIRATION`: Expiration resets on customer activity. Requires `sliding_expiration`.\n" }, "rolling_expiration": { "oneOf": [ { "$ref": "#/components/schemas/RollingExpiration" }, { "type": "null" } ] }, "calendar_expiration": { "oneOf": [ { "$ref": "#/components/schemas/CalendarExpiration" }, { "type": "null" } ] }, "sliding_expiration": { "oneOf": [ { "$ref": "#/components/schemas/SlidingExpiration" }, { "type": "null" } ] } }, "additionalProperties": false }, "RollingExpiration": { "type": "object", "required": [ "period" ], "properties": { "period": { "$ref": "#/components/schemas/RollingExpirationPeriod" }, "rounding": { "oneOf": [ { "$ref": "#/components/schemas/RollingExpirationRounding" }, { "type": "null" } ], "description": "Optional rounding to snap expiration to period boundaries." } }, "additionalProperties": false }, "RollingExpirationPeriod": { "type": "object", "required": [ "unit", "value" ], "properties": { "unit": { "type": "string", "enum": [ "DAY", "MONTH", "YEAR" ] }, "value": { "type": "integer", "minimum": 1, "description": "Maximum value depends on unit:\n- `DAY`: 1–90\n- `MONTH`: 1–12\n- `YEAR`: 1–5\n" } }, "additionalProperties": false }, "RollingExpirationRounding": { "type": "object", "required": [ "type" ], "properties": { "type": { "type": "string", "enum": [ "END_OF_MONTH", "END_OF_QUARTER", "END_OF_HALF_YEAR", "END_OF_YEAR", "END_OF_PARTICULAR_MONTH" ], "description": "Rounding strategy. When `END_OF_PARTICULAR_MONTH`, `value` is required (1–12 for month number).\nFor all other types, `value` must be null.\n" }, "value": { "oneOf": [ { "type": "integer", "minimum": 1, "maximum": 12 }, { "type": "null" } ], "description": "Month number (1–12). Required only for `END_OF_PARTICULAR_MONTH`." } }, "additionalProperties": false }, "CalendarExpiration": { "type": "object", "required": [ "expiration_dates" ], "properties": { "expiration_dates": { "type": "array", "minItems": 1, "maxItems": 20, "items": { "$ref": "#/components/schemas/CalendarExpirationDate" }, "description": "Fixed dates when points expire (max 20)." } }, "additionalProperties": false }, "CalendarExpirationDate": { "type": "object", "required": [ "day", "month" ], "properties": { "day": { "type": "integer", "minimum": 1, "maximum": 31, "description": "Day of month. Maximum depends on month:\n- Months 1,3,5,7,8,10,12: max 31\n- Months 4,6,9,11: max 30\n- Month 2: max 29\n" }, "month": { "type": "integer", "minimum": 1, "maximum": 12, "description": "Month number (1–12)." } }, "additionalProperties": false }, "SlidingExpiration": { "type": "object", "required": [ "period" ], "properties": { "earning_activity": { "type": "boolean", "description": "Reset expiration on earning activity." }, "spending_activity": { "type": "boolean", "description": "Reset expiration on spending activity." }, "custom_activity": { "type": "boolean", "description": "Reset expiration on custom activity types." }, "custom_activity_types": { "oneOf": [ { "type": "array", "items": { "type": "string" }, "minItems": 1, "maxItems": 10, "uniqueItems": true, "description": "Required when `custom_activity` is `true`. Max 10 unique items." }, { "type": "null" } ] }, "period": { "$ref": "#/components/schemas/SlidingExpirationPeriod" } }, "additionalProperties": false, "description": "At least one of `earning_activity`, `spending_activity`, or `custom_activity` must be `true`.\nWhen `custom_activity` is `true`, `custom_activity_types` is required with 1–10 unique string items.\n" }, "SlidingExpirationPeriod": { "type": "object", "required": [ "value", "unit" ], "properties": { "unit": { "type": "string", "enum": [ "DAY", "MONTH", "YEAR" ] }, "value": { "type": "integer", "minimum": 1, "description": "Maximum value depends on unit:\n- `DAY`: 1–90\n- `MONTH`: 1–12\n- `YEAR`: 1\n" } }, "additionalProperties": false }, "EarningRuleValidityHours": { "type": "object", "required": [ "daily" ], "properties": { "daily": { "type": "array", "minItems": 1, "items": { "$ref": "#/components/schemas/EarningRuleValidityDailyHours" }, "description": "Array of daily time windows. Overlapping windows for the same day are not allowed." } }, "additionalProperties": false }, "EarningRuleValidityDailyHours": { "type": "object", "required": [ "days_of_week", "start_time", "end_time" ], "properties": { "days_of_week": { "type": "array", "items": { "type": "integer", "minimum": 0, "maximum": 6 }, "minItems": 1, "maxItems": 7, "uniqueItems": true, "description": "Days of week (0=Sunday, 6=Saturday)." }, "start_time": { "type": "string", "pattern": "^\\d{2}:\\d{2}$", "description": "Start time in `HH:mm` format. Must be before `end_time`." }, "end_time": { "type": "string", "pattern": "^\\d{2}:\\d{2}$", "description": "End time in `HH:mm` format." } }, "additionalProperties": false }, "EarningRuleTriggerLimits": { "type": "object", "properties": { "cooldown": { "oneOf": [ { "$ref": "#/components/schemas/TriggerLimitsCooldown" }, { "type": "null" } ], "description": "Cooldown configuration. Defaults to `NO_COOLDOWN`." }, "frequency": { "oneOf": [ { "$ref": "#/components/schemas/TriggerLimitsFrequency" }, { "type": "null" } ], "description": "Frequency limit configuration. Defaults to `NO_LIMIT`." } }, "additionalProperties": false }, "TriggerLimitsCooldown": { "type": "object", "required": [ "type" ], "properties": { "type": { "type": "string", "enum": [ "NO_COOLDOWN", "FIXED_COOLDOWN" ], "description": "- `NO_COOLDOWN`: No cooldown period between triggers.\n- `FIXED_COOLDOWN`: Requires `fixed_cooldown` with period configuration.\n" }, "fixed_cooldown": { "oneOf": [ { "$ref": "#/components/schemas/TriggerLimitsCooldownFixedCooldown" }, { "type": "null" } ], "description": "Required when `type` is `FIXED_COOLDOWN`. Must be null for `NO_COOLDOWN`." } }, "additionalProperties": false }, "TriggerLimitsCooldownFixedCooldown": { "type": "object", "required": [ "period" ], "properties": { "period": { "$ref": "#/components/schemas/TriggerLimitsCooldownFixedCooldownPeriod" } }, "additionalProperties": false }, "TriggerLimitsCooldownFixedCooldownPeriod": { "type": "object", "required": [ "value", "unit" ], "properties": { "value": { "type": "integer", "minimum": 1, "description": "Cooldown duration. Maximum depends on unit:\n- `HOUR`: 1–24\n- `DAY`: 1–90\n- `WEEK`: 1–52\n- `MONTH`: 1–12\n- `YEAR`: 1\n" }, "unit": { "type": "string", "enum": [ "HOUR", "DAY", "WEEK", "MONTH", "YEAR" ] } }, "additionalProperties": false }, "TriggerLimitsFrequency": { "type": "object", "required": [ "type" ], "properties": { "type": { "type": "string", "enum": [ "NO_LIMIT", "LIMITED" ], "description": "- `NO_LIMIT`: No frequency restrictions.\n- `LIMITED`: Requires `limits` array with exactly one limit configuration.\n" }, "limits": { "oneOf": [ { "type": "array", "items": { "$ref": "#/components/schemas/TriggerLimitsFrequencyLimit" }, "minItems": 0, "maxItems": 1 }, { "type": "null" } ], "description": "When `type` is `LIMITED`, must be an array with exactly 1 item.\nWhen `type` is `NO_LIMIT`, must be empty array or null.\n" } }, "additionalProperties": false }, "TriggerLimitsFrequencyLimit": { "type": "object", "required": [ "type", "period", "triggers" ], "properties": { "type": { "type": "string", "enum": [ "TIME_BASED" ] }, "period": { "$ref": "#/components/schemas/TriggerLimitsFrequencyLimitPeriod" }, "triggers": { "$ref": "#/components/schemas/TriggerLimitsFrequencyLimitTriggers" } }, "additionalProperties": false }, "TriggerLimitsFrequencyLimitPeriod": { "type": "object", "required": [ "type" ], "properties": { "type": { "type": "string", "enum": [ "CURRENT_PERIOD" ] }, "current_period": { "oneOf": [ { "$ref": "#/components/schemas/TriggerLimitsFrequencyLimitCurrentPeriod" }, { "type": "null" } ], "description": "Required when `type` is `CURRENT_PERIOD`." } }, "additionalProperties": false }, "TriggerLimitsFrequencyLimitCurrentPeriod": { "type": "object", "required": [ "unit" ], "properties": { "unit": { "type": "string", "enum": [ "DAY", "WEEK", "MONTH", "QUARTER", "YEAR" ], "description": "The time period unit for frequency limiting." } }, "additionalProperties": false }, "TriggerLimitsFrequencyLimitTriggers": { "type": "object", "required": [ "max" ], "properties": { "max": { "type": "integer", "minimum": 1, "description": "Maximum number of triggers allowed within the frequency period." } }, "additionalProperties": false }, "EarningRuleError": { "type": "object", "required": [ "message" ], "properties": { "message": { "type": "string", "minLength": 1, "maxLength": 200, "description": "Custom error message when rule conditions are not satisfied." } }, "additionalProperties": false }, "EarningRuleResponse": { "type": "object", "properties": { "id": { "type": "string", "description": "Unique earning rule identifier." }, "name": { "type": "string" }, "status": { "type": "string", "enum": [ "DRAFT", "ACTIVE", "INACTIVE", "DELETED" ] }, "earnings": { "type": "array", "items": { "$ref": "#/components/schemas/EarningRuleEarningDTO" } }, "trigger": { "$ref": "#/components/schemas/EarningRuleTriggerDTO" }, "error": { "oneOf": [ { "$ref": "#/components/schemas/EarningRuleErrorDTO" }, { "type": "null" } ] }, "validity_hours": { "oneOf": [ { "$ref": "#/components/schemas/EarningRuleValidityHoursDTO" }, { "type": "null" } ] }, "start_date": { "type": [ "string", "null" ], "format": "date-time" }, "end_date": { "type": [ "string", "null" ], "format": "date-time" }, "trigger_limits": { "oneOf": [ { "$ref": "#/components/schemas/EarningRuleTriggerLimitsDTO" }, { "type": "null" } ] }, "metadata": { "type": "object", "additionalProperties": true }, "created_at": { "type": "string", "format": "date-time" }, "updated_at": { "type": [ "string", "null" ], "format": "date-time" }, "object": { "type": "string", "const": "earning_rule" } }, "required": [ "id", "name", "status", "earnings", "trigger", "metadata", "created_at", "object" ] }, "EarningRuleEarningDTO": { "type": "object", "properties": { "name": { "type": [ "string", "null" ] }, "rules": { "oneOf": [ { "$ref": "#/components/schemas/EarningRuleRulesGroupDTO" }, { "type": "null" } ] }, "effects": { "type": "array", "items": { "$ref": "#/components/schemas/EarningRuleEffectDTO" } }, "tier_rules": { "description": "Defines earning rules based on member tiers. Has two modes: \n- `NO_REQUIREMENTS`: Member doesn't have to belong to a tier structure to receive earnings.\n- `ANY_OF`: Member has to belong to a defined tier structure to receive earnings.", "oneOf": [ { "$ref": "#/components/schemas/EarningRuleEarningsType" } ] } } }, "EarningRuleRulesGroupDTO": { "type": "object", "properties": { "logic": { "type": "string" } }, "additionalProperties": { "$ref": "#/components/schemas/EarningRuleDefinitionDTO" } }, "EarningRuleDefinitionDTO": { "type": "object", "properties": { "name": { "type": "string" }, "property": { "type": [ "string", "null" ] }, "conditions": { "type": [ "object", "null" ], "additionalProperties": true }, "rules": { "oneOf": [ { "$ref": "#/components/schemas/EarningRuleRulesGroupDTO" }, { "type": "null" } ] }, "error": { "oneOf": [ { "$ref": "#/components/schemas/EarningRuleErrorDTO" }, { "type": "null" } ] }, "schema_id": { "type": [ "string", "null" ] } } }, "EarningRuleEffectDTO": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "POINTS", "POINTS_PROPORTIONAL", "INCENTIVE" ] }, "points": { "oneOf": [ { "$ref": "#/components/schemas/EarningRuleEffectPointsDTO" }, { "type": "null" } ] }, "points_proportional": { "oneOf": [ { "$ref": "#/components/schemas/EarningRuleEffectPointsProportionalDTO" }, { "type": "null" } ] }, "incentive": { "oneOf": [ { "$ref": "#/components/schemas/EarningRuleEffectIncentiveDTO" }, { "type": "null" } ] } } }, "EarningRuleEffectPointsDTO": { "type": "object", "properties": { "value": { "type": "integer" }, "card_definition_id": { "type": "string" }, "points_expiration": { "oneOf": [ { "$ref": "#/components/schemas/PointsExpirationDTO" }, { "type": "null" } ] } } }, "EarningRuleEffectPointsProportionalDTO": { "type": "object", "properties": { "calculation_type": { "type": "string", "enum": [ "PRE_DISCOUNT_ORDER_AMOUNT", "POST_DISCOUNT_ORDER_AMOUNT", "PRE_DISCOUNT_ORDER_ITEMS_AMOUNT", "POST_DISCOUNT_ORDER_ITEMS_AMOUNT", "ORDER_ITEMS_QUANTITY", "ORDER_METADATA_VALUE", "CUSTOMER_METADATA_VALUE" ] }, "card_definition_id": { "type": "string" }, "order": { "oneOf": [ { "$ref": "#/components/schemas/PointsProportionalOrderDTO" }, { "type": "null" } ] }, "customer": { "oneOf": [ { "$ref": "#/components/schemas/PointsProportionalCustomerDTO" }, { "type": "null" } ] }, "order_items": { "oneOf": [ { "$ref": "#/components/schemas/PointsProportionalOrderItemsDTO" }, { "type": "null" } ] }, "points_expiration": { "oneOf": [ { "$ref": "#/components/schemas/PointsExpirationDTO" }, { "type": "null" } ] } } }, "EarningRuleEffectIncentiveDTO": { "type": "object", "properties": { "id": { "type": "string" } } }, "PointsProportionalOrderDTO": { "type": "object", "properties": { "amount": { "oneOf": [ { "$ref": "#/components/schemas/PointsProportionalEveryDTO" }, { "type": "null" } ] }, "total_amount": { "oneOf": [ { "$ref": "#/components/schemas/PointsProportionalEveryDTO" }, { "type": "null" } ] }, "metadata": { "oneOf": [ { "$ref": "#/components/schemas/PointsProportionalMetadataDTO" }, { "type": "null" } ] } } }, "PointsProportionalCustomerDTO": { "type": "object", "properties": { "metadata": { "oneOf": [ { "$ref": "#/components/schemas/PointsProportionalMetadataDTO" }, { "type": "null" } ] } } }, "PointsProportionalOrderItemsDTO": { "type": "object", "properties": { "amount": { "oneOf": [ { "$ref": "#/components/schemas/PointsProportionalOrderItemsCalculationDTO" }, { "type": "null" } ] }, "subtotal_amount": { "oneOf": [ { "$ref": "#/components/schemas/PointsProportionalOrderItemsCalculationDTO" }, { "type": "null" } ] }, "quantity": { "oneOf": [ { "$ref": "#/components/schemas/PointsProportionalOrderItemsCalculationDTO" }, { "type": "null" } ] } } }, "PointsProportionalEveryDTO": { "type": "object", "properties": { "every": { "type": "integer" }, "value": { "type": "integer" } } }, "PointsProportionalMetadataDTO": { "type": "object", "properties": { "every": { "type": "integer" }, "value": { "type": "integer" }, "property": { "type": "string" } } }, "PointsProportionalOrderItemsCalculationDTO": { "type": "object", "properties": { "every": { "type": "integer" }, "value": { "type": "integer" }, "applicable_to": { "type": "array", "items": { "$ref": "#/components/schemas/PointsProportionalApplicableToDTO" } } } }, "PointsProportionalApplicableToDTO": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "product", "sku", "products_collection" ] }, "product": { "oneOf": [ { "type": "object", "properties": { "id": { "type": "string" } } }, { "type": "null" } ] }, "sku": { "oneOf": [ { "type": "object", "properties": { "id": { "type": "string" } } }, { "type": "null" } ] }, "products_collection": { "oneOf": [ { "type": "object", "properties": { "id": { "type": "string" } } }, { "type": "null" } ] } } }, "EarningRuleTriggerDTO": { "type": "object", "properties": { "event": { "type": "string", "enum": [ "customer.order.paid", "customer.custom_event", "customer.segment.entered" ] }, "custom_event": { "oneOf": [ { "type": "object", "properties": { "schema_id": { "type": "string" } } }, { "type": "null" } ] }, "segment": { "oneOf": [ { "type": "object", "properties": { "id": { "type": "string" } } }, { "type": "null" } ] } } }, "EarningRuleTriggerLimitsDTO": { "type": "object", "properties": { "cooldown": { "oneOf": [ { "$ref": "#/components/schemas/TriggerLimitsCooldownDTO" }, { "type": "null" } ] }, "frequency": { "oneOf": [ { "$ref": "#/components/schemas/TriggerLimitsFrequencyDTO" }, { "type": "null" } ] } } }, "TriggerLimitsCooldownDTO": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "NO_COOLDOWN", "FIXED_COOLDOWN" ] }, "fixed_cooldown": { "oneOf": [ { "type": "object", "properties": { "period": { "type": "object", "properties": { "value": { "type": "integer" }, "unit": { "type": "string", "enum": [ "HOUR", "DAY", "WEEK", "MONTH", "YEAR" ] } } } } }, { "type": "null" } ] } } }, "TriggerLimitsFrequencyDTO": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "NO_LIMIT", "LIMITED" ] }, "limits": { "type": "array", "items": { "$ref": "#/components/schemas/TriggerLimitsFrequencyLimitDTO" } } } }, "TriggerLimitsFrequencyLimitDTO": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "TIME_BASED" ] }, "period": { "oneOf": [ { "type": "object", "properties": { "type": { "type": "string", "enum": [ "CURRENT_PERIOD" ] }, "current_period": { "oneOf": [ { "type": "object", "properties": { "unit": { "type": "string", "enum": [ "DAY", "WEEK", "MONTH", "QUARTER", "YEAR" ] } } }, { "type": "null" } ] } } }, { "type": "null" } ] }, "triggers": { "oneOf": [ { "type": "object", "properties": { "max": { "type": "integer" } } }, { "type": "null" } ] } } }, "EarningRuleErrorDTO": { "type": "object", "properties": { "message": { "type": "string" } } }, "EarningRuleValidityHoursDTO": { "type": "object", "properties": { "daily": { "type": "array", "items": { "type": "object", "properties": { "days_of_week": { "type": "array", "items": { "type": "integer" } }, "start_time": { "type": "string" }, "end_time": { "type": "string" } } } } } }, "EarningRuleListResponse": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/EarningRuleResponse" } }, "cursor": { "oneOf": [ { "$ref": "#/components/schemas/PaginationCursor" }, { "type": "null" } ] }, "object": { "type": "string", "const": "list" } }, "required": [ "data", "object" ] }, "EarningRuleActivitiesListResponse": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/ActivityDTO" } }, "cursor": { "oneOf": [ { "$ref": "#/components/schemas/PaginationCursor" }, { "type": "null" } ] }, "object": { "type": "string", "const": "list" } }, "required": [ "data", "object" ] }, "ActivityDTO": { "type": "object", "properties": { "id": { "type": "string" }, "type": { "type": "string", "enum": [ "vl.earning_rule.created", "vl.earning_rule.updated", "vl.earning_rule.deleted", "vl.earning_rule.activated", "vl.earning_rule.deactivated", "vl.earning_rule.drafted", "vl.earning_rule.assigned", "vl.earning_rule.unassigned" ] }, "data": { "type": "object", "properties": { "earning_rule": { "$ref": "#/components/schemas/EarningRuleResponse" } }, "description": "Activity-specific data containing the earning rule snapshot." }, "created_at": { "type": "string", "format": "date-time" }, "group_id": { "type": "string" }, "source": { "oneOf": [ { "$ref": "#/components/schemas/ActivitySource" }, { "type": "null" } ] } } }, "TierStructure": { "type": "object", "description": "A tier structure resource as returned by the API.", "properties": { "id": { "type": "string", "description": "Unique tier structure identifier." }, "name": { "type": "string", "maxLength": 200, "description": "Display name." }, "type": { "type": "string", "enum": [ "POINT_BALANCE", "POINT_EARNED" ], "description": "Tiering model type." }, "card_definition_id": { "type": "string", "description": "ID of the linked card definition." }, "point_earned": { "oneOf": [ { "$ref": "#/components/schemas/TierStructurePointEarned" }, { "type": "null" } ], "description": "Point-earned tracking configuration. Present when `type` is `POINT_EARNED`." }, "expiration": { "oneOf": [ { "$ref": "#/components/schemas/TierStructureExpiration" }, { "type": "null" } ], "description": "Tier qualification expiration settings." }, "downgrade": { "oneOf": [ { "$ref": "#/components/schemas/TierStructureDowngrade" }, { "type": "null" } ], "description": "Downgrade behaviour settings." }, "metadata": { "type": "object", "description": "Custom key-value metadata.", "additionalProperties": true }, "status": { "type": "string", "enum": [ "DRAFT", "ACTIVE", "INACTIVE", "DELETED" ], "description": "Current lifecycle status." }, "created_at": { "type": "string", "format": "date-time", "description": "ISO 8601 creation timestamp." }, "updated_at": { "oneOf": [ { "type": "string", "format": "date-time" }, { "type": "null" } ], "description": "ISO 8601 last-update timestamp." }, "object": { "type": "string", "enum": [ "tier_structure" ], "description": "Object type discriminator." } }, "required": [ "id", "name", "type", "card_definition_id", "metadata", "status", "created_at", "object" ] }, "TierStructurePointEarned": { "type": "object", "properties": { "period": { "$ref": "#/components/schemas/TierStructurePointEarnedPeriod" }, "type": { "type": "string", "enum": [ "IMMEDIATELY", "NEXT_TRACKING_PERIOD" ], "description": "When the earned points are applied to tier qualification." } }, "required": [ "period", "type" ] }, "TierStructurePointEarnedPeriod": { "type": "object", "properties": { "value": { "type": "integer", "minimum": 1, "description": "Duration value." }, "unit": { "type": "string", "enum": [ "HOUR", "DAY", "WEEK", "MONTH", "YEAR" ], "description": "Duration unit." } }, "required": [ "value", "unit" ] }, "TierStructureExpiration": { "type": "object", "description": "Expiration configuration. The sub-object that is present depends on `type`:\n- `NO_EXPIRATION`: no sub-objects\n- `ROLLING_EXPIRATION`: `rolling_expiration` required\n- `CALENDAR_EXPIRATION`: `calendar_expiration` required\n- `SLIDING_EXPIRATION`: `sliding_expiration` required\n", "properties": { "type": { "type": "string", "enum": [ "NO_EXPIRATION", "SLIDING_EXPIRATION", "ROLLING_EXPIRATION", "CALENDAR_EXPIRATION" ] }, "rolling_expiration": { "oneOf": [ { "$ref": "#/components/schemas/TierStructureRollingExpiration" }, { "type": "null" } ] }, "calendar_expiration": { "oneOf": [ { "$ref": "#/components/schemas/TierStructureCalendarExpiration" }, { "type": "null" } ] }, "sliding_expiration": { "oneOf": [ { "$ref": "#/components/schemas/TierStructureSlidingExpiration" }, { "type": "null" } ] } }, "required": [ "type" ] }, "TierStructureRollingExpiration": { "type": "object", "properties": { "period": { "$ref": "#/components/schemas/TierStructureRollingExpirationPeriod" } }, "required": [ "period" ] }, "TierStructureRollingExpirationPeriod": { "type": "object", "properties": { "value": { "type": "integer", "minimum": 1, "description": "Duration value. Max depends on unit: DAY=90, MONTH=12, YEAR=5." }, "unit": { "type": "string", "enum": [ "DAY", "MONTH", "YEAR" ] } }, "required": [ "value", "unit" ] }, "TierStructureCalendarExpiration": { "type": "object", "properties": { "calendar_dates": { "type": "array", "items": { "$ref": "#/components/schemas/TierStructureCalendarDate" }, "minItems": 1, "maxItems": 20, "description": "List of calendar dates when tier qualification expires." } }, "required": [ "calendar_dates" ] }, "TierStructureCalendarDate": { "type": "object", "description": "Day/month pair. Day range depends on month (Feb max 29, Apr/Jun/Sep/Nov max 30, others max 31).", "properties": { "day": { "type": "integer", "minimum": 1, "maximum": 31 }, "month": { "type": "integer", "minimum": 1, "maximum": 12 } }, "required": [ "day", "month" ] }, "TierStructureSlidingExpiration": { "type": "object", "description": "Sliding window expiration that resets on qualifying activity.", "properties": { "earning_activity": { "type": "boolean", "description": "Whether earning activity resets the expiration window." }, "spending_activity": { "type": "boolean", "description": "Whether spending activity resets the expiration window." }, "custom_activity": { "type": "boolean", "description": "Whether custom activity resets the expiration window." }, "custom_activity_types": { "type": "array", "items": { "type": "string" }, "maxItems": 10, "description": "Custom event schema IDs that reset the window. Required when `custom_activity` is true." }, "period": { "$ref": "#/components/schemas/TierStructureSlidingExpirationPeriod" } }, "required": [ "earning_activity", "spending_activity", "custom_activity", "period" ] }, "TierStructureSlidingExpirationPeriod": { "type": "object", "properties": { "value": { "type": "integer", "minimum": 1, "description": "Duration value. Max depends on unit: DAY=90, MONTH=12, YEAR=5." }, "unit": { "type": "string", "enum": [ "DAY", "MONTH", "YEAR" ] } }, "required": [ "value", "unit" ] }, "TierStructureDowngrade": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "MULTI_LEVEL", "SINGLE_LEVEL", "NO_DOWNGRADE" ], "description": "Downgrade strategy." }, "grace_period": { "oneOf": [ { "$ref": "#/components/schemas/TierStructureDowngradeGracePeriod" }, { "type": "null" } ], "description": "Optional grace period before downgrade takes effect." } } }, "TierStructureDowngradeGracePeriod": { "type": "object", "properties": { "value": { "type": "integer", "minimum": 1, "description": "Duration value. Max depends on unit: DAY=90, MONTH=12, YEAR=5." }, "unit": { "type": "string", "enum": [ "DAY", "MONTH", "YEAR" ] }, "round_up": { "type": "boolean", "description": "Whether to round up the grace period to the next full unit." } }, "required": [ "value", "unit" ] }, "TierStructureCreateRequest": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 200, "description": "Display name." }, "type": { "type": "string", "enum": [ "POINT_BALANCE", "POINT_EARNED" ], "description": "Tiering model type." }, "card_definition_id": { "type": "string", "description": "ID of an existing card definition to link." }, "point_earned": { "oneOf": [ { "$ref": "#/components/schemas/TierStructurePointEarnedRequest" }, { "type": "null" } ], "description": "Required when `type` is `POINT_EARNED`. Must be null when `type` is `POINT_BALANCE`." }, "expiration": { "oneOf": [ { "$ref": "#/components/schemas/TierStructureExpirationRequest" }, { "type": "null" } ], "description": "Expiration settings. Defaults to `NO_EXPIRATION`." }, "downgrade": { "oneOf": [ { "$ref": "#/components/schemas/TierStructureDowngradeRequest" }, { "type": "null" } ], "description": "Downgrade settings. Defaults to `NO_DOWNGRADE`." }, "metadata": { "oneOf": [ { "type": "object", "additionalProperties": true }, { "type": "null" } ], "description": "Custom key-value metadata." }, "status": { "type": "string", "enum": [ "DRAFT", "ACTIVE" ], "description": "Initial status. Default: `DRAFT`." } }, "required": [ "name", "type", "card_definition_id" ], "additionalProperties": false }, "TierStructureUpdateRequest": { "type": "object", "description": "All fields optional. When not in `DRAFT` status, only `name` and `metadata` may be updated.\n", "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 200, "description": "Display name." }, "type": { "type": "string", "enum": [ "POINT_BALANCE", "POINT_EARNED" ], "description": "Tiering model type." }, "card_definition_id": { "type": "string", "description": "ID of an existing card definition to link." }, "point_earned": { "oneOf": [ { "$ref": "#/components/schemas/TierStructurePointEarnedRequest" }, { "type": "null" } ], "description": "Required when `type` changes to `POINT_EARNED`. Must be null when `type` is `POINT_BALANCE`." }, "expiration": { "oneOf": [ { "$ref": "#/components/schemas/TierStructureExpirationRequest" }, { "type": "null" } ], "description": "Expiration settings." }, "downgrade": { "oneOf": [ { "$ref": "#/components/schemas/TierStructureDowngradeRequest" }, { "type": "null" } ], "description": "Downgrade settings." }, "metadata": { "oneOf": [ { "type": "object", "additionalProperties": true }, { "type": "null" } ], "description": "Custom key-value metadata." } }, "additionalProperties": false }, "TierStructurePointEarnedRequest": { "type": "object", "properties": { "period": { "$ref": "#/components/schemas/TierStructurePointEarnedPeriodRequest" }, "type": { "type": "string", "enum": [ "IMMEDIATELY", "NEXT_TRACKING_PERIOD" ], "description": "When the earned points are applied to tier qualification." } }, "required": [ "period", "type" ], "additionalProperties": false }, "TierStructurePointEarnedPeriodRequest": { "type": "object", "properties": { "value": { "type": "integer", "minimum": 1, "description": "Duration value." }, "unit": { "type": "string", "enum": [ "HOUR", "DAY", "WEEK", "MONTH", "YEAR" ], "description": "Duration unit." } }, "required": [ "value", "unit" ], "additionalProperties": false }, "TierStructureExpirationRequest": { "type": "object", "description": "Expiration configuration. Supply the matching sub-object for the chosen `type`:\n- `NO_EXPIRATION`: no sub-objects allowed\n- `ROLLING_EXPIRATION`: `rolling_expiration` required\n- `CALENDAR_EXPIRATION`: `calendar_expiration` required\n- `SLIDING_EXPIRATION`: `sliding_expiration` required\n", "properties": { "type": { "type": "string", "enum": [ "NO_EXPIRATION", "SLIDING_EXPIRATION", "ROLLING_EXPIRATION", "CALENDAR_EXPIRATION" ] }, "rolling_expiration": { "oneOf": [ { "$ref": "#/components/schemas/TierStructureRollingExpirationRequest" }, { "type": "null" } ] }, "calendar_expiration": { "oneOf": [ { "$ref": "#/components/schemas/TierStructureCalendarExpirationRequest" }, { "type": "null" } ] }, "sliding_expiration": { "oneOf": [ { "$ref": "#/components/schemas/TierStructureSlidingExpirationRequest" }, { "type": "null" } ] } }, "required": [ "type" ], "additionalProperties": false }, "TierStructureRollingExpirationRequest": { "type": "object", "properties": { "period": { "$ref": "#/components/schemas/TierStructureRollingExpirationPeriodRequest" } }, "required": [ "period" ], "additionalProperties": false }, "TierStructureRollingExpirationPeriodRequest": { "type": "object", "properties": { "value": { "type": "integer", "minimum": 1, "description": "Duration value. Max depends on unit: DAY=90, MONTH=12, YEAR=5." }, "unit": { "type": "string", "enum": [ "DAY", "MONTH", "YEAR" ] } }, "required": [ "value", "unit" ], "additionalProperties": false }, "TierStructureCalendarExpirationRequest": { "type": "object", "properties": { "calendar_dates": { "type": "array", "items": { "$ref": "#/components/schemas/TierStructureCalendarDateRequest" }, "minItems": 1, "maxItems": 20, "description": "List of calendar dates when tier qualification expires." } }, "required": [ "calendar_dates" ], "additionalProperties": false }, "TierStructureCalendarDateRequest": { "type": "object", "description": "Day/month pair. Day range depends on month (Feb max 29, Apr/Jun/Sep/Nov max 30, others max 31).", "properties": { "day": { "type": "integer", "minimum": 1, "maximum": 31 }, "month": { "type": "integer", "minimum": 1, "maximum": 12 } }, "required": [ "day", "month" ], "additionalProperties": false }, "TierStructureSlidingExpirationRequest": { "type": "object", "description": "Sliding window expiration. At least one activity type must be true.", "properties": { "earning_activity": { "type": "boolean", "description": "Whether earning activity resets the expiration window." }, "spending_activity": { "type": "boolean", "description": "Whether spending activity resets the expiration window." }, "custom_activity": { "type": "boolean", "description": "Whether custom activity resets the expiration window." }, "custom_activity_types": { "type": "array", "items": { "type": "string" }, "maxItems": 10, "description": "Custom event schema IDs. Required and non-empty when `custom_activity` is true. Items must be unique." }, "period": { "oneOf": [ { "$ref": "#/components/schemas/TierStructureSlidingExpirationPeriodRequest" }, { "type": "null" } ] } }, "required": [ "period" ], "additionalProperties": false }, "TierStructureSlidingExpirationPeriodRequest": { "type": "object", "properties": { "value": { "type": "integer", "minimum": 1, "description": "Duration value. Max depends on unit: DAY=90, MONTH=12, YEAR=5." }, "unit": { "type": "string", "enum": [ "DAY", "MONTH", "YEAR" ] } }, "required": [ "value", "unit" ], "additionalProperties": false }, "TierStructureDowngradeRequest": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "MULTI_LEVEL", "SINGLE_LEVEL", "NO_DOWNGRADE" ], "description": "Downgrade strategy." }, "grace_period": { "oneOf": [ { "$ref": "#/components/schemas/TierStructureDowngradeGracePeriodRequest" }, { "type": "null" } ], "description": "Optional grace period before downgrade takes effect." } }, "additionalProperties": false }, "TierStructureDowngradeGracePeriodRequest": { "type": "object", "properties": { "value": { "type": "integer", "minimum": 1, "description": "Duration value. Max depends on unit: DAY=90, MONTH=12, YEAR=5." }, "unit": { "type": "string", "enum": [ "DAY", "MONTH", "YEAR" ] }, "round_up": { "type": "boolean", "description": "Whether to round up the grace period to the next full unit." } }, "required": [ "value", "unit" ], "additionalProperties": false }, "Tier": { "type": "object", "description": "A tier resource as returned by the API.", "properties": { "id": { "type": "string", "description": "Unique tier identifier." }, "tier_structure_id": { "type": "string", "description": "ID of the parent tier structure." }, "name": { "type": "string", "maxLength": 200, "description": "Display name." }, "qualification_rules": { "oneOf": [ { "$ref": "#/components/schemas/TierQualificationRules" }, { "type": "null" } ], "description": "Rules determining how members qualify for this tier." }, "downgrade": { "$ref": "#/components/schemas/TierDowngrade" }, "metadata": { "type": "object", "description": "Custom key-value metadata.", "additionalProperties": true }, "created_at": { "type": "string", "format": "date-time", "description": "ISO 8601 creation timestamp." }, "updated_at": { "oneOf": [ { "type": "string", "format": "date-time" }, { "type": "null" } ], "description": "ISO 8601 last-update timestamp." }, "object": { "type": "string", "enum": [ "tier" ], "description": "Object type discriminator." } }, "required": [ "id", "tier_structure_id", "name", "downgrade", "metadata", "created_at", "object" ] }, "TierQualificationRules": { "type": "object", "description": "When `type` is `POINTS`, `min_value` is required and defines the point threshold.\n`max_value` is optional (open-ended tier if omitted).\nWhen `type` is `SEGMENT`, `segment` is required.\n", "properties": { "type": { "type": "string", "enum": [ "POINTS", "SEGMENT" ] }, "min_value": { "oneOf": [ { "type": "integer", "minimum": 0 }, { "type": "null" } ], "description": "Minimum point value for tier qualification." }, "max_value": { "oneOf": [ { "type": "integer", "minimum": 0 }, { "type": "null" } ], "description": "Maximum point value for tier qualification." }, "segment": { "oneOf": [ { "$ref": "#/components/schemas/TierQualificationRulesSegment" }, { "type": "null" } ], "description": "Segment reference. Present when `type` is `SEGMENT`." } }, "required": [ "type" ] }, "TierQualificationRulesSegment": { "type": "object", "properties": { "id": { "type": "string", "description": "Segment identifier." } }, "required": [ "id" ] }, "TierDowngrade": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "INHERIT", "NO_DOWNGRADE" ], "description": "`INHERIT` uses the tier structure's downgrade setting. `NO_DOWNGRADE` disables downgrade for this tier." } } }, "TierCreateRequest": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 200, "description": "Display name." }, "qualification_rules": { "$ref": "#/components/schemas/TierQualificationRulesRequest" }, "downgrade": { "oneOf": [ { "$ref": "#/components/schemas/TierDowngradeRequest" }, { "type": "null" } ], "description": "Downgrade override. Default: `INHERIT`." }, "metadata": { "oneOf": [ { "type": "object", "additionalProperties": true }, { "type": "null" } ], "description": "Custom key-value metadata." } }, "required": [ "name", "qualification_rules" ], "additionalProperties": false }, "TierUpdateRequest": { "type": "object", "description": "All fields optional. Omitted fields retain their current values.", "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 200, "description": "Display name." }, "qualification_rules": { "oneOf": [ { "$ref": "#/components/schemas/TierQualificationRulesRequest" }, { "type": "null" } ], "description": "Qualification rules." }, "downgrade": { "oneOf": [ { "$ref": "#/components/schemas/TierDowngradeRequest" }, { "type": "null" } ], "description": "Downgrade override." }, "metadata": { "oneOf": [ { "type": "object", "additionalProperties": true }, { "type": "null" } ], "description": "Custom key-value metadata." } }, "additionalProperties": false }, "TierQualificationRulesRequest": { "type": "object", "description": "When `type` is `POINTS`, `min_value` is required. `max_value` is optional but if\nprovided must be >= `min_value`. Cannot have `max_value` without `min_value`.\nWhen `type` is `SEGMENT`, `segment` is required and `min_value`/`max_value` are not allowed.\n", "properties": { "type": { "type": "string", "enum": [ "POINTS", "SEGMENT" ] }, "min_value": { "type": "integer", "minimum": 0, "description": "Minimum point value for tier qualification." }, "max_value": { "type": "integer", "minimum": 0, "description": "Maximum point value. Must be >= min_value." }, "segment": { "oneOf": [ { "$ref": "#/components/schemas/TierQualificationRulesSegmentRequest" }, { "type": "null" } ], "description": "Segment reference. Required when `type` is `SEGMENT`." } }, "required": [ "type" ], "additionalProperties": false }, "TierQualificationRulesSegmentRequest": { "type": "object", "properties": { "id": { "type": "string", "description": "Segment identifier." } }, "required": [ "id" ], "additionalProperties": false }, "TierDowngradeRequest": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "INHERIT", "NO_DOWNGRADE" ], "description": "`INHERIT` uses the tier structure's downgrade setting." } }, "required": [ "type" ], "additionalProperties": false }, "TierStructureListResponse": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/TierStructure" } }, "cursor": { "oneOf": [ { "$ref": "#/components/schemas/PaginationCursor" }, { "type": "null" } ] }, "object": { "type": "string", "enum": [ "list" ] } }, "required": [ "data", "object" ] }, "TierListResponse": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/Tier" } }, "cursor": { "oneOf": [ { "$ref": "#/components/schemas/PaginationCursor" }, { "type": "null" } ] }, "object": { "type": "string", "enum": [ "list" ] } }, "required": [ "data", "object" ] }, "TierStructureActivityListResponse": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/TierStructureActivity" } }, "cursor": { "oneOf": [ { "$ref": "#/components/schemas/PaginationCursor" }, { "type": "null" } ] }, "object": { "type": "string", "enum": [ "list" ] } }, "required": [ "data", "object" ] }, "TierStructureActivity": { "type": "object", "properties": { "id": { "type": "string", "description": "Unique activity identifier." }, "tier_structure_id": { "type": "string", "description": "ID of the tier structure this activity belongs to." }, "type": { "type": "string", "enum": [ "vl.tier_structure.created", "vl.tier_structure.updated", "vl.tier_structure.deleted", "vl.tier_structure.activated", "vl.tier_structure.deactivated", "vl.tier_structure.drafted", "vl.tier_structure.assigned", "vl.tier_structure.unassigned", "vl.tier_structure.tier.created", "vl.tier_structure.tier.updated", "vl.tier_structure.tier.deleted" ], "description": "Activity event type." }, "data": { "type": "object", "description": "Event-specific payload containing the affected resource snapshots.", "additionalProperties": true }, "created_at": { "type": "string", "format": "date-time", "description": "ISO 8601 timestamp of when the activity occurred." }, "group_id": { "oneOf": [ { "type": "string" }, { "type": "null" } ], "description": "Group identifier for correlated activities." }, "source": { "oneOf": [ { "$ref": "#/components/schemas/ActivitySource" }, { "type": "null" } ], "description": "Source channel that triggered the activity." } }, "required": [ "id", "tier_structure_id", "type", "data", "created_at" ] }, "IncentiveType": { "type": "string", "enum": [ "POINTS", "POINTS_PROPORTIONAL", "MATERIAL", "DIGITAL" ], "description": "Type of incentive. Determines which detail object is present in the response and required in create/update requests.\n" }, "IncentiveStatus": { "type": "string", "enum": [ "DRAFT", "ACTIVE", "DELETED" ], "description": "Current lifecycle status of the incentive." }, "IncentiveCreateStatus": { "type": "string", "enum": [ "DRAFT", "ACTIVE" ], "description": "Status allowed when creating an incentive." }, "IncentiveMaterialType": { "type": "string", "enum": [ "PRODUCT", "SKU" ] }, "IncentiveDigitalType": { "type": "string", "enum": [ "GIFT_VOUCHERS", "DISCOUNT_COUPONS" ] }, "PointsProportionalCalculationType": { "type": "string", "enum": [ "PRE_DISCOUNT_ORDER_AMOUNT", "POST_DISCOUNT_ORDER_AMOUNT", "PRE_DISCOUNT_ORDER_ITEMS_AMOUNT", "POST_DISCOUNT_ORDER_ITEMS_AMOUNT", "ORDER_ITEMS_QUANTITY", "ORDER_METADATA_VALUE", "CUSTOMER_METADATA_VALUE" ], "description": "Calculation type for proportional points. Determines which sub-object (`order`, `customer`, `order_items`) is required.\n" }, "PointsProportionalApplicableToObjectType": { "type": "string", "enum": [ "product", "sku", "products_collection" ] }, "FiltersJunction": { "type": "string", "enum": [ "AND", "OR" ], "description": "Logical junction between filter conditions." }, "IncentiveActivityType": { "type": "string", "enum": [ "vl.incentive.created", "vl.incentive.updated", "vl.incentive.deleted", "vl.incentive.activated", "vl.incentive.drafted" ] }, "ActivitySourceChannel": { "type": "string", "enum": [ "USER_PORTAL", "API", "CLIENT_API", "INTERNAL" ] }, "IncentivePointsDTO": { "type": "object", "description": "Fixed-points incentive configuration.", "properties": { "value": { "type": "integer", "minimum": 0, "maximum": 9223372036854776000, "description": "Number of points to award." }, "card_definition_id": { "type": "string", "pattern": "^lcdef_[a-f0-9]+$", "description": "Card definition to which points are added." } }, "required": [ "value", "card_definition_id" ] }, "IncentivePointsProportionalEvery": { "type": "object", "properties": { "every": { "type": "integer", "minimum": 1, "maximum": 9223372036854776000, "description": "For every `every` units of the base metric." }, "value": { "type": "integer", "minimum": 0, "maximum": 9223372036854776000, "description": "Award `value` points." } }, "required": [ "every", "value" ], "additionalProperties": false }, "IncentivePointsProportionalMetadata": { "type": "object", "properties": { "every": { "type": "integer", "minimum": 1, "maximum": 9223372036854776000 }, "value": { "type": "integer", "minimum": 0, "maximum": 9223372036854776000 }, "property": { "type": "string", "minLength": 1, "description": "Metadata property key to read the value from." } }, "required": [ "every", "value", "property" ], "additionalProperties": false }, "IncentivePointsProportionalApplicableToProduct": { "type": "object", "properties": { "id": { "type": "string", "pattern": "^prod_[a-f0-9]+" } }, "required": [ "id" ], "additionalProperties": false }, "IncentivePointsProportionalApplicableToSku": { "type": "object", "properties": { "id": { "type": "string", "pattern": "^sku_[a-f0-9]+" } }, "required": [ "id" ], "additionalProperties": false }, "IncentivePointsProportionalApplicableToProductsCollection": { "type": "object", "properties": { "id": { "type": "string", "pattern": "^pc_[a-zA-Z0-9]+" } }, "required": [ "id" ], "additionalProperties": false }, "IncentivePointsProportionalApplicableTo": { "type": "object", "description": "Identifies a product, SKU, or products collection that the calculation applies to. Exactly one of `product`, `sku`, or `products_collection` must be provided based on `type`.\n", "properties": { "type": { "$ref": "#/components/schemas/PointsProportionalApplicableToObjectType" }, "product": { "$ref": "#/components/schemas/IncentivePointsProportionalApplicableToProduct" }, "sku": { "$ref": "#/components/schemas/IncentivePointsProportionalApplicableToSku" }, "products_collection": { "$ref": "#/components/schemas/IncentivePointsProportionalApplicableToProductsCollection" } }, "required": [ "type" ], "additionalProperties": false }, "IncentivePointsProportionalOrderItemsCalculation": { "type": "object", "properties": { "every": { "type": "integer", "minimum": 1, "maximum": 9223372036854776000 }, "value": { "type": "integer", "minimum": 0, "maximum": 9223372036854776000 }, "applicable_to": { "type": "array", "items": { "$ref": "#/components/schemas/IncentivePointsProportionalApplicableTo" }, "minItems": 1 } }, "required": [ "every", "value", "applicable_to" ], "additionalProperties": false }, "IncentivePointsProportionalOrder": { "type": "object", "description": "Order-level proportional calculation config.", "properties": { "amount": { "$ref": "#/components/schemas/IncentivePointsProportionalEvery" }, "total_amount": { "$ref": "#/components/schemas/IncentivePointsProportionalEvery" }, "metadata": { "$ref": "#/components/schemas/IncentivePointsProportionalMetadata" } }, "additionalProperties": false }, "IncentivePointsProportionalCustomer": { "type": "object", "description": "Customer-level proportional calculation config.", "properties": { "metadata": { "$ref": "#/components/schemas/IncentivePointsProportionalMetadata" } }, "required": [ "metadata" ], "additionalProperties": false }, "IncentivePointsProportionalOrderItems": { "type": "object", "description": "Order-items-level proportional calculation config.", "properties": { "amount": { "$ref": "#/components/schemas/IncentivePointsProportionalOrderItemsCalculation" }, "subtotal_amount": { "$ref": "#/components/schemas/IncentivePointsProportionalOrderItemsCalculation" }, "quantity": { "$ref": "#/components/schemas/IncentivePointsProportionalOrderItemsCalculation" } }, "additionalProperties": false }, "IncentivePointsProportionalDTO": { "type": "object", "description": "Proportional-points incentive configuration. The `calculation_type` determines which sub-object is required: - `PRE_DISCOUNT_ORDER_AMOUNT` -> `order.amount` - `POST_DISCOUNT_ORDER_AMOUNT` -> `order.total_amount` - `ORDER_METADATA_VALUE` -> `order.metadata` - `CUSTOMER_METADATA_VALUE` -> `customer.metadata` - `PRE_DISCOUNT_ORDER_ITEMS_AMOUNT` -> `order_items.amount` - `POST_DISCOUNT_ORDER_ITEMS_AMOUNT` -> `order_items.subtotal_amount` - `ORDER_ITEMS_QUANTITY` -> `order_items.quantity`\n", "properties": { "calculation_type": { "$ref": "#/components/schemas/PointsProportionalCalculationType" }, "card_definition_id": { "type": "string", "pattern": "^lcdef_[a-f0-9]+$", "description": "Card definition to which points are added." }, "order": { "$ref": "#/components/schemas/IncentivePointsProportionalOrder" }, "customer": { "$ref": "#/components/schemas/IncentivePointsProportionalCustomer" }, "order_items": { "$ref": "#/components/schemas/IncentivePointsProportionalOrderItems" } }, "required": [ "calculation_type", "card_definition_id" ] }, "IncentiveMaterialProductDTO": { "type": "object", "properties": { "id": { "type": "string", "pattern": "^prod_[a-f0-9]+", "description": "Product identifier." } }, "required": [ "id" ], "additionalProperties": false }, "IncentiveMaterialSkuDTO": { "type": "object", "properties": { "product_id": { "type": "string", "pattern": "^prod_[a-f0-9]+", "description": "Parent product identifier." }, "id": { "type": "string", "pattern": "^sku_[a-f0-9]+", "description": "SKU identifier." } }, "required": [ "product_id", "id" ], "additionalProperties": false }, "IncentiveMaterialDTO": { "type": "object", "description": "Material incentive configuration. Exactly one of `product` or `sku` must be provided based on `type`.\n", "properties": { "type": { "$ref": "#/components/schemas/IncentiveMaterialType" }, "product": { "oneOf": [ { "$ref": "#/components/schemas/IncentiveMaterialProductDTO" }, { "type": "null" } ] }, "sku": { "oneOf": [ { "$ref": "#/components/schemas/IncentiveMaterialSkuDTO" }, { "type": "null" } ] } }, "required": [ "type" ] }, "IncentiveDigitalDiscountCouponsDTO": { "type": "object", "properties": { "campaign_id": { "type": "string", "pattern": "^camp_[a-zA-Z0-9]+", "description": "ID of a DISCOUNT_COUPONS campaign." } }, "required": [ "campaign_id" ], "additionalProperties": false }, "IncentiveDigitalGiftVouchersDTO": { "type": "object", "properties": { "campaign_id": { "type": "string", "pattern": "^camp_[a-zA-Z0-9]+", "description": "ID of a GIFT_VOUCHERS campaign." }, "balance": { "type": "number", "minimum": 0, "maximum": 9223372036854776000, "description": "Initial balance to set on the gift voucher." } }, "required": [ "campaign_id", "balance" ], "additionalProperties": false }, "IncentiveDigitalDTO": { "type": "object", "description": "Digital incentive configuration. Exactly one of `discount_coupons` or `gift_vouchers` must be provided based on `type`.\n", "properties": { "type": { "$ref": "#/components/schemas/IncentiveDigitalType" }, "discount_coupons": { "oneOf": [ { "$ref": "#/components/schemas/IncentiveDigitalDiscountCouponsDTO" }, { "type": "null" } ] }, "gift_vouchers": { "oneOf": [ { "$ref": "#/components/schemas/IncentiveDigitalGiftVouchersDTO" }, { "type": "null" } ] } }, "required": [ "type" ] }, "IncentiveDTO": { "type": "object", "description": "Incentive response object.", "properties": { "id": { "type": "string", "pattern": "^linc_[a-f0-9]+$", "description": "Unique incentive identifier.", "example": "linc_abc123def456" }, "name": { "type": "string", "maxLength": 200, "description": "Human-readable name." }, "type": { "$ref": "#/components/schemas/IncentiveType" }, "status": { "$ref": "#/components/schemas/IncentiveStatus" }, "stock": { "type": "integer", "minimum": 0, "maximum": 2147483647, "description": "Remaining stock count." }, "points": { "$ref": "#/components/schemas/IncentivePointsDTO" }, "points_proportional": { "$ref": "#/components/schemas/IncentivePointsProportionalDTO" }, "material": { "$ref": "#/components/schemas/IncentiveMaterialDTO" }, "digital": { "$ref": "#/components/schemas/IncentiveDigitalDTO" }, "created_at": { "type": "string", "format": "date-time", "description": "ISO 8601 creation timestamp." }, "updated_at": { "type": [ "string", "null" ], "format": "date-time", "description": "ISO 8601 last-update timestamp, or null if never updated." }, "object": { "type": "string", "const": "incentive", "description": "Object type discriminator." } }, "required": [ "id", "name", "type", "status", "stock", "created_at", "object" ] }, "IncentiveCreateRequest": { "type": "object", "description": "Request body for creating an incentive. The `type` field determines which detail object is required. Exactly one of `points`, `points_proportional`, `material`, or `digital` must be non-null, matching the given `type`.\n", "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 200, "description": "Human-readable name (must be unique per project)." }, "type": { "$ref": "#/components/schemas/IncentiveType" }, "status": { "$ref": "#/components/schemas/IncentiveCreateStatus" }, "points": { "oneOf": [ { "$ref": "#/components/schemas/IncentivePointsDTO" }, { "type": "null" } ] }, "points_proportional": { "oneOf": [ { "$ref": "#/components/schemas/IncentivePointsProportionalDTO" }, { "type": "null" } ] }, "material": { "oneOf": [ { "$ref": "#/components/schemas/IncentiveMaterialDTO" }, { "type": "null" } ] }, "digital": { "oneOf": [ { "$ref": "#/components/schemas/IncentiveDigitalDTO" }, { "type": "null" } ] }, "stock": { "type": "integer", "minimum": 0, "maximum": 2147483647, "description": "Initial stock count." } }, "required": [ "name", "type", "stock" ], "additionalProperties": false }, "IncentiveUpdateRequest": { "type": "object", "description": "Request body for updating an incentive. At least one property must be provided. When the incentive is ACTIVE, only `name` and `stock` are allowed. When DRAFT, all properties may be updated. If `type` changes the corresponding detail object must also be provided.\n", "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 200 }, "type": { "$ref": "#/components/schemas/IncentiveType" }, "points": { "oneOf": [ { "$ref": "#/components/schemas/IncentivePointsDTO" }, { "type": "null" } ] }, "points_proportional": { "oneOf": [ { "$ref": "#/components/schemas/IncentivePointsProportionalDTO" }, { "type": "null" } ] }, "material": { "oneOf": [ { "$ref": "#/components/schemas/IncentiveMaterialDTO" }, { "type": "null" } ] }, "digital": { "oneOf": [ { "$ref": "#/components/schemas/IncentiveDigitalDTO" }, { "type": "null" } ] }, "stock": { "type": "integer", "minimum": 0, "maximum": 2147483647 } }, "additionalProperties": false }, "IncentiveListResponse": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/IncentiveDTO" } }, "cursor": { "$ref": "#/components/schemas/PaginationCursor" }, "object": { "type": "string", "const": "list" } }, "required": [ "data", "cursor", "object" ] }, "IncentiveActivityDTO": { "type": "object", "description": "An activity log entry for an incentive.", "properties": { "id": { "type": "string", "pattern": "^lainc_[a-f0-9]+$", "description": "Unique activity identifier." }, "incentive_id": { "type": "string", "pattern": "^linc_[a-f0-9]+$", "description": "The incentive this activity belongs to." }, "type": { "$ref": "#/components/schemas/IncentiveActivityType" }, "data": { "type": "object", "description": "Activity payload. Contains the incentive DTO snapshot.", "properties": { "incentive": { "$ref": "#/components/schemas/IncentiveDTO" } } }, "created_at": { "type": "string", "format": "date-time" }, "group_id": { "type": "string", "description": "Groups related activities from the same transaction." }, "source": { "$ref": "#/components/schemas/ActivitySource" } }, "required": [ "id", "incentive_id", "type", "data", "created_at" ] }, "IncentiveActivityListResponse": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/IncentiveActivityDTO" } }, "cursor": { "$ref": "#/components/schemas/PaginationCursor" }, "object": { "type": "string", "const": "list" } }, "required": [ "data", "cursor", "object" ] }, "ResourceInUseErrorResponse": { "allOf": [ { "$ref": "#/components/schemas/ErrorResponse" }, { "type": "object", "properties": { "related_object_ids": { "type": "array", "items": { "type": "string" }, "description": "IDs of the objects that reference this resource." }, "related_object_type": { "type": "string", "description": "Type of the related objects (e.g. `earning_rule`)." }, "related_object_total": { "type": "integer", "description": "Total count of related objects." } } } ] }, "VLRewardDTO": { "type": "object", "description": "Reward resource representation.", "properties": { "id": { "type": "string", "description": "Unique reward identifier." }, "name": { "type": "string", "description": "Reward display name." }, "type": { "type": "string", "enum": [ "MATERIAL", "DIGITAL" ], "description": "Reward type." }, "status": { "type": "string", "enum": [ "ACTIVE", "DRAFT", "INACTIVE", "DELETED" ], "description": "Current lifecycle status." }, "material": { "$ref": "#/components/schemas/VLRewardMaterialDTO", "description": "Material configuration. Present only when type is MATERIAL." }, "digital": { "$ref": "#/components/schemas/VLRewardDigitalDTO", "description": "Digital configuration. Present only when type is DIGITAL." }, "metadata": { "type": "object", "additionalProperties": true, "description": "Key-value metadata." }, "created_at": { "type": "string", "format": "date-time", "description": "ISO 8601 creation timestamp." }, "updated_at": { "type": [ "string", "null" ], "format": "date-time", "description": "ISO 8601 last-update timestamp. Null if never updated." }, "object": { "type": "string", "const": "reward" } }, "required": [ "id", "name", "type", "status", "metadata", "created_at", "updated_at", "object" ] }, "VLRewardMaterialDTO": { "type": "object", "description": "Material reward configuration.", "properties": { "type": { "type": "string", "enum": [ "PRODUCT", "SKU" ], "description": "Material sub-type." }, "product": { "$ref": "#/components/schemas/VLRewardMaterialProductDTO", "description": "Present when material type is PRODUCT." }, "sku": { "$ref": "#/components/schemas/VLRewardMaterialSKUDTO", "description": "Present when material type is SKU." } }, "required": [ "type" ] }, "VLRewardMaterialProductDTO": { "type": "object", "properties": { "id": { "type": "string", "description": "Product identifier." } }, "required": [ "id" ] }, "VLRewardMaterialSKUDTO": { "type": "object", "properties": { "product_id": { "type": "string", "description": "Parent product identifier." }, "id": { "type": "string", "description": "SKU identifier." } }, "required": [ "product_id", "id" ] }, "VLRewardDigitalDTO": { "type": "object", "description": "Digital reward configuration.", "properties": { "type": { "type": "string", "enum": [ "DISCOUNT_COUPONS", "GIFT_VOUCHERS" ], "description": "Digital sub-type." }, "discount_coupons": { "$ref": "#/components/schemas/VLRewardDigitalDiscountCouponsDTO", "description": "Present when digital type is DISCOUNT_COUPONS." }, "gift_vouchers": { "$ref": "#/components/schemas/VLRewardDigitalGiftVouchersDTO", "description": "Present when digital type is GIFT_VOUCHERS." } }, "required": [ "type" ] }, "VLRewardDigitalDiscountCouponsDTO": { "type": "object", "properties": { "campaign_id": { "type": "string", "description": "Linked discount-coupons campaign identifier." } }, "required": [ "campaign_id" ] }, "VLRewardDigitalGiftVouchersDTO": { "type": "object", "properties": { "campaign_id": { "type": "string", "description": "Linked gift-vouchers campaign identifier." }, "balance": { "type": "number", "minimum": 0, "description": "Gift voucher balance amount." } }, "required": [ "campaign_id", "balance" ] }, "VLRewardCreateAPIParams": { "type": "object", "description": "Payload for creating a reward.", "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 200, "description": "Reward display name." }, "type": { "type": "string", "enum": [ "MATERIAL", "DIGITAL" ], "description": "Reward type. Determines which sub-configuration is required." }, "status": { "type": "string", "enum": [ "DRAFT", "ACTIVE" ], "description": "Initial status. Defaults to DRAFT when omitted." }, "material": { "oneOf": [ { "$ref": "#/components/schemas/VLRewardMaterialAPIParams" }, { "type": "null" } ], "description": "Required when type is MATERIAL. Must be null/absent when type is DIGITAL." }, "digital": { "oneOf": [ { "$ref": "#/components/schemas/VLRewardDigitalAPIParams" }, { "type": "null" } ], "description": "Required when type is DIGITAL. Must be null/absent when type is MATERIAL." }, "metadata": { "oneOf": [ { "$ref": "#/components/schemas/Metadata" }, { "type": "null" } ], "description": "Optional key-value metadata." } }, "required": [ "name", "type" ], "additionalProperties": false }, "VLRewardUpdateAPIParams": { "type": "object", "description": "Payload for updating a reward. All fields are optional.\nIn ACTIVE/INACTIVE status only `name` and `metadata` may be updated.\nSupplying `type` resets the non-matching sub-configuration to null.\n", "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 200, "description": "Reward display name." }, "type": { "type": "string", "enum": [ "MATERIAL", "DIGITAL" ], "description": "Reward type." }, "material": { "oneOf": [ { "$ref": "#/components/schemas/VLRewardMaterialAPIParams" }, { "type": "null" } ], "description": "Required when type is MATERIAL." }, "digital": { "oneOf": [ { "$ref": "#/components/schemas/VLRewardDigitalAPIParams" }, { "type": "null" } ], "description": "Required when type is DIGITAL." }, "metadata": { "oneOf": [ { "$ref": "#/components/schemas/Metadata" }, { "type": "null" } ], "description": "Key-value metadata. Merged with existing metadata on update." } }, "additionalProperties": false }, "VLRewardMaterialAPIParams": { "type": "object", "description": "Material reward configuration for create/update.", "properties": { "type": { "type": "string", "enum": [ "PRODUCT", "SKU" ], "description": "Material sub-type." }, "product": { "oneOf": [ { "$ref": "#/components/schemas/VLRewardMaterialProductAPIParams" }, { "type": "null" } ], "description": "Required when material type is PRODUCT. Must be null when SKU." }, "sku": { "oneOf": [ { "$ref": "#/components/schemas/VLRewardMaterialSKUAPIParams" }, { "type": "null" } ], "description": "Required when material type is SKU. Must be null when PRODUCT." } }, "required": [ "type" ], "additionalProperties": false }, "VLRewardMaterialProductAPIParams": { "type": "object", "properties": { "id": { "type": "string", "description": "Product identifier." } }, "required": [ "id" ], "additionalProperties": false }, "VLRewardMaterialSKUAPIParams": { "type": "object", "properties": { "product_id": { "type": "string", "description": "Parent product identifier." }, "id": { "type": "string", "description": "SKU identifier." } }, "required": [ "product_id", "id" ], "additionalProperties": false }, "VLRewardDigitalAPIParams": { "type": "object", "description": "Digital reward configuration for create/update.", "properties": { "type": { "type": "string", "enum": [ "DISCOUNT_COUPONS", "GIFT_VOUCHERS" ], "description": "Digital sub-type." }, "discount_coupons": { "oneOf": [ { "$ref": "#/components/schemas/VLRewardDigitalDiscountCouponsAPIParams" }, { "type": "null" } ], "description": "Required when type is DISCOUNT_COUPONS." }, "gift_vouchers": { "oneOf": [ { "$ref": "#/components/schemas/VLRewardDigitalGiftVouchersAPIParams" }, { "type": "null" } ], "description": "Required when type is GIFT_VOUCHERS." } }, "required": [ "type" ], "additionalProperties": false }, "VLRewardDigitalDiscountCouponsAPIParams": { "type": "object", "properties": { "campaign_id": { "type": "string", "description": "Discount-coupons campaign ID. The campaign must be of type DISCOUNT_COUPONS." } }, "required": [ "campaign_id" ], "additionalProperties": false }, "VLRewardDigitalGiftVouchersAPIParams": { "type": "object", "properties": { "campaign_id": { "type": "string", "description": "Gift-vouchers campaign ID. The campaign must be of type GIFT_VOUCHERS." }, "balance": { "type": "number", "minimum": 0, "description": "Gift voucher balance. Must be a non-negative number." } }, "required": [ "campaign_id", "balance" ], "additionalProperties": false }, "VLRewardListResponse": { "type": "object", "description": "Paginated list of rewards.", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/VLRewardDTO" } }, "cursor": { "oneOf": [ { "$ref": "#/components/schemas/PaginationCursor" }, { "type": "null" } ], "description": "Null when there are no more pages." }, "object": { "type": "string", "const": "list" } }, "required": [ "data", "cursor", "object" ] }, "VLRewardActivityListResponse": { "type": "object", "description": "Paginated list of reward activities.", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/VLRewardActivityDTO" } }, "cursor": { "oneOf": [ { "$ref": "#/components/schemas/PaginationCursor" }, { "type": "null" } ], "description": "Null when there are no more pages." }, "object": { "type": "string", "const": "list" } }, "required": [ "data", "cursor", "object" ] }, "VLRewardActivityDTO": { "type": "object", "description": "Reward activity audit-log entry.", "properties": { "id": { "type": "string", "description": "Unique activity identifier." }, "type": { "type": "string", "enum": [ "vl.reward.created", "vl.reward.updated", "vl.reward.deleted", "vl.reward.assigned", "vl.reward.unassigned", "vl.reward.activated", "vl.reward.deactivated", "vl.reward.drafted" ], "description": "Activity type." }, "data": { "type": "object", "description": "Activity payload. Always contains `reward`.\nFor `assigned` / `unassigned` types also includes `program` and `program_reward`.\n", "properties": { "reward": { "$ref": "#/components/schemas/VLRewardDTO" } }, "required": [ "reward" ], "additionalProperties": true }, "created_at": { "type": "string", "format": "date-time", "description": "ISO 8601 timestamp." }, "group_id": { "type": "string", "description": "Correlation group identifier." }, "source": { "$ref": "#/components/schemas/ActivitySource", "description": "Origin of the activity." }, "reward_id": { "type": "string", "description": "Reward this activity belongs to." } }, "required": [ "id", "type", "data", "created_at", "reward_id" ] }, "VLRewardsFilters": { "type": "object", "description": "Filter criteria for the rewards list.", "properties": { "junction": { "oneOf": [ { "type": "string", "enum": [ "AND", "OR" ] }, { "type": "null" } ], "description": "Logical junction between field filters. Default AND." }, "id": { "oneOf": [ { "$ref": "#/components/schemas/IdFilterField" }, { "type": "null" } ], "description": "Filter by reward ID." }, "name": { "oneOf": [ { "$ref": "#/components/schemas/StringFilterField" }, { "type": "null" } ], "description": "Filter by reward name." }, "type": { "oneOf": [ { "$ref": "#/components/schemas/RewardTypeFilterField" }, { "type": "null" } ], "description": "Filter by reward type (MATERIAL / DIGITAL)." }, "created_at": { "oneOf": [ { "$ref": "#/components/schemas/DateFilterField" }, { "type": "null" } ], "description": "Filter by creation date." } }, "additionalProperties": false }, "VLRewardActivitiesFilters": { "type": "object", "description": "Filter criteria for the reward activities list.", "properties": { "junction": { "oneOf": [ { "type": "string", "enum": [ "AND", "OR" ] }, { "type": "null" } ], "description": "Logical junction between field filters." }, "id": { "oneOf": [ { "$ref": "#/components/schemas/IdFilterField" }, { "type": "null" } ], "description": "Filter by activity ID." }, "type": { "oneOf": [ { "$ref": "#/components/schemas/ActivityTypeFilterField" }, { "type": "null" } ], "description": "Filter by activity type." }, "created_at": { "oneOf": [ { "$ref": "#/components/schemas/DateFilterField" }, { "type": "null" } ], "description": "Filter by creation date." } }, "additionalProperties": false }, "IdFilterField": { "type": "object", "description": "ID-based filter. Conditions: $is, $is_not, $in (max 100), $not_in (max 100).", "properties": { "conditions": { "type": "object", "properties": { "$is": { "$ref": "#/components/schemas/StringOrSingleArray" }, "$is_not": { "$ref": "#/components/schemas/StringOrSingleArray" }, "$in": { "$ref": "#/components/schemas/StringOrIdBatchArray" }, "$not_in": { "$ref": "#/components/schemas/StringOrIdBatchArray" } }, "additionalProperties": false, "minProperties": 1 } }, "required": [ "conditions" ], "additionalProperties": false }, "StringFilterField": { "type": "object", "description": "String-based filter. Supports pattern, containment, and presence conditions.", "properties": { "conditions": { "type": "object", "properties": { "$is": { "$ref": "#/components/schemas/StringOrSingleArray" }, "$is_not": { "$ref": "#/components/schemas/StringOrSingleArray" }, "$contains": { "$ref": "#/components/schemas/StringOrSingleArray" }, "$not_contain": { "$ref": "#/components/schemas/StringOrSingleArray" }, "$starts_with": { "$ref": "#/components/schemas/StringOrSingleArray" }, "$ends_with": { "$ref": "#/components/schemas/StringOrSingleArray" }, "$in": { "$ref": "#/components/schemas/StringOrBatchArray" }, "$not_in": { "$ref": "#/components/schemas/StringOrBatchArray" }, "$has_value": { "$ref": "#/components/schemas/PresenceValue" }, "$is_unknown": { "$ref": "#/components/schemas/PresenceValue" } }, "additionalProperties": false, "minProperties": 1 } }, "required": [ "conditions" ], "additionalProperties": false }, "RewardTypeFilterField": { "type": "object", "description": "Enum filter for reward type.", "properties": { "conditions": { "type": "object", "properties": { "$is": { "$ref": "#/components/schemas/RewardTypeValue" }, "$is_not": { "$ref": "#/components/schemas/RewardTypeValue" }, "$in": { "$ref": "#/components/schemas/RewardTypeBatchValue" }, "$not_in": { "$ref": "#/components/schemas/RewardTypeBatchValue" } }, "additionalProperties": false, "minProperties": 1 } }, "required": [ "conditions" ], "additionalProperties": false }, "ActivityTypeFilterField": { "type": "object", "description": "Enum filter for activity type.", "properties": { "conditions": { "type": "object", "properties": { "$is": { "$ref": "#/components/schemas/ActivityTypeValue" }, "$is_not": { "$ref": "#/components/schemas/ActivityTypeValue" }, "$in": { "$ref": "#/components/schemas/ActivityTypeBatchValue" }, "$not_in": { "$ref": "#/components/schemas/ActivityTypeBatchValue" } }, "additionalProperties": false, "minProperties": 1 } }, "required": [ "conditions" ], "additionalProperties": false }, "DateFilterField": { "type": "object", "description": "Date-based filter. Supports absolute dates, relative days-ago, and presence checks.", "properties": { "conditions": { "type": "object", "properties": { "$before": { "$ref": "#/components/schemas/DateValue" }, "$after": { "$ref": "#/components/schemas/DateValue" }, "$is": { "$ref": "#/components/schemas/DaysAgoValue" }, "$more_than": { "$ref": "#/components/schemas/DaysAgoValue" }, "$less_than": { "$ref": "#/components/schemas/DaysAgoValue" }, "$has_value": { "$ref": "#/components/schemas/PresenceValue" }, "$is_unknown": { "$ref": "#/components/schemas/PresenceValue" } }, "additionalProperties": false, "minProperties": 1 } }, "required": [ "conditions" ], "additionalProperties": false }, "StringOrSingleArray": { "description": "A single string or a one-element string array.", "oneOf": [ { "type": "string" }, { "type": "array", "items": { "type": "string" }, "minItems": 1, "maxItems": 1 }, { "type": "null" } ] }, "StringOrBatchArray": { "description": "A single string or a string array (max 10 items).", "oneOf": [ { "type": "string" }, { "type": "array", "items": { "type": "string" }, "minItems": 1, "maxItems": 10 }, { "type": "null" } ] }, "StringOrIdBatchArray": { "description": "A single string or a string array (max 100 items, for ID fields).", "oneOf": [ { "type": "string" }, { "type": "array", "items": { "type": "string" }, "minItems": 1, "maxItems": 100 }, { "type": "null" } ] }, "PresenceValue": { "description": "Presence-check value (any truthy string or empty array).", "oneOf": [ { "type": "string" }, { "type": "array", "maxItems": 1 }, { "type": "null" } ] }, "DateValue": { "description": "ISO 8601 date-time string or single-element array.", "oneOf": [ { "type": "string", "format": "date-time" }, { "type": "array", "items": { "type": "string", "format": "date-time" }, "minItems": 1, "maxItems": 1 }, { "type": "null" } ] }, "DaysAgoValue": { "description": "Non-negative integer (days ago) encoded as a string, or single-element array.", "oneOf": [ { "type": "string", "pattern": "^\\d+$" }, { "type": "array", "items": { "type": "string", "pattern": "^\\d+$" }, "minItems": 1, "maxItems": 1 }, { "type": "null" } ] }, "RewardTypeValue": { "description": "Single reward-type enum value.", "oneOf": [ { "type": "string", "enum": [ "MATERIAL", "DIGITAL" ] }, { "type": "array", "items": { "type": "string", "enum": [ "MATERIAL", "DIGITAL" ] }, "minItems": 1, "maxItems": 1 }, { "type": "null" } ] }, "RewardTypeBatchValue": { "description": "Reward-type enum values (max 10).", "oneOf": [ { "type": "string", "enum": [ "MATERIAL", "DIGITAL" ] }, { "type": "array", "items": { "type": "string", "enum": [ "MATERIAL", "DIGITAL" ] }, "minItems": 1, "maxItems": 10 }, { "type": "null" } ] }, "ActivityTypeValue": { "description": "Single activity-type enum value.", "oneOf": [ { "type": "string", "enum": [ "vl.reward.created", "vl.reward.updated", "vl.reward.deleted", "vl.reward.assigned", "vl.reward.unassigned", "vl.reward.activated", "vl.reward.deactivated", "vl.reward.drafted" ] }, { "type": "array", "items": { "type": "string", "enum": [ "vl.reward.created", "vl.reward.updated", "vl.reward.deleted", "vl.reward.assigned", "vl.reward.unassigned", "vl.reward.activated", "vl.reward.deactivated", "vl.reward.drafted" ] }, "minItems": 1, "maxItems": 1 }, { "type": "null" } ] }, "ActivityTypeBatchValue": { "description": "Activity-type enum values (max 10).", "oneOf": [ { "type": "string", "enum": [ "vl.reward.created", "vl.reward.updated", "vl.reward.deleted", "vl.reward.assigned", "vl.reward.unassigned", "vl.reward.activated", "vl.reward.deactivated", "vl.reward.drafted" ] }, { "type": "array", "items": { "type": "string", "enum": [ "vl.reward.created", "vl.reward.updated", "vl.reward.deleted", "vl.reward.assigned", "vl.reward.unassigned", "vl.reward.activated", "vl.reward.deactivated", "vl.reward.drafted" ] }, "minItems": 1, "maxItems": 10 }, { "type": "null" } ] } } } }