# Create a Theme

> POST /v3/kb/themes · Knowledge base API

Source: https://developer.kustomer.com/api/knowledge-base/create-a-theme

```http
POST https://{orgname}.api.kustomerapp.com/v3/kb/themes
Authorization: Bearer <API key>
```

## Authorization

Requires any one of these roles: `org.permission.kb.create`; or legacy `org.admin.content.kb.write`, `org.admin.kb.write`. The API key or user must hold at least one of them. Legacy roles predate permission sets and still work.

Creates a Knowledge Base theme.

## About Knowledge base themes

A theme controls how a help center looks and is laid out, from colors and fonts to the code for each page. Themes keep a history of revisions, so you can edit and preview a draft before you publish it. Templates are the ready-made starting points that new themes are copied from.

Admins customize themes in the theme editor in the knowledge base settings. Each knowledge base displays the theme set in its `theme` field. A theme's `active` and `default` fields are left over from an older model, so ignore them. The public endpoint for the active theme returns the theme of the knowledge base that the request's host identifies.

A theme is customized at two levels. The `manifest` holds settings that admins change without code. It is grouped into sections such as `design`, `header`, `footer`, `searchBar`, `announcement` and `featuredArticles`, and each variable has a type such as `color`, `select`, `slider`, `text`, `link`, `list`, `boolean` or `file`. Theme files hold the code.

#### Theme files

| `type` | What it is | Examples |
| --- | --- | --- |
| `page` | One help center page | `homepage.jsx`, `article.jsx`, `categories.jsx`, `search.jsx`, `tag.jsx`, `contact.jsx`, `404.jsx` |
| `component` | A piece shared between pages | `Nav.jsx`, `Footer.jsx`, `ArticleBreadcrumbs.jsx` |
| `asset` | Stylesheets and scripts, used as written | `styles.css`, `utils.js` |

Pages and components are JSX. Kustomer compiles them when you save and returns the output in `compiled`. If the content doesn't compile, the save fails with `400`. File names must be unique within a revision. Text in a theme can use [snippets](https://developer.kustomer.com/api/settings-and-configurations#snippets), so one theme serves every language. Kustomer collects the snippet keys in the manifest into `configSnippets` for you. List the keys your code uses in the theme's `jsxSnippets` and in each file's `snippets`, and make sure each key exists, because Kustomer rejects a file that lists an unknown key.

#### Drafts and revisions

A theme keeps a stack of revisions, and each revision has its own files. The newest revision is either the published one or a single draft on top of it. The theme's `status` is `draft` while a draft exists and `published` otherwise.

1. `POST …/revisions/draft` creates the draft from the `name`, `manifest` and `jsxSnippets` you send, with a copy of the published revision's files. To copy an older revision's settings and files instead, send only `duplicateRevisionId`. If a draft already exists, it is replaced, and edits to its files are lost.
2. Edit the draft's `name`, `manifest` and `jsxSnippets` with `PUT …/revisions/draft`, and edit its files through the file endpoints using the draft's revision ID.
3. Preview the draft with the public endpoints by passing `status=draft` or the `revisionId`.
4. Send `{ "publish": true }` to `PUT …/revisions/draft` to publish, or `DELETE` the draft to discard it.

Kustomer keeps the 30 most recent revisions. When a publish pushes out the oldest revision, its files are deleted.

#### Templates

Templates aren't page templates. Each template is a complete starter theme that Kustomer provides, such as "Midtown". It has a `title`, a `description`, preview `images`, a `version` and a default `manifest`. Templates are read-only. To start from one, create a theme with `duplicateTemplateId`, and the theme's `templateVersionId` records the template version it came from. To copy one of your own themes, use `duplicateThemeId` instead. You can't send both. A new knowledge base created without a theme gets one built from Midtown.

#### Which endpoint to use

| To | Call |
| --- | --- |
| List themes, or read one | [`GET /v3/kb/themes`](https://developer.kustomer.com/api/knowledge-base/get-themes) or [`GET /v3/kb/themes/{id}`](https://developer.kustomer.com/api/knowledge-base/get-themes-by-id) |
| Create a theme from a template or another theme | [`POST /v3/kb/themes`](https://developer.kustomer.com/api/knowledge-base/create-a-theme) |
| Load the live theme or a preview, without an API key | [`GET /p/v3/kb/themes/active`](https://developer.kustomer.com/api/knowledge-base/get-active-theme-public), [`GET /p/v3/kb/themes/{id}`](https://developer.kustomer.com/api/knowledge-base/get-theme-by-id-public) or [`GET /p/v3/kb/themes/{id}/files`](https://developer.kustomer.com/api/knowledge-base/get-theme-files-public) |
| Browse revision history | [`GET …/revisions`](https://developer.kustomer.com/api/knowledge-base/get-theme-revisions) or [`GET …/revisions/{id}`](https://developer.kustomer.com/api/knowledge-base/get-theme-revision-by-id) |
| Start, edit, publish or discard the draft | [`POST`](https://developer.kustomer.com/api/knowledge-base/create-theme-draft-revision), [`PUT`](https://developer.kustomer.com/api/knowledge-base/update-theme-draft-revision) or [`DELETE /v3/kb/themes/{themeId}/revisions/draft`](https://developer.kustomer.com/api/knowledge-base/delete-theme-draft-revision) |
| List or read a revision's files | [`GET …/revisions/{revisionId}/files`](https://developer.kustomer.com/api/knowledge-base/get-theme-files-by-revision) or [`GET …/files/{id}`](https://developer.kustomer.com/api/knowledge-base/get-theme-file-by-revision) |
| Add, change or remove a file | [`POST …/files`](https://developer.kustomer.com/api/knowledge-base/create-revision-theme-file), [`PUT …/files/{id}`](https://developer.kustomer.com/api/knowledge-base/update-revision-theme-file) or [`DELETE …/files/{id}`](https://developer.kustomer.com/api/knowledge-base/delete-revision-theme-file) |
| List the starter templates, or read one | [`GET /v3/kb/templates`](https://developer.kustomer.com/api/knowledge-base/get-templates) or [`GET /v3/kb/templates/{id}`](https://developer.kustomer.com/api/knowledge-base/get-templates-by-id) |

The public theme endpoints return the published revision unless you ask for a draft or a specific revision. Reads need a knowledge base read role, and writes need `org.admin.kb.write` or the matching permission.

Related: [Knowledge bases](https://developer.kustomer.com/api/knowledge-base#knowledge-bases), [Snippets](https://developer.kustomer.com/api/settings-and-configurations#snippets), [Add chat to a Kustomer knowledge base](https://developer.kustomer.com/docs/chat/web)

### Recipes

#### 1. Change a help center's colors and review them before they go live

Update a theme's button and link colors for a rebrand in a draft, check the draft, then publish it.

**Step 1.** [`GET /v3/kb/themes/{id}`](https://developer.kustomer.com/api/knowledge-base/get-themes-by-id.md). Read the theme. Its `manifest` holds the published settings, grouped into sections; the colors are in the `design` section.

```bash title="cURL"
curl "https://api.kustomerapp.com/v3/kb/themes/$THEME_ID" \
  --header "Authorization: Bearer $KUSTOMER_API_KEY" > theme.json
```

```bash title="kusty"
kusty api GET /v3/kb/themes/$THEME_ID > theme.json
```

**Step 2.** [`POST /v3/kb/themes/{themeId}/revisions/draft`](https://developer.kustomer.com/api/knowledge-base/create-theme-draft-revision.md). Start a draft with the theme's `name`, `jsxSnippets` and the edited `manifest`. The draft gets its settings from what you send, so send every section, not just the one you changed. Kustomer copies the published revision's files into the draft, and the live help center doesn't change yet.

```bash title="cURL"
curl --request POST "https://api.kustomerapp.com/v3/kb/themes/$THEME_ID/revisions/draft" \
  --header "Authorization: Bearer $KUSTOMER_API_KEY" \
  --header "Content-Type: application/json" \
  --data "$(jq '.data.attributes | {name, jsxSnippets, manifest: (.manifest | map(
      if .name == "design" then .variables.primaryButtonColor.value = "#5B2D90" | .variables.linksColor.value = "#5B2D90" else . end))}' theme.json)"
```

```bash title="kusty"
kusty api POST /v3/kb/themes/$THEME_ID/revisions/draft --fields attributes.status \
  --data "$(jq '.data.attributes | {name, jsxSnippets, manifest: (.manifest | map(
    if .name == "design" then .variables.primaryButtonColor.value = "#5B2D90" | .variables.linksColor.value = "#5B2D90" else . end))}' theme.json)"
```

**Step 3.** [`GET /p/v3/kb/themes/{id}`](https://developer.kustomer.com/api/knowledge-base/get-theme-by-id-public.md). Load the draft the way the help center does, with `status=draft`. No API key is needed; call your org host. Without `status`, this endpoint returns the published revision.

```bash title="cURL"
curl "https://$ORG.api.kustomerapp.com/p/v3/kb/themes/$THEME_ID?status=draft"
```

```bash title="kusty"
kusty api GET /p/v3/kb/themes/$THEME_ID --base-url "https://$ORG.api.kustomerapp.com" \
  --query status=draft --fields attributes.manifest
```

**Step 4.** [`PUT /v3/kb/themes/{themeId}/revisions/draft`](https://developer.kustomer.com/api/knowledge-base/update-theme-draft-revision.md). When it looks right, publish the draft. The theme's `status` goes back to `published`, and `rev` moves up to the draft's revision number.

```bash title="cURL"
curl --request PUT "https://api.kustomerapp.com/v3/kb/themes/$THEME_ID/revisions/draft" \
  --header "Authorization: Bearer $KUSTOMER_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{"publish": true}'
```

```bash title="kusty"
kusty api PUT /v3/kb/themes/$THEME_ID/revisions/draft --field publish:=true
```

> To make more changes before publishing, send the full `name`, `manifest` and `jsxSnippets` to [`PUT …/revisions/draft`](https://developer.kustomer.com/api/knowledge-base/update-theme-draft-revision); it replaces the draft's settings. To drop the draft instead, call [`DELETE …/revisions/draft`](https://developer.kustomer.com/api/knowledge-base/delete-theme-draft-revision).

#### 2. Edit a page component in a draft

Change the code of a shared component, such as the footer, in a draft, check that it compiles and renders, then publish it.

**Step 1.** [`POST /v3/kb/themes/{themeId}/revisions/draft`](https://developer.kustomer.com/api/knowledge-base/create-theme-draft-revision.md). Start a draft with the theme's current settings, read from [`GET /v3/kb/themes/{id}`](https://developer.kustomer.com/api/knowledge-base/get-themes-by-id). Kustomer copies the published files into it. If the theme already has a draft, this replaces it and its file edits are lost, so check `status` first.

```bash title="cURL"
curl --request POST "https://api.kustomerapp.com/v3/kb/themes/$THEME_ID/revisions/draft" \
  --header "Authorization: Bearer $KUSTOMER_API_KEY" \
  --header "Content-Type: application/json" \
  --data "$(jq '.data.attributes | {name, manifest, jsxSnippets}' theme.json)"
```

```bash title="kusty"
kusty api POST /v3/kb/themes/$THEME_ID/revisions/draft \
  --data "$(jq '.data.attributes | {name, manifest, jsxSnippets}' theme.json)" --fields attributes.status
```

**Step 2.** [`GET /v3/kb/themes/{themeId}/revisions`](https://developer.kustomer.com/api/knowledge-base/get-theme-revisions.md). Find the draft's revision ID. The file endpoints take it, not the theme ID alone.

```bash title="cURL"
curl "https://api.kustomerapp.com/v3/kb/themes/$THEME_ID/revisions" \
  --header "Authorization: Bearer $KUSTOMER_API_KEY"
```

```bash title="kusty"
DRAFT_REV_ID=$(kusty api GET /v3/kb/themes/$THEME_ID/revisions --all \
  | jq -r 'select(.data.attributes.status == "draft") | .data.id')
```

**Step 3.** [`GET /v3/kb/themes/{themeId}/revisions/{revisionId}/files`](https://developer.kustomer.com/api/knowledge-base/get-theme-files-by-revision.md). List the draft's files and save the one to change. Each file has a `name`, a `type` and its `content`.

```bash title="cURL"
curl "https://api.kustomerapp.com/v3/kb/themes/$THEME_ID/revisions/$DRAFT_REV_ID/files?page=1&pageSize=100" \
  --header "Authorization: Bearer $KUSTOMER_API_KEY"
```

```bash title="kusty"
kusty api GET /v3/kb/themes/$THEME_ID/revisions/$DRAFT_REV_ID/files --all \
  | jq -c 'select(.data.attributes.name == "Footer.jsx")' > footer.json
FILE_ID=$(jq -r .data.id footer.json)
```

**Step 4.** [`PUT /v3/kb/themes/{themeId}/revisions/{revisionId}/files/{id}`](https://developer.kustomer.com/api/knowledge-base/update-revision-theme-file.md). Save the new code from a local `Footer.jsx`. Send the file's `name` and `type`, and its `snippets` list with any new snippet keys the code uses. Kustomer compiles the JSX and returns it in `compiled`; if it doesn't compile, the save fails with `400` and the draft keeps the old code.

```bash title="cURL"
curl --request PUT "https://api.kustomerapp.com/v3/kb/themes/$THEME_ID/revisions/$DRAFT_REV_ID/files/$FILE_ID" \
  --header "Authorization: Bearer $KUSTOMER_API_KEY" \
  --header "Content-Type: application/json" \
  --data "$(jq --rawfile content Footer.jsx '.data.attributes | {name, type, snippets, content: $content}' footer.json)"
```

```bash title="kusty"
kusty api PUT /v3/kb/themes/$THEME_ID/revisions/$DRAFT_REV_ID/files/$FILE_ID --fields attributes.name \
  --data "$(jq --rawfile content Footer.jsx '.data.attributes | {name, type, snippets, content: $content}' footer.json)"
```

**Step 5.** [`GET /p/v3/kb/themes/{id}/files`](https://developer.kustomer.com/api/knowledge-base/get-theme-files-public.md). Load the draft's files the way the help center does, with `status=draft` and the language to check. No API key is needed; call your org host.

```bash title="cURL"
curl "https://$ORG.api.kustomerapp.com/p/v3/kb/themes/$THEME_ID/files?status=draft&lang=en_us&page=1&pageSize=100"
```

**Step 6.** [`PUT /v3/kb/themes/{themeId}/revisions/draft`](https://developer.kustomer.com/api/knowledge-base/update-theme-draft-revision.md). Publish the draft to put the new footer live.

```bash title="cURL"
curl --request PUT "https://api.kustomerapp.com/v3/kb/themes/$THEME_ID/revisions/draft" \
  --header "Authorization: Bearer $KUSTOMER_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{"publish": true}'
```

```bash title="kusty"
kusty api PUT /v3/kb/themes/$THEME_ID/revisions/draft --field publish:=true
```

> Each key in a file's `snippets` must be an existing [snippet](https://developer.kustomer.com/api/settings-and-configurations#snippets), or Kustomer rejects the file. Add new keys to the theme's `jsxSnippets` too, with [`PUT …/revisions/draft`](https://developer.kustomer.com/api/knowledge-base/update-theme-draft-revision).

#### 3. Roll a theme back to an earlier revision

Undo a bad publish by bringing back the settings and files of an earlier revision.

**Step 1.** [`GET /v3/kb/themes/{themeId}/revisions`](https://developer.kustomer.com/api/knowledge-base/get-theme-revisions.md). List the theme's revisions, newest first, and pick the one to restore by its `rev` and `createdAt`.

```bash title="cURL"
curl "https://api.kustomerapp.com/v3/kb/themes/$THEME_ID/revisions" \
  --header "Authorization: Bearer $KUSTOMER_API_KEY"
```

```bash title="kusty"
kusty api GET /v3/kb/themes/$THEME_ID/revisions --all \
  | jq -r '.data | [.id, .attributes.rev, .attributes.status, .attributes.createdAt] | @tsv'
```

**Step 2.** [`POST /v3/kb/themes/{themeId}/revisions/draft`](https://developer.kustomer.com/api/knowledge-base/create-theme-draft-revision.md). Start a draft from that revision by sending only `duplicateRevisionId`. Kustomer copies its settings and files into the draft, replacing any draft that already exists.

```bash title="cURL"
curl --request POST "https://api.kustomerapp.com/v3/kb/themes/$THEME_ID/revisions/draft" \
  --header "Authorization: Bearer $KUSTOMER_API_KEY" \
  --header "Content-Type: application/json" \
  --data "{\"duplicateRevisionId\": \"$REVISION_ID\"}"
```

```bash title="kusty"
kusty api POST /v3/kb/themes/$THEME_ID/revisions/draft --field duplicateRevisionId=$REVISION_ID
```

**Step 3.** [`PUT /v3/kb/themes/{themeId}/revisions/draft`](https://developer.kustomer.com/api/knowledge-base/update-theme-draft-revision.md). Publish the draft. The restored settings go live as a new revision, so the revision you rolled back from stays in the history.

```bash title="cURL"
curl --request PUT "https://api.kustomerapp.com/v3/kb/themes/$THEME_ID/revisions/draft" \
  --header "Authorization: Bearer $KUSTOMER_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{"publish": true}'
```

```bash title="kusty"
kusty api PUT /v3/kb/themes/$THEME_ID/revisions/draft --field publish:=true
```

> Kustomer keeps the 30 most recent revisions, and deletes the files of older ones, so a revision you may need again shouldn't be allowed to fall off the end.

#### 4. Give a help center a fresh theme from a starter template

Build a new theme from one of Kustomer's starter templates and switch a knowledge base to it.

**Step 1.** [`GET /v3/kb/templates`](https://developer.kustomer.com/api/knowledge-base/get-templates.md). List the starter templates and pick one by `title`, such as "Midtown". Each has a `description` and preview `images`.

```bash title="cURL"
curl "https://api.kustomerapp.com/v3/kb/templates?page=1&pageSize=100" \
  --header "Authorization: Bearer $KUSTOMER_API_KEY"
```

```bash title="kusty"
TEMPLATE_ID=$(kusty api GET /v3/kb/templates --all \
  | jq -r 'select(.data.attributes.title == "Midtown") | .data.id')
```

**Step 2.** [`POST /v3/kb/themes`](https://developer.kustomer.com/api/knowledge-base/create-a-theme.md). Create the theme with a `name` and `duplicateTemplateId`. It starts with the template's settings and files, and `templateVersionId` records which template version it came from. To copy one of your own themes instead, send `duplicateThemeId`; a theme created with neither starts with no files.

```bash title="cURL"
curl --request POST "https://api.kustomerapp.com/v3/kb/themes" \
  --header "Authorization: Bearer $KUSTOMER_API_KEY" \
  --header "Content-Type: application/json" \
  --data "{\"name\": \"Spring refresh\", \"duplicateTemplateId\": \"$TEMPLATE_ID\"}"
```

```bash title="kusty"
kusty api POST /v3/kb/themes --field name="Spring refresh" \
  --field duplicateTemplateId=$TEMPLATE_ID --fields id
```

**Step 3.** [`PATCH /v1/kb/knowledge-bases/{id}`](https://developer.kustomer.com/api/knowledge-base/update-knowledge-base.md). Once you've customized it through a draft, switch the knowledge base to the new theme. The help center shows the new theme's published revision right away.

```bash title="cURL"
curl --request PATCH "https://api.kustomerapp.com/v1/kb/knowledge-bases/$KB_ID" \
  --header "Authorization: Bearer $KUSTOMER_API_KEY" \
  --header "Content-Type: application/json" \
  --data "{\"theme\": \"$NEW_THEME_ID\"}"
```

```bash title="kusty"
kusty api PATCH /v1/kb/knowledge-bases/$KB_ID --field theme=$NEW_THEME_ID
```

> Customize the new theme before switching: its first revision is published, so preview it with [`GET /p/v3/kb/themes/{id}`](https://developer.kustomer.com/api/knowledge-base/get-theme-by-id-public) and change it with a draft, as in the recipes above.

### Example object

A real record from [`GET /v3/kb/themes/{id}`](https://developer.kustomer.com/api/knowledge-base/get-themes-by-id.md):

```json
{
  "type": "theme",
  "id": "6026cf46fcca5f03e5541ece",
  "attributes": {
    "name": "Midtown Theme",
    "active": false,
    "default": false,
    "lastFileUpdatedAt": "2021-02-12T18:56:06.686Z",
    "status": "published",
    "templateVersionId": "6026aba3fcca5f03e5541cd5",
    "manifest": [
      {
        "name": "design",
        "variables": {
          "headingsAndButtonsFont": {
            "name": "headingsAndButtonsFont",
            "type": "select",
            "enum": [
              {
                "label": "Arial",
                "value": "arial"
              },
              {
                "label": "Verdana",
                "value": "verdana"
              },
              {
                "label": "Helvetica",
                "value": "helvetica"
              }
            ],
            "value": "Helvetica"
          },
          "headingBaseSizeFont": {
            "name": "headingBaseSizeFont",
            "type": "slider",
            "value": "36px"
          },
          "bodyTextFont": {
            "name": "bodyTextFont",
            "type": "select",
            "enum": [
              {
                "label": "Arial",
                "value": "arial"
              },
              {
                "label": "Verdana",
                "value": "verdana"
              },
              {
                "label": "Helvetica",
                "value": "helvetica"
              }
            ],
            "value": "Helvetica"
          },
          "baseSizeFont": {
            "name": "baseSizeFont",
            "type": "slider",
            "value": "16px"
          },
          "headingsColor": {
            "name": "headingsColor",
            "type": "color",
            "value": "#0A3355"
          },
          "bodyTextColor": {
            "name": "bodyTextColor",
            "type": "color",
            "value": "#222222"
          },
          "secondaryTextColor": {
            "name": "secondaryTextColor",
            "type": "color",
            "value": "#939FA8"
          },
          "linksColor": {
            "name": "linksColor",
            "type": "color",
            "value": "#0A3355"
          },
          "primaryButtonColor": {
            "name": "primaryButtonColor",
            "type": "color",
            "value": "#0A3355"
          },
          "primaryButtonTextColor": {
            "name": "primaryButtonTextColor",
            "type": "color",
            "value": "#ffffff"
          },
          "primaryBackgroundPageColor": {
            "name": "primaryBackgroundPageColor",
            "type": "color",
            "value": "#ffffff"
          },
          "secondaryBackgroundPageColor": {
            "name": "secondaryBackgroundPageColor",
            "type": "color",
            "value": "#F9F9F9"
          },
          "borderPageColor": {
            "name": "borderPageColor",
            "type": "color",
            "value": "#B2B2B2"
          }
        }
      },
      {
        "name": "announcement",
        "label": "[[ sn.kustomer.themebuilder.announcement_label ]]",
        "enabled": true,
        "variables": {
          "homepageOnly": {
            "name": "homepageOnly",
            "type": "boolean",
            "label": "[[ sn.kustomer.themebuilder.announcement_show_on_home_page_label ]]",
            "value": false
          },
          "announcementText": {
            "name": "announcementText",
            "type": "text",
            "label": "[[ sn.kustomer.themebuilder.announcement_text_value ]]",
            "value": "Important update about our holiday hours"
          },
          "textColor": {
            "name": "textColor",
            "type": "color",
            "label": "[[ sn.kustomer.themebuilder.announcement_text_color_label ]]",
            "value": "#FFFFFF"
          },
          "backgroundColor": {
            "name": "backgroundColor",
            "type": "color",
            "label": "[[ sn.kustomer.themebuilder.announcement_background_color_label ]]",
            "value": "#E16360"
          },
          "ctaText": {
            "name": "ctaText",
            "type": "string",
            "label": "[[ sn.kustomer.themebuilder.cta_text_label ]]",
            "value": "<Snippet id=\"sn.kustomer.themebuilder.announcement_cta_text_value\" />"
          },
          "ctaTextColor": {
            "name": "ctaTextColor",
            "type": "color",
            "label": "[[ sn.kustomer.themebuilder.announcement_cta_text_color_label ]]",
            "value": "#FFFFFF"
          },
          "ctaLink": {
            "name": "ctaLink",
            "type": "link",
            "label": "[[ sn.kustomer.themebuilder.cta_link_label ]]",
            "value": ""
          }
        }
      },
      {
        "name": "header",
        "label": "[[ sn.kustomer.themebuilder.header_label ]]",
        "link": {
          "label": "[[ sn.kustomer.themebuilder.header_link_label ]]",
          "description": "[[ sn.kustomer.themebuilder.header_link_description ]]",
          "buttonText": "[[ sn.kustomer.themebuilder.header_link_button_text ]]",
          "value": "/app/settings/kb/config"
        },
        "variables": {
          "navigation": {
            "name": "navigation",
            "type": "list",
            "minItems": 1,
            "maxItems": 5,
            "label": "[[ sn.kustomer.themebuilder.header_navigation_label ]]",
            "buttonText": "[[ sn.kustomer.themebuilder.header_navigation_button_text ]]",
            "value": [
              {
                "navigationText": {
                  "name": "navigationText",
                  "label": "[[ sn.kustomer.themebuilder.navigation_text_label_1 ]]",
                  "type": "string",
                  "value": "<Snippet id=\"sn.kustomer.themebuilder.navigation_text_value_1\" />"
                },
                "navigationLink": {
                  "name": "navigationLink",
                  "label": "[[ sn.kustomer.themebuilder.navigation_link_label_1 ]]",
                  "type": "link",
                  "value": ""
                }
              }
            ]
          }
        }
      }
    ],
    "configSnippets": [
      "sn.kustomer.themebuilder.announcement_label",
      "sn.kustomer.themebuilder.announcement_show_on_home_page_label",
      "sn.kustomer.themebuilder.announcement_text_value"
    ],
    "jsxSnippets": [
      "sn.kustomer.themebuilder.announcement_cta_text_value",
      "sn.kustomer.themebuilder.navigation_text_value_1",
      "sn.kustomer.themebuilder.search_bar_primary_message_value"
    ],
    "createdAt": "2021-02-12T18:56:06.686Z",
    "updatedAt": "2021-02-12T18:56:06.686Z",
    "modifiedAt": "2021-02-12T18:56:06.686Z",
    "rev": 1
  },
  "relationships": {
    "org": {
      "links": {
        "self": "/v1/orgs/5e15fa33623f88001a8e0bb5"
      },
      "data": {
        "type": "org",
        "id": "5e15fa33623f88001a8e0bb5"
      }
    },
    "createdBy": {
      "links": {
        "self": "/v1/users/5e15fa45623f88001a8e0bbb"
      },
      "data": {
        "type": "user",
        "id": "5e15fa45623f88001a8e0bbb"
      }
    },
    "modifiedBy": {
      "links": {
        "self": "/v1/users/5e15fa45623f88001a8e0bbb"
      },
      "data": {
        "type": "user",
        "id": "5e15fa45623f88001a8e0bbb"
      }
    }
  },
  "links": {
    "self": "/v1/kb/themes/6026cf46fcca5f03e5541ece"
  }
}
```

Fields:

- `attributes.name` (string): The theme's name in the theme editor, 3 to 256 characters.
- `attributes.active` (boolean): Left over from an older model, so ignore it. A help center shows the theme set in its knowledge base's `theme`.
- `attributes.default` (boolean): Left over from an older model, so ignore it.
- `attributes.lastFileUpdatedAt` (string): When the theme's files were last changed.
- `attributes.status` (string): `draft` while the theme has an unpublished draft revision, and `published` otherwise.
- `attributes.templateVersionId` (string): The version of the starter template the theme was built from. Themes copied from another theme keep that theme's value.
- `attributes.manifest` (array): The published revision's no-code settings, as a list of sections. While a draft exists, read the draft's settings from its revision with [`GET …/revisions/{id}`](https://developer.kustomer.com/api/knowledge-base/get-theme-revision-by-id), which returns them in `included`.
- `attributes.manifest[].name` (string): The section's name, such as `design`, `header`, `footer`, `searchBar`, `announcement` or `featuredArticles`.
- `attributes.manifest[].variables` (object): The section's settings, keyed by variable name. Each one has a `name`, a `type` and a `value`.
- `attributes.manifest[].variables.headingsAndButtonsFont.type` (string): The kind of setting, such as `color`, `select`, `slider`, `text`, `link`, `list`, `boolean` or `file`. The editor shows a matching control.
- `attributes.manifest[].variables.headingsAndButtonsFont.enum` (array): The choices for a `select` setting, each with a `label` and a `value`.
- `attributes.manifest[].variables.headingsAndButtonsFont.value` (string): The setting's current value. To change it, send the whole edited `manifest` in a draft and publish it.
- `attributes.configSnippets` (array): The [snippet](https://developer.kustomer.com/api/settings-and-configurations#snippets) keys used in the manifest's labels and text. Kustomer collects them for you, so you don't send them.
- `attributes.jsxSnippets` (array): The snippet keys the theme's code uses. You list them, and each one must exist.
- `attributes.rev` (integer): The number of the published revision. A new draft takes the next number, and `rev` moves up to it when the draft is published.

### Relationships

- Referenced by **Knowledge bases** via `relationships.theme`: The theme a knowledge base's help center displays. Switching a knowledge base to another theme changes the site's look; editing the theme itself goes through its draft and publish cycle.

### Permissions

Fewest roles for a read-only integration: `org.permission.kb.read`. For every endpoint: `org.permission.kb.read`, `org.permission.kb.create`, `org.permission.kb.delete`, `org.permission.kb.update`.

## Request body

Content type: `application/json` (required)

- `name` (string, required): (min length 3; max length 256)
- `duplicateThemeId` (string<object-id>)
- `duplicateTemplateId` (string<object-id>)
- `status` (string): One of: `draft`, `published`.

Example:

```json
{
  "name": "example_name",
  "duplicateThemeId": "65f2c0a1b4e3d2001234abcd",
  "duplicateTemplateId": "65f2c0a1b4e3d2001234abcd",
  "status": "draft"
}
```

## Responses

### 201

Created

- `data` (object, required)
  - `type` (string, required)
  - `id` (string, required)
  - `attributes` (object, required)
    - `name` (string, required)
    - `active` (boolean, required)
    - `default` (boolean, required)
    - `lastFileUpdatedAt` (string, required)
    - `status` (string, required)
    - `templateVersionId` (string, required)
    - `manifest` (array<object>, required)
    - `configSnippets` (array<string>, required)
    - `jsxSnippets` (array<string>, required)
    - `createdAt` (string, required)
    - `updatedAt` (string, required)
    - `modifiedAt` (string, required)
    - `rev` (integer, required)
  - `relationships` (object, required)
    - `org` (object, required)
    - `createdBy` (object, required)
    - `modifiedBy` (object, required)
  - `links` (object, required)
    - `self` (string, required)

```json
{
  "data": {
    "type": "theme",
    "id": "6026d08efcca5f03e5541f39",
    "attributes": {
      "name": "Duplicate Midtown Theme",
      "active": false,
      "default": false,
      "lastFileUpdatedAt": "2021-02-12T19:01:34.058Z",
      "status": "published",
      "templateVersionId": "6026aba3fcca5f03e5541cd5",
      "manifest": [
        {
          "name": "design",
          "variables": {
            "headingsAndButtonsFont": {
              "name": "headingsAndButtonsFont",
              "type": "select",
              "enum": [
                {
                  "label": "Arial",
                  "value": "arial"
                },
                {
                  "label": "Verdana",
                  "value": "verdana"
                },
                {
                  "label": "Helvetica",
                  "value": "helvetica"
                }
              ],
              "value": "Helvetica"
            },
            "headingBaseSizeFont": {
              "name": "headingBaseSizeFont",
              "type": "slider",
              "value": "36px"
            },
            "bodyTextFont": {
              "name": "bodyTextFont",
              "type": "select",
              "enum": [
                {
                  "label": "Arial",
                  "value": "arial"
                },
                {
                  "label": "Verdana",
                  "value": "verdana"
                },
                {
                  "label": "Helvetica",
                  "value": "helvetica"
                }
              ],
              "value": "Helvetica"
            },
            "baseSizeFont": {
              "name": "baseSizeFont",
              "type": "slider",
              "value": "16px"
            },
            "headingsColor": {
              "name": "headingsColor",
              "type": "color",
              "value": "#0A3355"
            },
            "bodyTextColor": {
              "name": "bodyTextColor",
              "type": "color",
              "value": "#222222"
            },
            "secondaryTextColor": {
              "name": "secondaryTextColor",
              "type": "color",
              "value": "#939FA8"
            },
            "linksColor": {
              "name": "linksColor",
              "type": "color",
              "value": "#0A3355"
            },
            "primaryButtonColor": {
              "name": "primaryButtonColor",
              "type": "color",
              "value": "#0A3355"
            },
            "primaryButtonTextColor": {
              "name": "primaryButtonTextColor",
              "type": "color",
              "value": "#ffffff"
            },
            "primaryBackgroundPageColor": {
              "name": "primaryBackgroundPageColor",
              "type": "color",
              "value": "#ffffff"
            },
            "secondaryBackgroundPageColor": {
              "name": "secondaryBackgroundPageColor",
              "type": "color",
              "value": "#F9F9F9"
            },
            "borderPageColor": {
              "name": "borderPageColor",
              "type": "color",
              "value": "#B2B2B2"
            }
          }
        },
        {
          "name": "announcement",
          "label": "[[ sn.kustomer.themebuilder.announcement_label ]]",
          "enabled": true,
          "variables": {
            "homepageOnly": {
              "name": "homepageOnly",
              "type": "boolean",
              "label": "[[ sn.kustomer.themebuilder.announcement_show_on_home_page_label ]]",
              "value": false
            },
            "announcementText": {
              "name": "announcementText",
              "type": "text",
              "label": "[[ sn.kustomer.themebuilder.announcement_text_value ]]",
              "value": "Important update about our holiday hours"
            },
            "textColor": {
              "name": "textColor",
              "type": "color",
              "label": "[[ sn.kustomer.themebuilder.announcement_text_color_label ]]",
              "value": "#FFFFFF"
            },
            "backgroundColor": {
              "name": "backgroundColor",
              "type": "color",
              "label": "[[ sn.kustomer.themebuilder.announcement_background_color_label ]]",
              "value": "#E16360"
            },
            "ctaText": {
              "name": "ctaText",
              "type": "string",
              "label": "[[ sn.kustomer.themebuilder.cta_text_label ]]",
              "value": "<Snippet id=\"sn.kustomer.themebuilder.announcement_cta_text_value\" />"
            },
            "ctaTextColor": {
              "name": "ctaTextColor",
              "type": "color",
              "label": "[[ sn.kustomer.themebuilder.announcement_cta_text_color_label ]]",
              "value": "#FFFFFF"
            },
            "ctaLink": {
              "name": "ctaLink",
              "type": "link",
              "label": "[[ sn.kustomer.themebuilder.cta_link_label ]]",
              "value": ""
            }
          }
        },
        {
          "name": "header",
          "label": "[[ sn.kustomer.themebuilder.header_label ]]",
          "link": {
            "label": "[[ sn.kustomer.themebuilder.header_link_label ]]",
            "description": "[[ sn.kustomer.themebuilder.header_link_description ]]",
            "buttonText": "[[ sn.kustomer.themebuilder.header_link_button_text ]]",
            "value": "/app/settings/kb/config"
          },
          "variables": {
            "navigation": {
              "name": "navigation",
              "type": "list",
              "minItems": 1,
              "maxItems": 5,
              "label": "[[ sn.kustomer.themebuilder.header_navigation_label ]]",
              "buttonText": "[[ sn.kustomer.themebuilder.header_navigation_button_text ]]",
              "value": [
                {
                  "navigationText": {
                    "name": "navigationText",
                    "label": "[[ sn.kustomer.themebuilder.navigation_text_label_1 ]]",
                    "type": "string",
                    "value": "<Snippet id=\"sn.kustomer.themebuilder.navigation_text_value_1\" />"
                  },
                  "navigationLink": {
                    "name": "navigationLink",
                    "label": "[[ sn.kustomer.themebuilder.navigation_link_label_1 ]]",
                    "type": "link",
                    "value": ""
                  }
                }
              ]
            }
          }
        }
      ],
      "configSnippets": [
        "sn.kustomer.themebuilder.announcement_label",
        "sn.kustomer.themebuilder.announcement_show_on_home_page_label",
        "sn.kustomer.themebuilder.announcement_text_value"
      ],
      "jsxSnippets": [
        "sn.kustomer.themebuilder.announcement_cta_text_value",
        "sn.kustomer.themebuilder.navigation_text_value_1",
        "sn.kustomer.themebuilder.search_bar_primary_message_value"
      ],
      "createdAt": "2021-02-12T19:01:34.058Z",
      "updatedAt": "2021-02-12T19:01:34.058Z",
      "modifiedAt": "2021-02-12T19:01:34.058Z",
      "rev": 1
    },
    "relationships": {
      "org": {
        "links": {
          "self": "/v1/orgs/5e15fa33623f88001a8e0bb5"
        },
        "data": {
          "type": "org",
          "id": "5e15fa33623f88001a8e0bb5"
        }
      },
      "createdBy": {
        "links": {
          "self": "/v1/users/5e15fa45623f88001a8e0bbb"
        },
        "data": {
          "type": "user",
          "id": "5e15fa45623f88001a8e0bbb"
        }
      },
      "modifiedBy": {
        "links": {
          "self": "/v1/users/5e15fa45623f88001a8e0bbb"
        },
        "data": {
          "type": "user",
          "id": "5e15fa45623f88001a8e0bbb"
        }
      }
    },
    "links": {
      "self": "/v1/kb/themes/6026d08efcca5f03e5541f39"
    }
  }
}
```

### 400

Bad Request

### 401

Unauthorized

### 403

Forbidden

## Example request

```bash
curl --request POST \
  --url 'https://api.kustomerapp.com/v3/kb/themes' \
  --header "Authorization: Bearer $KUSTOMER_API_KEY" \
  --header 'Content-Type: application/json' \
  --data '{
  "name": "example_name",
  "duplicateThemeId": "65f2c0a1b4e3d2001234abcd",
  "duplicateTemplateId": "65f2c0a1b4e3d2001234abcd",
  "status": "draft"
}'
```
