# unPLUG Loyalty Management API v1, OpenAPI 3.1. # Docs: https://docs.unplugdining.com Support: support@unplugdining.com # Items with x-status: coming-soon are designed but not released yet. openapi: 3.1.0 info: title: unPLUG Loyalty Management API summary: 'Automate what the unPLUG Dashboard does: offers, challenges, points adjustments and reports.' description: |- For brands that want their own tools to do what the unPLUG Dashboard does: create, publish and grant offers, run challenges, adjust points, merge members and read reports. You don't need it to run loyalty in your app or website; that is the App API: https://docs.unplugdining.com/reference Every operation takes a secret key, server side only, with the scope it lists. Operations and schemas marked `x-status: coming-soon` (and tagged "Coming soon") are designed but not released; their shape can still change. Guides and examples: https://docs.unplugdining.com/management version: v1 contact: name: unPLUG developer support email: support@unplugdining.com url: https://docs.unplugdining.com/support servers: - url: https://api.unplugdining.com/v1 description: Production (uk_live_ keys) - url: https://sandbox.api.unplugdining.com/v1 description: Sandbox (uk_test_ keys) security: - secretKey: [] tags: - name: Offers - name: Challenges - name: Member support - name: Reports - name: Coming soon description: Designed but not released yet. paths: /members/{id}/merge: post: operationId: mergeMembers summary: Merge two members tags: - Member support - Coming soon x-status: coming-soon description: 'Coming soon. Scope: `members:write`.' security: - secretKey: [] parameters: - $ref: '#/components/parameters/Id' - $ref: '#/components/parameters/IdempotencyKey' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/MergeRequest' responses: '200': description: OK headers: Request-Id: $ref: '#/components/headers/Request-Id' content: application/json: schema: $ref: '#/components/schemas/Member' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '422': $ref: '#/components/responses/Unprocessable' '429': $ref: '#/components/responses/TooManyRequests' /members/{id}/points_adjustments: post: operationId: createPointsAdjustment summary: Adjust points tags: - Member support description: 'Scope: `points:adjust`.' security: - secretKey: [] parameters: - $ref: '#/components/parameters/Id' - $ref: '#/components/parameters/IdempotencyKeyRequired' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/PointsAdjustmentRequest' responses: '201': description: Created. headers: Request-Id: $ref: '#/components/headers/Request-Id' content: application/json: schema: $ref: '#/components/schemas/ActivityEntry' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '410': $ref: '#/components/responses/Gone' '422': $ref: '#/components/responses/Unprocessable' '429': $ref: '#/components/responses/TooManyRequests' /challenges: get: operationId: listAllChallenges summary: List challenges tags: - Challenges - Coming soon x-status: coming-soon description: |- Coming soon. All your challenges in any status, newest first. Scope: `challenges:write`. security: - secretKey: [] parameters: - $ref: '#/components/parameters/ChallengeStatus' - $ref: '#/components/parameters/Limit' - $ref: '#/components/parameters/Cursor' responses: '200': description: OK headers: Request-Id: $ref: '#/components/headers/Request-Id' content: application/json: schema: allOf: - $ref: '#/components/schemas/CursorList' - type: object properties: data: type: array items: $ref: '#/components/schemas/Challenge' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '429': $ref: '#/components/responses/TooManyRequests' post: operationId: createChallenge summary: Create a challenge tags: - Challenges - Coming soon x-status: coming-soon description: 'Coming soon. Scope: `challenges:write`.' security: - secretKey: [] parameters: - $ref: '#/components/parameters/IdempotencyKey' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ChallengeWrite' responses: '201': description: OK headers: Request-Id: $ref: '#/components/headers/Request-Id' content: application/json: schema: $ref: '#/components/schemas/Challenge' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '429': $ref: '#/components/responses/TooManyRequests' /challenges/{id}: patch: operationId: updateChallenge summary: Update a challenge tags: - Challenges - Coming soon x-status: coming-soon description: 'Coming soon. Scope: `challenges:write`.' security: - secretKey: [] parameters: - $ref: '#/components/parameters/Id' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ChallengeWrite' responses: '200': description: OK headers: Request-Id: $ref: '#/components/headers/Request-Id' content: application/json: schema: $ref: '#/components/schemas/Challenge' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/Conflict' '429': $ref: '#/components/responses/TooManyRequests' /challenges/{id}/publish: post: operationId: publishChallenge summary: Publish a challenge tags: - Challenges - Coming soon x-status: coming-soon description: |- Coming soon. `409 invalid_state` when the challenge's status doesn't allow it. Scope: `challenges:write`. security: - secretKey: [] parameters: - $ref: '#/components/parameters/Id' - $ref: '#/components/parameters/IdempotencyKey' responses: '200': description: OK headers: Request-Id: $ref: '#/components/headers/Request-Id' content: application/json: schema: $ref: '#/components/schemas/Challenge' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/Conflict' '429': $ref: '#/components/responses/TooManyRequests' /challenges/{id}/pause: post: operationId: pauseChallenge summary: Pause a challenge tags: - Challenges - Coming soon x-status: coming-soon description: |- Coming soon. `409 invalid_state` when the challenge's status doesn't allow it. Scope: `challenges:write`. security: - secretKey: [] parameters: - $ref: '#/components/parameters/Id' - $ref: '#/components/parameters/IdempotencyKey' responses: '200': description: OK headers: Request-Id: $ref: '#/components/headers/Request-Id' content: application/json: schema: $ref: '#/components/schemas/Challenge' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/Conflict' '429': $ref: '#/components/responses/TooManyRequests' /challenges/{id}/end: post: operationId: endChallenge summary: End a challenge tags: - Challenges - Coming soon x-status: coming-soon description: |- Coming soon. `409 invalid_state` when the challenge's status doesn't allow it. Scope: `challenges:write`. security: - secretKey: [] parameters: - $ref: '#/components/parameters/Id' - $ref: '#/components/parameters/IdempotencyKey' responses: '200': description: OK headers: Request-Id: $ref: '#/components/headers/Request-Id' content: application/json: schema: $ref: '#/components/schemas/Challenge' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/Conflict' '429': $ref: '#/components/responses/TooManyRequests' /challenges/{id}/preview: post: operationId: previewChallenge summary: Preview a challenge tags: - Challenges - Coming soon x-status: coming-soon description: |- Coming soon. Dry run: audience, expected completions and cost. Scope: `challenges:write`. security: - secretKey: [] parameters: - $ref: '#/components/parameters/Id' - $ref: '#/components/parameters/IdempotencyKey' responses: '200': description: OK headers: Request-Id: $ref: '#/components/headers/Request-Id' content: application/json: schema: $ref: '#/components/schemas/ChallengePreview' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '429': $ref: '#/components/responses/TooManyRequests' /challenges/{id}/enrollments: post: operationId: enrollInChallenge summary: Enroll members tags: - Challenges - Coming soon x-status: coming-soon description: 'Coming soon. Scope: `challenges:write`.' security: - secretKey: [] parameters: - $ref: '#/components/parameters/Id' - $ref: '#/components/parameters/IdempotencyKeyRequired' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/EnrollmentRequest' responses: '200': description: OK headers: Request-Id: $ref: '#/components/headers/Request-Id' content: application/json: schema: $ref: '#/components/schemas/EnrollmentResult' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/Conflict' '422': $ref: '#/components/responses/Unprocessable' '429': $ref: '#/components/responses/TooManyRequests' /challenge_templates: get: operationId: listChallengeTemplates summary: List challenge templates tags: - Challenges - Coming soon x-status: coming-soon description: 'Coming soon. Scope: `challenges:write`.' security: - secretKey: [] parameters: - $ref: '#/components/parameters/Limit' - $ref: '#/components/parameters/Cursor' responses: '200': description: OK headers: Request-Id: $ref: '#/components/headers/Request-Id' content: application/json: schema: allOf: - $ref: '#/components/schemas/CursorList' - type: object properties: data: type: array items: $ref: '#/components/schemas/ChallengeTemplate' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '429': $ref: '#/components/responses/TooManyRequests' /offers: post: operationId: createOffer summary: Create an offer tags: - Offers - Coming soon x-status: coming-soon description: |- Coming soon. Creates a draft. Scope: `offers:write`. security: - secretKey: [] parameters: - $ref: '#/components/parameters/IdempotencyKey' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/OfferWrite' responses: '201': description: OK headers: Request-Id: $ref: '#/components/headers/Request-Id' content: application/json: schema: $ref: '#/components/schemas/Offer' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '429': $ref: '#/components/responses/TooManyRequests' get: operationId: listOffers summary: List offers tags: - Offers - Coming soon x-status: coming-soon description: 'Coming soon. Scope: `offers:write`.' security: - secretKey: [] parameters: - $ref: '#/components/parameters/Limit' - $ref: '#/components/parameters/Cursor' responses: '200': description: OK headers: Request-Id: $ref: '#/components/headers/Request-Id' content: application/json: schema: allOf: - $ref: '#/components/schemas/CursorList' - type: object properties: data: type: array items: $ref: '#/components/schemas/Offer' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '429': $ref: '#/components/responses/TooManyRequests' /offers/{id}: get: operationId: getOffer summary: Get an offer tags: - Offers - Coming soon x-status: coming-soon description: 'Coming soon. Scope: `offers:write`.' security: - secretKey: [] parameters: - $ref: '#/components/parameters/Id' responses: '200': description: OK headers: Request-Id: $ref: '#/components/headers/Request-Id' content: application/json: schema: $ref: '#/components/schemas/Offer' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '429': $ref: '#/components/responses/TooManyRequests' patch: operationId: updateOffer summary: Update an offer tags: - Offers - Coming soon x-status: coming-soon description: |- Coming soon. A draft is edited in place. Editing a scheduled or live offer creates a new version; members keep the version they got. An ended offer returns `409 invalid_state`. Scope: `offers:write`. security: - secretKey: [] parameters: - $ref: '#/components/parameters/Id' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/OfferWrite' responses: '200': description: OK headers: Request-Id: $ref: '#/components/headers/Request-Id' content: application/json: schema: $ref: '#/components/schemas/Offer' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/Conflict' '429': $ref: '#/components/responses/TooManyRequests' /offers/{id}/publish: post: operationId: publishOffer summary: Publish an offer tags: - Offers - Coming soon x-status: coming-soon description: |- Coming soon. `409 invalid_state` when the offer's status doesn't allow it. Scope: `offers:write`. security: - secretKey: [] parameters: - $ref: '#/components/parameters/Id' - $ref: '#/components/parameters/IdempotencyKey' responses: '200': description: OK headers: Request-Id: $ref: '#/components/headers/Request-Id' content: application/json: schema: $ref: '#/components/schemas/Offer' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/Conflict' '429': $ref: '#/components/responses/TooManyRequests' /offers/{id}/pause: post: operationId: pauseOffer summary: Pause an offer tags: - Offers - Coming soon x-status: coming-soon description: |- Coming soon. `409 invalid_state` when the offer's status doesn't allow it. Scope: `offers:write`. security: - secretKey: [] parameters: - $ref: '#/components/parameters/Id' - $ref: '#/components/parameters/IdempotencyKey' responses: '200': description: OK headers: Request-Id: $ref: '#/components/headers/Request-Id' content: application/json: schema: $ref: '#/components/schemas/Offer' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/Conflict' '429': $ref: '#/components/responses/TooManyRequests' /offers/{id}/resume: post: operationId: resumeOffer summary: Resume an offer tags: - Offers - Coming soon x-status: coming-soon description: |- Coming soon. `409 invalid_state` when the offer's status doesn't allow it. Scope: `offers:write`. security: - secretKey: [] parameters: - $ref: '#/components/parameters/Id' - $ref: '#/components/parameters/IdempotencyKey' responses: '200': description: OK headers: Request-Id: $ref: '#/components/headers/Request-Id' content: application/json: schema: $ref: '#/components/schemas/Offer' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/Conflict' '429': $ref: '#/components/responses/TooManyRequests' /offers/{id}/end: post: operationId: endOffer summary: End an offer tags: - Offers - Coming soon x-status: coming-soon description: |- Coming soon. `409 invalid_state` when the offer's status doesn't allow it. Wallet items already granted stay usable until their own expiry. Scope: `offers:write`. security: - secretKey: [] parameters: - $ref: '#/components/parameters/Id' - $ref: '#/components/parameters/IdempotencyKey' responses: '200': description: OK headers: Request-Id: $ref: '#/components/headers/Request-Id' content: application/json: schema: $ref: '#/components/schemas/Offer' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/Conflict' '429': $ref: '#/components/responses/TooManyRequests' /offers/{id}/preview: post: operationId: previewOffer summary: Preview an offer tags: - Offers - Coming soon x-status: coming-soon description: |- Coming soon. Dry run. Scope: `offers:write`. security: - secretKey: [] parameters: - $ref: '#/components/parameters/Id' - $ref: '#/components/parameters/IdempotencyKey' responses: '200': description: OK headers: Request-Id: $ref: '#/components/headers/Request-Id' content: application/json: schema: $ref: '#/components/schemas/OfferPreview' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '429': $ref: '#/components/responses/TooManyRequests' /offers/{id}/grants: post: operationId: grantOffer summary: Grant an offer tags: - Offers - Coming soon x-status: coming-soon description: |- Coming soon. Each grant becomes a wallet item. The same `grant_ref` and member never grant twice. Scope: `offers:write`. security: - secretKey: [] parameters: - $ref: '#/components/parameters/Id' - $ref: '#/components/parameters/IdempotencyKeyRequired' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/GrantRequest' responses: '200': description: OK headers: Request-Id: $ref: '#/components/headers/Request-Id' content: application/json: schema: $ref: '#/components/schemas/GrantResult' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/Conflict' '422': $ref: '#/components/responses/Unprocessable' '429': $ref: '#/components/responses/TooManyRequests' /offers/{id}/code_batches: post: operationId: createCodeBatch summary: Create a code batch tags: - Offers - Coming soon x-status: coming-soon description: 'Coming soon. Scope: `offers:write`.' security: - secretKey: [] parameters: - $ref: '#/components/parameters/Id' - $ref: '#/components/parameters/IdempotencyKey' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CodeBatchRequest' responses: '201': description: OK headers: Request-Id: $ref: '#/components/headers/Request-Id' content: application/json: schema: $ref: '#/components/schemas/CodeBatch' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/Conflict' '429': $ref: '#/components/responses/TooManyRequests' /offers/{id}/code_batches/{batch_id}/codes: get: operationId: listBatchCodes summary: List a batch's codes tags: - Offers - Coming soon x-status: coming-soon description: |- Coming soon. JSON pages, or the whole batch as CSV with `Accept: text/csv`. Scope: `offers:write`. security: - secretKey: [] parameters: - $ref: '#/components/parameters/Id' - name: batch_id in: path required: true schema: type: string format: uuid - $ref: '#/components/parameters/Limit' - $ref: '#/components/parameters/Cursor' responses: '200': description: OK headers: Request-Id: $ref: '#/components/headers/Request-Id' content: application/json: schema: allOf: - $ref: '#/components/schemas/CursorList' - type: object properties: data: type: array items: $ref: '#/components/schemas/PromoCode' text/csv: schema: type: string '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/Conflict' '429': $ref: '#/components/responses/TooManyRequests' /offers/{id}/code_batches/{batch_id}/void: post: operationId: voidCodeBatch summary: Void a code batch tags: - Offers - Coming soon x-status: coming-soon description: 'Coming soon. Scope: `offers:write`.' security: - secretKey: [] parameters: - $ref: '#/components/parameters/Id' - name: batch_id in: path required: true schema: type: string format: uuid - $ref: '#/components/parameters/IdempotencyKey' responses: '200': description: OK headers: Request-Id: $ref: '#/components/headers/Request-Id' content: application/json: schema: $ref: '#/components/schemas/CodeBatch' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/Conflict' '429': $ref: '#/components/responses/TooManyRequests' /reports/program_summary: get: operationId: getProgramSummary summary: Program summary report tags: - Reports - Coming soon x-status: coming-soon description: |- Coming soon. Days are local dates in the location's time zone, or the brand's. Scope: `reports:read`. security: - secretKey: [] parameters: - name: from in: query required: true schema: type: string format: date description: Local date, included. - name: to in: query required: true schema: type: string format: date description: Local date, included. - name: location_id in: query schema: type: string format: uuid responses: '200': description: OK headers: Request-Id: $ref: '#/components/headers/Request-Id' content: application/json: schema: $ref: '#/components/schemas/ProgramSummaryReport' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '429': $ref: '#/components/responses/TooManyRequests' /reports/rewards: get: operationId: getRewardsReport summary: Rewards report tags: - Reports - Coming soon x-status: coming-soon description: 'Coming soon. Scope: `reports:read`.' security: - secretKey: [] parameters: - name: from in: query required: true schema: type: string format: date description: Local date, included. - name: to in: query required: true schema: type: string format: date description: Local date, included. responses: '200': description: OK headers: Request-Id: $ref: '#/components/headers/Request-Id' content: application/json: schema: $ref: '#/components/schemas/RewardsReport' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '429': $ref: '#/components/responses/TooManyRequests' components: securitySchemes: secretKey: type: http scheme: bearer bearerFormat: uk_live_... or uk_test_... description: Secret key, server side only. Scopes limit what each key can do. parameters: IdempotencyKey: name: Idempotency-Key in: header required: false description: 'Any string up to 255 characters; use a UUID v4. Kept 24 hours per key (or member) and endpoint. Same key and body replays the first response with `Idempotent-Replayed: true`.' schema: type: string maxLength: 255 IdempotencyKeyRequired: name: Idempotency-Key in: header required: true description: Required on this endpoint. Any string up to 255 characters; use a UUID v4. Missing returns `400 idempotency_key_required`. schema: type: string maxLength: 255 Limit: name: limit in: query schema: type: integer minimum: 1 maximum: 100 default: 25 Cursor: name: cursor in: query schema: type: string description: '`next_cursor` from the previous page.' Id: name: id in: path required: true schema: type: string format: uuid ChallengeStatus: name: status in: query description: Only challenges in this status. schema: type: string enum: - draft - scheduled - live - paused - ended headers: Request-Id: description: Quote it to support. schema: type: string examples: - req_7Hq2kD9xLm RateLimit-Limit: schema: type: integer RateLimit-Remaining: schema: type: integer RateLimit-Reset: schema: type: integer description: Seconds until the window resets. Retry-After: schema: type: integer description: Seconds. Idempotent-Replayed: schema: type: string enum: - 'true' responses: BadRequest: description: '`invalid_request`, `invalid_param`, `missing_param` or `idempotency_key_required`.' headers: Request-Id: $ref: '#/components/headers/Request-Id' content: application/problem+json: schema: $ref: '#/components/schemas/Problem' Unauthorized: description: '`invalid_api_key` or `token_expired`.' headers: Request-Id: $ref: '#/components/headers/Request-Id' content: application/problem+json: schema: $ref: '#/components/schemas/Problem' Forbidden: description: '`missing_scope`, or a member token calling something it can''t.' headers: Request-Id: $ref: '#/components/headers/Request-Id' content: application/problem+json: schema: $ref: '#/components/schemas/Problem' NotFound: description: '`not_found` or a resource-specific not-found code.' headers: Request-Id: $ref: '#/components/headers/Request-Id' content: application/problem+json: schema: $ref: '#/components/schemas/Problem' Gone: description: '`member_deleted`.' headers: Request-Id: $ref: '#/components/headers/Request-Id' content: application/problem+json: schema: $ref: '#/components/schemas/Problem' Conflict: description: '`request_in_progress`, `phone_in_use`, `order_already_exists`, `redemption_not_reserved`, or `invalid_state` when the object''s status doesn''t allow the action.' headers: Request-Id: $ref: '#/components/headers/Request-Id' content: application/problem+json: schema: $ref: '#/components/schemas/Problem' Unprocessable: description: The request is well formed but can't be done. `idempotency_key_reused` and business errors such as `insufficient_points`. headers: Request-Id: $ref: '#/components/headers/Request-Id' content: application/problem+json: schema: $ref: '#/components/schemas/Problem' TooManyRequests: description: '`rate_limited`.' headers: Request-Id: $ref: '#/components/headers/Request-Id' Retry-After: $ref: '#/components/headers/Retry-After' content: application/problem+json: schema: $ref: '#/components/schemas/Problem' NoContent: description: No content. headers: Request-Id: $ref: '#/components/headers/Request-Id' schemas: Problem: type: object properties: type: type: string description: Link to the docs for this error. format: uri examples: - https://docs.unplugdining.com/reference/errors#insufficient_points title: type: string examples: - Not enough points status: type: integer examples: - 422 code: $ref: '#/components/schemas/ErrorCode' detail: type: string description: A sentence about this occurrence. examples: - This reward costs 500 Beans. The member has 420. param: type: - string - 'null' description: The request field at fault, when there is one. order_id: type: string format: uuid description: 'Only on `order_already_exists`: the order that was already credited.' request_id: type: string description: Same as the `Request-Id` header. examples: - req_7Hq2kD9xLm required: - type - title - status - code - request_id description: RFC 9457 problem details, served as `application/problem+json`. ErrorCode: type: string description: Machine-readable error code. May grow. enum: - invalid_request - invalid_param - missing_param - invalid_api_key - token_expired - missing_scope - not_found - member_not_found - member_deleted - external_id_taken - phone_in_use - idempotency_key_required - idempotency_key_reused - request_in_progress - rate_limited - insufficient_points - reward_not_found - reward_not_applicable - reward_expired - reward_already_used - code_invalid - code_expired - code_limit_reached - redemption_expired - redemption_not_reserved - one_redemption_per_order - order_already_exists - refund_exceeds_order - location_not_found - challenge_not_joinable - invalid_state - internal_error - service_unavailable CursorList: type: object properties: data: type: array items: {} has_more: type: boolean description: True when another page exists. next_cursor: type: - string - 'null' description: Pass as `cursor` to get the next page. required: - data - has_more - next_cursor description: Cursor-paginated list. `?limit=` (1 to 100, default 25) and `?cursor=`. TierRef: type: object properties: id: type: string format: uuid name: type: string examples: - Green required: - id - name Discount: type: object properties: type: type: string enum: - amount - percent - free_item - bogo amount_cents: type: integer description: For `amount`. percent: type: number description: For `percent`. items: type: array items: type: object properties: pos_item_id: type: string name: type: string description: Item scope, by Square variation id. categories: type: array items: type: object properties: pos_category_id: type: string name: type: string description: Category scope. max_items: type: integer required: - type AvailableTime: type: object properties: days: type: array items: type: string enum: - mon - tue - wed - thu - fri - sat - sun start: type: string description: Local time, HH:MM. examples: - 07:00 end: type: string description: Local time, HH:MM. examples: - '11:00' Rules: type: object properties: min_subtotal_cents: type: integer description: Integer cents. minimum: 0 channels: type: array items: type: string enum: - app - web location_ids: type: array items: type: string format: uuid fulfillment: type: array items: type: string enum: - pickup - delivery - curbside - dine_in available_times: type: array items: $ref: '#/components/schemas/AvailableTime' tier_ids: type: array items: type: string format: uuid description: Empty arrays mean no limit. Member: type: object properties: id: type: string format: uuid external_id: type: - string - 'null' maxLength: 128 examples: - usr_10482 status: type: string enum: - active - deleted first_name: type: - string - 'null' examples: - Maya last_name: type: - string - 'null' examples: - Lopez email: type: - string - 'null' format: email examples: - maya@example.com phone: type: - string - 'null' description: E.164. examples: - '+15125550142' phone_verified: type: boolean birthday: type: - string - 'null' format: date examples: - '1994-03-18' points_balance: type: integer examples: - 420 lifetime_points: type: integer examples: - 1880 tier: $ref: '#/components/schemas/TierRef' next_tier: type: - object - 'null' properties: id: type: string format: uuid name: type: string points_needed: type: integer communication_preferences: type: object properties: email_marketing: type: boolean sms_marketing: type: boolean push_marketing: type: boolean metadata: type: object additionalProperties: type: string maxLength: 500 maxProperties: 20 linked_existing: type: boolean description: 'Only on create: true when an existing member was linked by verified phone.' enrolled_at: type: string format: date-time created_at: type: string format: date-time updated_at: type: string format: date-time required: - id - status - points_balance - lifetime_points - tier - created_at - updated_at MergeRequest: type: object properties: source_member_id: type: string format: uuid required: - source_member_id ActivityEntry: type: object properties: id: type: string format: uuid type: type: string description: May grow. `expire` is coming soon. enum: - earn - bonus - redeem - adjust - reverse - expire points: type: integer description: Signed. balance_after: type: integer description: type: string examples: - Order app-30417 order_id: type: - string - 'null' format: uuid reward_id: type: - string - 'null' format: uuid adjustment_reason: type: - string - 'null' enum: - goodwill - correction - migration - other - null created_at: type: string format: date-time required: - id - type - points - balance_after - created_at PointsAdjustmentRequest: type: object properties: points: type: integer description: Signed. Negative values never take the balance below zero. reason: type: string enum: - goodwill - correction - migration - other note: type: string counts_toward_tier: type: boolean default: false required: - points - reason Budget: type: object properties: max_redemptions: type: - integer - 'null' max_discount_cents: type: - integer - 'null' used_redemptions: type: integer readOnly: true used_discount_cents: type: integer readOnly: true Offer: type: object properties: id: type: string format: uuid name: type: string description: type: string status: type: string enum: - draft - scheduled - live - paused - ended version: type: integer discount: $ref: '#/components/schemas/Discount' rules: $ref: '#/components/schemas/Rules' distribution: type: string enum: - granted - shared_code - unique_codes shared_code: type: - string - 'null' per_member_limit: type: - integer - 'null' budget: $ref: '#/components/schemas/Budget' starts_at: type: - string - 'null' format: date-time ends_at: type: - string - 'null' format: date-time wallet_expiry_days: type: - integer - 'null' created_by: type: string enum: - api - dashboard - campaign required: - id - name - status - version - discount - distribution description: Coming soon. x-status: coming-soon OfferWrite: type: object properties: name: type: string description: type: string discount: $ref: '#/components/schemas/Discount' rules: $ref: '#/components/schemas/Rules' distribution: type: string enum: - granted - shared_code - unique_codes shared_code: type: string per_member_limit: type: integer budget: type: object properties: max_redemptions: type: integer max_discount_cents: type: integer starts_at: type: string format: date-time ends_at: type: string format: date-time wallet_expiry_days: type: integer description: Coming soon. OfferPreview: type: object properties: eligible_members: type: integer expected_redemptions: type: integer expected_cost_cents: type: integer warnings: type: array items: type: string GrantRequest: type: object properties: grant_ref: type: string examples: - nov-winback-1 member_ids: type: array items: type: string format: uuid maxItems: 500 required: - grant_ref - member_ids Skipped: type: object properties: member_id: type: string format: uuid reason: type: string GrantResult: type: object properties: granted: type: integer skipped: type: array items: $ref: '#/components/schemas/Skipped' CodeBatchRequest: type: object properties: prefix: type: string examples: - HOLIDAY quantity: type: integer examples: - 5000 required: - prefix - quantity CodeBatch: type: object properties: id: type: string format: uuid offer_id: type: string format: uuid prefix: type: string quantity: type: integer status: type: string created_at: type: string format: date-time PromoCode: type: object properties: code: type: string status: type: string Challenge: type: object properties: id: type: string format: uuid name: type: string description: type: string image_url: type: - string - 'null' format: uri type: type: string enum: - visits - streak - spend - menu_discovery goal: type: object properties: target: type: integer unit: type: string enum: - visits - periods - cents - items period: type: - string - 'null' enum: - day - week - null grace_periods: type: - integer - 'null' item_set: type: array items: type: object qualifying: type: object properties: min_subtotal_cents: type: integer description: Integer cents. minimum: 0 channels: type: array items: type: string location_ids: type: array items: type: string format: uuid fulfillment: type: array items: type: string enum: - pickup - delivery - curbside - dine_in available_times: type: array items: $ref: '#/components/schemas/AvailableTime' max_counted_per_day: type: integer examples: - 1 window: oneOf: - type: object properties: kind: type: string const: fixed starts_at: type: string format: date-time ends_at: type: string format: date-time required: - kind - type: object properties: kind: type: string const: rolling days: type: integer examples: - 7 required: - kind enrollment: type: string enum: - automatic - opt_in reward: oneOf: - type: object properties: kind: type: string const: points points: type: integer required: - kind - type: object properties: kind: type: string const: reward reward_id: type: string format: uuid required: - kind max_completions_per_member: type: integer examples: - 1 budget: type: object properties: max_completions: type: - integer - 'null' status: type: string enum: - draft - scheduled - live - paused - ended version: type: integer required: - id - name - type - goal - window - enrollment - reward - status description: Coming soon. x-status: coming-soon ChallengeWrite: type: object properties: name: type: string description: type: string image_url: type: - string - 'null' format: uri type: type: string enum: - visits - streak - spend - menu_discovery goal: type: object properties: target: type: integer unit: type: string enum: - visits - periods - cents - items period: type: - string - 'null' enum: - day - week - null grace_periods: type: - integer - 'null' item_set: type: array items: type: object qualifying: type: object properties: min_subtotal_cents: type: integer description: Integer cents. minimum: 0 channels: type: array items: type: string location_ids: type: array items: type: string format: uuid fulfillment: type: array items: type: string enum: - pickup - delivery - curbside - dine_in available_times: type: array items: $ref: '#/components/schemas/AvailableTime' max_counted_per_day: type: integer examples: - 1 window: oneOf: - type: object properties: kind: type: string const: fixed starts_at: type: string format: date-time ends_at: type: string format: date-time required: - kind - type: object properties: kind: type: string const: rolling days: type: integer examples: - 7 required: - kind enrollment: type: string enum: - automatic - opt_in reward: oneOf: - type: object properties: kind: type: string const: points points: type: integer required: - kind - type: object properties: kind: type: string const: reward reward_id: type: string format: uuid required: - kind max_completions_per_member: type: integer examples: - 1 budget: type: object properties: max_completions: type: - integer - 'null' description: Coming soon. ChallengePreview: type: object properties: audience_members: type: integer expected_completions: type: integer expected_points: type: integer expected_cost_cents: type: integer warnings: type: array items: type: string EnrollmentRequest: type: object properties: member_ids: type: array items: type: string format: uuid maxItems: 500 required: - member_ids EnrollmentResult: type: object properties: enrolled: type: integer skipped: type: array items: $ref: '#/components/schemas/Skipped' ChallengeTemplate: type: object properties: id: type: string examples: - weekly_regular name: type: string description: type: string type: type: string goal: type: object qualifying: type: object window_kind: type: string enum: - fixed - rolling window_days: type: integer enrollment: type: string enum: - automatic - opt_in suggested_reward: type: string ReportFigures: type: object properties: members: type: object properties: total: type: integer new: type: integer active: type: integer points: type: object properties: issued: type: integer redeemed: type: integer adjusted: type: integer outstanding: type: integer rewards: type: object properties: issued: type: integer redeemed: type: integer discount_cents: type: integer orders: type: object properties: member_orders: type: integer member_sales_cents: type: integer non_member_orders: type: integer non_member_sales_cents: type: integer ProgramSummaryReport: type: object properties: from: type: string format: date to: type: string format: date location_id: type: - string - 'null' format: uuid time_zone: type: string currency: type: string description: ISO 4217 code. `USD`. examples: - USD totals: $ref: '#/components/schemas/ReportFigures' days: type: array items: allOf: - type: object properties: date: type: string format: date required: - date - $ref: '#/components/schemas/ReportFigures' description: Coming soon. x-status: coming-soon RewardReportRow: type: object properties: reward_id: type: string format: uuid name: type: string kind: type: string enum: - points - wallet points_cost: type: - integer - 'null' issued: type: integer redeemed: type: integer points_spent: type: integer discount_cents: type: integer RewardsReport: type: object properties: from: type: string format: date to: type: string format: date time_zone: type: string currency: type: string description: ISO 4217 code. `USD`. examples: - USD data: type: array items: $ref: '#/components/schemas/RewardReportRow' description: Coming soon. x-status: coming-soon