# Update Store configuration

Replace the Store settings for the community that owns your API key, from its title and banner to its embeddable widget.

- Endpoint: `PUT https://api.returning.ai/v1/stores`
- Section: Store and rewards / General
- Authentication: `Authorization: Bearer <API_KEY>` (Community API key)
- Permission: `store` (Shown in the dashboard as "Store")
- Retries: No Idempotency-Key; the same body is safe to repeat
- Guide: hand-written
- Verified: live, 2026-09-27
- Last updated: 26 Sep 2026
- Web page: https://docs.returning.ai/api-reference/store/update-store-configuration

## When to use this

- Rename the Store or change its description.
- Switch the Store on or off, or show a custom coin name and icon.
- Allow your website's domain to embed the Store widget, or move the widget from testing to live.

**Instead:** Use [Get Store configuration](https://docs.returning.ai/api-reference/store/get-store-configuration.md) first to read the current settings; this endpoint needs all of them back.

**Full replace:** Every setting in the body is required. Read the current settings, change what you need, and send the whole object back.

## Authentication

- Header: `Authorization: Bearer <API_KEY>`
- Permission: `store`

Send a Community API key with the `store` permission. The key decides the community, so you can only change your own Store and never send a community ID. Keep the key on your server.

## Behaviour

This is a full replace. `isEnabled`, `title`, `description`, `cover`, `currency` and `widget` are all required, with every field inside them, so a request that sends only a new title is rejected. Read the settings with Get Store configuration, change the fields you need, and send the rest back unchanged.

A new title or description clears the automatically generated translations of that text, because they no longer match; translations your team entered by hand are kept. Translations, the widget ID and the widget's access key can't be changed here.

## Request

### Headers

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `Authorization` | `string` | Yes | Community API key with `store`. (`Bearer <API_KEY>`) |
| `Content-Type` | `string` | Yes | Request body format. (`application/json`) |

### Body

Send booleans as JSON `true` or `false`; `"true"` is rejected. Image and link URLs must use HTTPS, or be an empty string. `widgetID` is rejected if you send it back from a read; other fields this endpoint doesn't take, such as `i18n`, `_id` and the timestamps, are ignored.

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `isEnabled` | `boolean` | Yes | `true` switches the Store on. When `true`, `title` can't be empty. (JSON boolean) |
| `title` | `string` | Yes | Store title shown to traders. (Up to 32 chars; required when `isEnabled` is `true`) |
| `description` | `string` | Yes | Store description as HTML. Send an empty string for none. |
| `cover` | `object` | Yes | Banner images at the top of the Store. |
| `cover.isEnabled` | `boolean` | Yes | `true` shows the banner. Needs at least one image. (JSON boolean) |
| `cover.light` | `string` | Yes | Banner image URL for light mode. Send an empty string for none. (HTTPS URL or empty string) |
| `cover.dark` | `string` | Yes | Banner image URL for dark mode. Send an empty string for none. (HTTPS URL or empty string) |
| `currency` | `object` | Yes | A custom name and icon for coins in the Store. |
| `currency.isEnabled` | `boolean` | Yes | `true` shows the custom coin name and icons. Needs `name`. (JSON boolean) |
| `currency.name` | `string` | Yes | The custom coin name, such as `Coins`. Send an empty string for none. (Up to 32 chars; required when `isEnabled` is `true`) |
| `currency.light` | `string` | Yes | Coin icon URL for light mode. Send an empty string for none. (HTTPS URL or empty string) |
| `currency.dark` | `string` | Yes | Coin icon URL for dark mode. Send an empty string for none. (HTTPS URL or empty string) |
| `widget` | `object` | Yes | Settings for embedding the Store on your own website. Send the whole object even if you don't use the widget. |
| `widget.isEnabled` | `boolean` | Yes | `true` switches the widget on. When `true`, both theme names are required. (JSON boolean) |
| `widget.allowedDomains` | `string[]` | Yes | Hostnames allowed to embed the widget. Hostnames only, without `https://` or a path. (Hostnames such as `example.com`) |
| `widget.accessMode` | `string` | Yes | `live` for every trader, `development` for the test users and roles only. (`live` or `development`) |
| `widget.testUsers` | `string[]` | Yes | IDs of the traders who can use the widget in `development` mode. Send `[]` for none. |
| `widget.testRoles` | `string[]` | Yes | IDs of the roles that can use the widget in `development` mode. Send `[]` for none. |
| `widget.size` | `object` | Yes | Widget size. |
| `widget.size.mode` | `string` | Yes | `dynamic` fills the space available; `fixed` uses `width` and `height`. (`dynamic` or `fixed`) |
| `widget.size.width` | `number` | Yes | Width in pixels. (Number, 0 or more) |
| `widget.size.height` | `number` | Yes | Height in pixels. (Number, 0 or more) |
| `widget.appearance` | `object` | Yes | Widget colours. |
| `widget.appearance.light` | `object` | Yes | Light-mode theme. |
| `widget.appearance.light.name` | `string` | Yes | Theme name, such as `white-smoke`. Required when the widget is on. |
| `widget.appearance.light.palette` | `object` | Yes | Colour overrides, keyed by colour name, each a CSS colour string. Send `{}` for none. |
| `widget.appearance.dark` | `object` | Yes | Dark-mode theme. |
| `widget.appearance.dark.name` | `string` | Yes | Theme name, such as `black-beauty`. Required when the widget is on. |
| `widget.appearance.dark.palette` | `object` | Yes | Colour overrides, keyed by colour name, each a CSS colour string. Send `{}` for none. |
| `widget.appearance.useCommunityTheme` | `boolean` | Yes | `true` makes the widget use your community's theme instead of these. |
| `widget.callToAction` | `object` | Yes | A button shown in the widget. |
| `widget.callToAction.isEnabled` | `boolean` | Yes | `true` shows the button. |
| `widget.callToAction.text` | `string` | Yes | Button label. Can be empty. |
| `widget.callToAction.link` | `string` | Yes | Button link. Send an empty string for none. (HTTPS URL or empty string) |
| `widget.userIdentifierFields` | `object[]` | Yes | Fields the widget uses to identify the signed-in trader. Send `[]` for none. |
| `widget.userIdentifierFields.id` | `string` | Yes | Field ID. |
| `widget.userIdentifierFields.field` | `string` | Yes | The source field key, such as `email`. |
| `widget.userIdentifierFields.label` | `string` | Yes | Label shown to traders. |
| `widget.userIdentifierFields.type` | `string` | No | Where the field comes from. (`default` or `custom`) |
| `widget.userIdentifierFields.dataAttribute` | `string` | No | The HTML data attribute your page sets for this field, such as `data-email`. |

### Example request

```bash
curl --request PUT \
  --url https://api.returning.ai/v1/stores \
  --header 'Authorization: Bearer <API_KEY>' \
  --header 'Content-Type: application/json' \
  --data '{
    "isEnabled": true,
    "title": "Trading Rewards Store",
    "description": "<p>Redeem your coins for trading credits and gifts.</p>",
    "cover": {
      "isEnabled": false,
      "light": "",
      "dark": ""
    },
    "currency": {
      "isEnabled": true,
      "name": "Coins",
      "light": "https://cdn.example.com/store/coin-light.png",
      "dark": "https://cdn.example.com/store/coin-dark.png"
    },
    "widget": {
      "isEnabled": true,
      "allowedDomains": ["example.com"],
      "accessMode": "live",
      "testUsers": [],
      "testRoles": [],
      "size": {
        "mode": "dynamic",
        "width": 400,
        "height": 400
      },
      "appearance": {
        "light": {
          "name": "white-smoke",
          "palette": {}
        },
        "dark": {
          "name": "black-beauty",
          "palette": {}
        },
        "useCommunityTheme": false
      },
      "callToAction": {
        "isEnabled": false,
        "text": "",
        "link": ""
      },
      "userIdentifierFields": []
    }
  }'
```

## Response

A `200` returns the Store settings after the change in `data`, in the same shape as Get Store configuration. Branch on the HTTP status and `meta.code`, never on `message`.

### Response fields

| Field | Type | Presence | Description |
| --- | --- | --- | --- |
| `meta` | `object` | always | Status details. |
| `meta.status` | `string` | always | Result of the request. (`success`) |
| `meta.statusCode` | `integer` | always | The HTTP status, repeated. |
| `meta.code` | `string` | always | Machine-readable result code. (`STORE_CONFIGURATION_UPDATED`) |
| `message` | `string` | always | Human-readable summary. Do not branch on it. |
| `data` | `object` | always | Your Store settings after the change, in the same shape as Get Store configuration. |
| `data._id` | `string` | - | ID of the Store settings record. |
| `data.communityID` | `string` | - | Your community ID. |
| `data.isEnabled` | `boolean` | - | `true` when the Store is switched on. |
| `data.title` | `string` | - | The stored title. |
| `data.description` | `string` | - | The stored description. |
| `data.cover` | `object` | - | Cover/banner image configuration returned for the store. |
| `data.cover.isEnabled` | `boolean` | - | Whether banner display is enabled for the store. |
| `data.cover.light` | `string` | - | Light-mode cover image URL. Defaults to empty string until configured. |
| `data.cover.dark` | `string` | - | Dark-mode cover image URL. Defaults to empty string until configured. |
| `data.currency` | `object` | - | Custom currency display configuration returned for the store. |
| `data.currency.isEnabled` | `boolean` | - | Whether custom currency display is enabled. |
| `data.currency.name` | `string` | - | Custom currency display name. Defaults to empty string until configured. |
| `data.currency.light` | `string` | - | Light-mode custom currency icon URL. Defaults to empty string until configured. |
| `data.currency.dark` | `string` | - | Dark-mode custom currency icon URL. Defaults to empty string until configured. |
| `data.widgetID` | `string` | - | ID of the Store's embeddable widget. Read-only. |
| `data.widget` | `object` | - | Populated widget configuration. Internal widget identifiers such as store widgetID and widget _id are intentionally not exposed. (Nullable) |
| `data.widget.isEnabled` | `boolean` | - | Whether the embedded store widget is enabled. |
| `data.widget.allowedDomains` | `string[]` | - | Allowed widget embed domains. Defaults to an empty array. |
| `data.widget.accessMode` | `string` | - | Widget rollout access mode. (`development`, `live`) |
| `data.widget.testUsers` | `string[]` | - | User IDs allowed to use the widget in development mode. Defaults to an empty array. |
| `data.widget.testRoles` | `string[]` | - | Role IDs allowed to use the widget in development mode. Defaults to an empty array. |
| `data.widget.size` | `object` | - | Widget size configuration. |
| `data.widget.size.mode` | `string` | - | Widget sizing mode. (`dynamic`, `fixed`) |
| `data.widget.size.width` | `number` | - | Widget width in pixels. Defaults to 400. |
| `data.widget.size.height` | `number` | - | Widget height in pixels. Defaults to 400. |
| `data.widget.appearance` | `object` | - | Widget appearance configuration. |
| `data.widget.appearance.light` | `object` | - | Light theme appearance configuration. |
| `data.widget.appearance.light.name` | `string` | - | Theme name identifier. |
| `data.widget.appearance.light.palette` | `object` | - | Theme palette map keyed by color token. |
| `data.widget.appearance.dark` | `object` | - | Dark theme appearance configuration. |
| `data.widget.appearance.dark.name` | `string` | - | Theme name identifier. |
| `data.widget.appearance.dark.palette` | `object` | - | Theme palette map keyed by color token. |
| `data.widget.appearance.useCommunityTheme` | `boolean` | - | Whether the widget uses the community theme. |
| `data.widget.callToAction` | `object` | - | Widget call-to-action configuration. |
| `data.widget.callToAction.isEnabled` | `boolean` | - | Whether widget call-to-action display is enabled. |
| `data.widget.callToAction.text` | `string` | - | CTA label text. Defaults to empty string. |
| `data.widget.callToAction.link` | `string` | - | CTA link URL. Defaults to empty string. |
| `data.widget.userIdentifierFields` | `object[]` | - | Widget user identifier fields used for authentication. Defaults to an empty array. |
| `data.widget.userIdentifierFields.id` | `string` | - | Identifier field ID. |
| `data.widget.userIdentifierFields.field` | `string` | - | Source field key used by widget authentication. |
| `data.widget.userIdentifierFields.label` | `string` | - | Display label shown to users. |
| `data.widget.userIdentifierFields.type` | `string` | - | Identifier field source type. (`default`, `custom`) |
| `data.widget.userIdentifierFields.dataAttribute` | `string` | - | Optional HTML data attribute used by widget integration. |
| `data.widget.createdAt` | `string` | - | Widget creation timestamp. (Date-time) |
| `data.widget.updatedAt` | `string` | - | Widget last update timestamp. (Date-time) |
| `data.widget.__v` | `integer` | - | Mongoose version key when selected. |
| `data.i18n` | `object` | - | Translations of the title and description. This endpoint doesn't change them, except as described under Behaviour. |
| `data.i18n.isTranslationEnabled` | `boolean` | - | Whether store translations are enabled. |
| `data.i18n.titleTranslations` | `object[]` | - | Title translations. Defaults to an empty array. |
| `data.i18n.titleTranslations.locale` | `string` | - | Translation locale code. |
| `data.i18n.titleTranslations.content` | `string` | - | Translated content value. |
| `data.i18n.titleTranslations.label` | `string` | - | Language display label. |
| `data.i18n.titleTranslations.isAiGenerated` | `boolean` | - | Whether this value was generated by AI. |
| `data.i18n.titleTranslations.translationConfigHash` | `string` | - | Translation config hash used for AI-generated content. |
| `data.i18n.descriptionTranslations` | `object[]` | - | Description translations. Defaults to an empty array. |
| `data.i18n.descriptionTranslations.locale` | `string` | - | Translation locale code. |
| `data.i18n.descriptionTranslations.content` | `string` | - | Translated content value. |
| `data.i18n.descriptionTranslations.label` | `string` | - | Language display label. |
| `data.i18n.descriptionTranslations.isAiGenerated` | `boolean` | - | Whether this value was generated by AI. |
| `data.i18n.descriptionTranslations.translationConfigHash` | `string` | - | Translation config hash used for AI-generated content. |
| `data.i18n.translationPrompt` | `string` | - | Store-specific AI translation prompt. |
| `data.i18n.translationIgnoreList` | `string[]` | - | Terms AI translation should preserve exactly. |
| `data.createdAt` | `string` | - | Store config creation timestamp. May be omitted when using fields projection. (Date-time) |
| `data.updatedAt` | `string` | - | Store config last update timestamp. May be omitted when using fields projection. (Date-time) |
| `data.__v` | `integer` | - | Mongoose version key when selected. May be omitted when using fields projection. |

### Example response (200)

```json
{
  "meta": {
    "status": "success",
    "statusCode": 200,
    "code": "STORE_CONFIGURATION_UPDATED"
  },
  "message": "Update store config success.",
  "data": {
    "_id": "66f000000000000000000901",
    "communityID": "66f000000000000000000010",
    "isEnabled": true,
    "title": "Trading Rewards Store",
    "description": "<p>Redeem your coins for trading credits and gifts.</p>",
    "cover": {
      "isEnabled": false,
      "light": "",
      "dark": ""
    },
    "currency": {
      "isEnabled": true,
      "name": "Coins",
      "light": "https://cdn.example.com/store/coin-light.png",
      "dark": "https://cdn.example.com/store/coin-dark.png"
    },
    "widgetID": "66f000000000000000000902",
    "i18n": {
      "isTranslationEnabled": false,
      "titleTranslations": [],
      "descriptionTranslations": []
    },
    "widget": {
      "isEnabled": true,
      "allowedDomains": ["example.com"],
      "accessMode": "live",
      "testUsers": [],
      "testRoles": [],
      "size": {
        "mode": "dynamic",
        "width": 400,
        "height": 400
      },
      "appearance": {
        "light": {
          "name": "white-smoke",
          "palette": {}
        },
        "dark": {
          "name": "black-beauty",
          "palette": {}
        },
        "useCommunityTheme": false
      },
      "callToAction": {
        "isEnabled": false,
        "text": "",
        "link": ""
      },
      "userIdentifierFields": [],
      "createdAt": "2026-09-01T08:30:00.000Z",
      "updatedAt": "2026-09-27T10:15:00.000Z",
      "__v": 0
    },
    "createdAt": "2026-09-01T08:30:00.000Z",
    "updatedAt": "2026-09-27T10:15:00.000Z",
    "__v": 0
  }
}
```

## Errors

Every error carries its code in `meta.code`, with the reason in `detail` keyed by setting name. The `message` on a `400` varies, so don't read it.

### Fix the request

| Status | Code | What to do |
| --- | --- | --- |
| 400 | `VALIDATION_FAILED` | A setting is missing or breaks a rule, and nothing was changed. `detail` names each one, for example `widget must be an object`, `title must be shorter than or equal to 32 characters`, `Image URL must be an HTTPS URL or an empty string.`, `Domain must be a valid hostname such as example.com.` or `widgetID is response-only and cannot be updated`. |
| 401 | `AUTH_API_KEY_REQUIRED` | No key was sent. Send `Authorization: Bearer <API_KEY>`. |
| 401 | `AUTH_API_KEY_INVALID` | The key is unknown, expired or malformed. Use a current Community API key. |
| 403 | `AUTH_PERMISSION_REQUIRED` | The key lacks `store`. Add the permission in Settings > Integration > API Keys. |

### Retry with backoff

| Status | Code | What to do |
| --- | --- | --- |
| 502 | `STORE_DEPENDENCY_UNAVAILABLE` | The outcome is unknown. Read the settings with Get Store configuration, then send the update again if it didn't apply. |
| 500 | `INTERNAL_ERROR` | The outcome is unknown. Read the settings with Get Store configuration, then send the update again if it didn't apply. |
| 401 | `AUTH_API_KEY_VALIDATION_FAILED` | The key could not be checked just now, and nothing was changed. Retry with backoff. |

**Retries:** Update Store configuration doesn't accept an `Idempotency-Key`, but sending the same body again leaves the Store in the same state. After a timeout, a `500` or a `502`, read the settings back before you retry. Over the [rate limit](https://docs.returning.ai/how-it-works.md#rate-limits), requests return `429`; wait for the window to reset, then retry.

## Next step

- [Get Store configuration](https://docs.returning.ai/api-reference/store/get-store-configuration.md): `GET /v1/stores`. Read the settings back to confirm the change.
- [Organise the Store with List Store categories](https://docs.returning.ai/api-reference/store-categories/list-store-categories.md): `GET /v1/categories`.
