Configure a loyalty season

Creates or updates one loyalty campaign (season) together with the shop-level display settings, bonus definitions and reward products it depends on, and optionally activates the program. The campaign id is the upsert key: an existing id updates that season, a new id creates one. The request describes the whole season it names, so a tier or milestone omitted from it is removed from that season; bonuses and reward products are created or updated by id or SKU and never removed. Draft and scheduled seasons accept every change. An active season accepts names, descriptions, images, milestone rewards, tier earn rates and a new end date; thresholds, adding or removing tiers or milestones, the start date and reset rules are refused with FAILED_PRECONDITION listing the fields. Ended seasons are read-only. This method accepts only the versioned x-stash-hmac-signature header, signed over the request body exactly as sent; the legacy stash-hmac-signature header is rejected with UNAUTHENTICATED, because it carries no timestamp and a captured request could be replayed. Applying is idempotent: after a 500, resend the same request. Returns INVALID_ARGUMENT with per-field violations when validation fails, FAILED_PRECONDITION also when the shop's loyalty program is bound to more than one shop, PERMISSION_DENIED when the shop is not enabled for configuration writes, ABORTED when another update for the shop is in progress, and NOT_FOUND for an unknown shop.

PUT
/sdk/studio/{shopId}/loyalty/config
x-stash-hmac-signature<token>

Versioned HMAC-SHA256 signature authenticating server-to-server SDK requests (your backend calling Stash), as opposed to client-side SDK operations. Recommended over the deprecated X-Stash-Api-Key for the best security. Header format: v1;{appId};{unixMillisTimestamp};{base64Signature} (semicolon-delimited). {base64Signature} is the base64-encoded HMAC-SHA256 of the string {unixMillisTimestamp}.{requestBody} using your app ingress secret (the ingress secret is shown base64-encoded in Studio; base64-decode it to the raw bytes used as the HMAC key), where {requestBody} is the compact canonical request JSON for POST requests and empty for GET requests. The timestamp must be within 5 minutes of Stash server time. Your appId is your immutable app identifier, shown in Stash Studio under Project Settings > App details; your ingress secret is under Project Settings > API Secrets.

In: header

Path Parameters

shopId*string

Shop identifier from Stash Studio

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

One season plus the shop-level items it depends on. Signed over the request body.

Response Body

application/json

application/json

curl -X PUT "https://example.com/sdk/studio/string/loyalty/config" \  -H "Content-Type: application/json" \  -d '{    "campaign": {      "id": "string",      "name": "string"    }  }'
{  "displayConfig": {    "programName": "string",    "vipStoreName": "string"  },  "bonuses": [    {      "id": "string",      "type": "BONUS_TYPE_UNSPECIFIED",      "name": "string",      "pluralName": "string",      "abbreviatedName": "string",      "iconImageUrl": "string"    }  ],  "products": [    {      "sku": "string",      "name": "string",      "description": "string",      "imageUrl": "string",      "backgroundImageUrl": "string",      "status": "REWARD_PRODUCT_STATUS_UNSPECIFIED"    }  ],  "campaign": {    "id": "string",    "name": "string",    "startAt": "2019-08-24T14:15:22Z",    "endAt": "2019-08-24T14:15:22Z",    "reset": {      "points": "POINTS_UNSPECIFIED",      "milestoneClaims": "MILESTONE_CLAIMS_UNSPECIFIED",      "currency": "CURRENCY_UNSPECIFIED"    },    "tiers": [      {        "id": "string",        "name": "string",        "startPoints": 0,        "iconUrl": "string",        "backgroundImageUrl": "string",        "color": "string",        "benefits": [          {            "text": "string"          }        ],        "earnRates": [          {            "bonusId": "string",            "rewardPerDollar": 0          }        ],        "milestones": [          {            "id": "string",            "name": "string",            "description": "string",            "pointsNeeded": 0,            "rewardName": "string",            "rewardImageUrl": "string",            "backgroundImageUrl": "string",            "bonusRewards": [              {                "bonusId": "string",                "amount": 0              }            ],            "productRewards": [              {                "sku": "string",                "quantity": 0              }            ]          }        ]      }    ],    "status": "CAMPAIGN_STATUS_UNSPECIFIED"  },  "warnings": [    "string"  ]}

How is this guide?