Skip to content

Themes

Admin

Themes groups 9 operations on the admin tier.

Admin tier. Requires an RBAC-gated vnstat_ access token, sent as Authorization: Bearer … or X-Vinosoft-Access-Token.

GET

/api/{version}/admin/themes

Every theme of the tenant, unpaged. Exactly one carries role: "main".

AuthenticationToken requiredAdmin tier. Requires an RBAC-gated vnstat_ access token, sent as Authorization: Bearer … or X-Vinosoft-Access-Token.

Responses

curl -X GET \
  'https://<your-shop-domain>/api/2026-04-01/admin/themes' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer vnstat_<token>'
Response200example shape
{
  "themes": [
    {
      "id": "00000000-0000-0000-0000-000000000000",
      "name": "string",
      "role": "string",
      "theme_key": "string",
      "created_at": "2026-04-01T12:00:00Z",
      "updated_at": "2026-04-01T12:00:00Z"
    }
  ]
}
GET

/api/{version}/admin/themes/{id}

One theme record (no assets).

AuthenticationToken requiredAdmin tier. Requires an RBAC-gated vnstat_ access token, sent as Authorization: Bearer … or X-Vinosoft-Access-Token.

Path parameters

NameTypeDescription
id
required
string (uuid)

Responses

curl -X GET \
  'https://<your-shop-domain>/api/2026-04-01/admin/themes/<id>' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer vnstat_<token>'
Response200example shape
{
  "theme": {
    "id": "00000000-0000-0000-0000-000000000000",
    "name": "string",
    "role": "string",
    "theme_key": "string",
    "created_at": "2026-04-01T12:00:00Z",
    "updated_at": "2026-04-01T12:00:00Z"
  }
}
PUT

/api/{version}/admin/themes/{id}

Renames the theme and/or publishes it. role: "main" publishes (deactivating whichever theme held the role); role: "unpublished" is accepted but is a no-op, since the API never leaves a tenant without an active theme. A missing body or an unrecognized role is a 422.

AuthenticationToken requiredAdmin tier. Requires an RBAC-gated vnstat_ access token, sent as Authorization: Bearer … or X-Vinosoft-Access-Token.

Path parameters

NameTypeDescription
id
required
string (uuid)

Request body

application/json, text/json, application/*+json · optional

UpdateThemeRequest

Body for PUT /api/{version}/admin/themes/{id}. Both fields are optional; only the supplied ones are applied. Setting role to main publishes the theme (activating it and deactivating any other). unpublished is accepted but is a no-op — the API never leaves a tenant with no active theme (that would 503 the storefront).

  • namestringnullable
  • rolestringnullable

Responses

curl -X PUT \
  'https://<your-shop-domain>/api/2026-04-01/admin/themes/<id>' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer vnstat_<token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "string",
  "role": "string"
}'
Response200example shape
{
  "theme": {
    "id": "00000000-0000-0000-0000-000000000000",
    "name": "string",
    "role": "string",
    "theme_key": "string",
    "created_at": "2026-04-01T12:00:00Z",
    "updated_at": "2026-04-01T12:00:00Z"
  }
}
GET

/api/{version}/admin/themes/{id}/assets

The theme's text assets (Liquid, localization JSON, config). One route, two bodies: with ?key= the response carries asset (the file with its value), without it the response carries assets (every key plus metadata, no content). A key that escapes the theme root is a 422, not a 404.

AuthenticationToken requiredAdmin tier. Requires an RBAC-gated vnstat_ access token, sent as Authorization: Bearer … or X-Vinosoft-Access-Token.

Path parameters

NameTypeDescription
id
required
string (uuid)

Query parameters

NameTypeDescription
key
optional
string

Responses

curl -X GET \
  'https://<your-shop-domain>/api/2026-04-01/admin/themes/<id>/assets' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer vnstat_<token>'
Response200example shape
{
  "asset": {
    "key": "string",
    "value": "string",
    "size": 1,
    "content_type": "string"
  },
  "assets": [
    {
      "key": "string",
      "size": 1,
      "content_type": "string",
      "updated_at": "2026-04-01T12:00:00Z"
    }
  ]
}
PUT

/api/{version}/admin/themes/{id}/assets

Upserts one text asset from the JSON key/value body: creates it when absent, replaces it when present. A missing key or one that escapes the theme root is a 422.

AuthenticationToken requiredAdmin tier. Requires an RBAC-gated vnstat_ access token, sent as Authorization: Bearer … or X-Vinosoft-Access-Token.

Path parameters

NameTypeDescription
id
required
string (uuid)

Request body

application/json, text/json, application/*+json · optional

PutThemeAssetRequest

Body for PUT /api/{version}/admin/themes/{id}/assets. key is the asset path relative to the theme root (e.g. templates/product.liquid); value is its text content. Upserts: creates the asset when absent, replaces it when present.

  • keystringnullable
  • valuestringnullable

Responses

curl -X PUT \
  'https://<your-shop-domain>/api/2026-04-01/admin/themes/<id>/assets' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer vnstat_<token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "key": "string",
  "value": "string"
}'
Response200example shape
{
  "asset": {
    "key": "string",
    "value": "string",
    "size": 1,
    "content_type": "string"
  }
}
DELETE

/api/{version}/admin/themes/{id}/assets

Deletes one text asset. Returns 204 with no body; a missing or escaping key is a 422 and an unknown asset a 404.

AuthenticationToken requiredAdmin tier. Requires an RBAC-gated vnstat_ access token, sent as Authorization: Bearer … or X-Vinosoft-Access-Token.

Path parameters

NameTypeDescription
id
required
string (uuid)

Query parameters

NameTypeDescription
key
optional
string

Responses

curl -X DELETE \
  'https://<your-shop-domain>/api/2026-04-01/admin/themes/<id>/assets' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer vnstat_<token>'
GET

/api/{version}/admin/themes/{id}/assets/data

The theme's binary media. One route, two media types: the keyless form returns the JSON assets list documented below, while ?key= streams that asset's raw bytes with the asset's own Content-Type and no JSON envelope at all. Branch on the response's content type. A key that escapes the theme root is a 422.

AuthenticationToken requiredAdmin tier. Requires an RBAC-gated vnstat_ access token, sent as Authorization: Bearer … or X-Vinosoft-Access-Token.

Path parameters

NameTypeDescription
id
required
string (uuid)

Query parameters

NameTypeDescription
key
optional
string

Responses

curl -X GET \
  'https://<your-shop-domain>/api/2026-04-01/admin/themes/<id>/assets/data' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer vnstat_<token>'
Response200example shape
{
  "assets": [
    {
      "key": "string",
      "size": 1,
      "content_type": "string",
      "updated_at": "2026-04-01T12:00:00Z",
      "url": "string"
    }
  ]
}
PUT

/api/{version}/admin/themes/{id}/assets/data

Upserts one binary asset from the raw request body (no JSON envelope); the request's Content-Type is stored as the asset's. A body over 20 MB is a 413; a missing or escaping key is a 422. The upload is served by the storefront as soon as this returns.

AuthenticationToken requiredAdmin tier. Requires an RBAC-gated vnstat_ access token, sent as Authorization: Bearer … or X-Vinosoft-Access-Token.

Path parameters

NameTypeDescription
id
required
string (uuid)

Query parameters

NameTypeDescription
key
optional
string

Responses

curl -X PUT \
  'https://<your-shop-domain>/api/2026-04-01/admin/themes/<id>/assets/data' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer vnstat_<token>'
Response200example shape
{
  "asset": {
    "key": "string",
    "size": 1,
    "content_type": "string",
    "updated_at": "2026-04-01T12:00:00Z",
    "url": "string"
  }
}
DELETE

/api/{version}/admin/themes/{id}/assets/data

Deletes one binary asset. Returns 204 with no body; a missing or escaping key is a 422 and an unknown asset a 404.

AuthenticationToken requiredAdmin tier. Requires an RBAC-gated vnstat_ access token, sent as Authorization: Bearer … or X-Vinosoft-Access-Token.

Path parameters

NameTypeDescription
id
required
string (uuid)

Query parameters

NameTypeDescription
key
optional
string

Responses

curl -X DELETE \
  'https://<your-shop-domain>/api/2026-04-01/admin/themes/<id>/assets/data' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer vnstat_<token>'

Schemas

ApiErrorResponse

The error envelope every non-2xx response from this API uses. Documentation shape: actions build it as an anonymous object, so this type exists to give the OpenAPI document a schema to point at.

  • errorsstringnullable

    Human-readable description of what went wrong, e.g. Not Found, Invalid page_info.

  • codestringnullable

    Machine-readable error code. Only a few endpoints (checkout) emit one; omitted everywhere else.

PutThemeAssetRequest

Body for PUT /api/{version}/admin/themes/{id}/assets. key is the asset path relative to the theme root (e.g. templates/product.liquid); value is its text content. Upserts: creates the asset when absent, replaces it when present.

  • keystringnullable
  • valuestringnullable

ThemeAssetContentDto

An asset with its full text content (single read + upsert response).

  • keystringnullable
  • valuestringnullable
  • sizeinteger (int64)
  • content_typestringnullable

ThemeAssetDto

An asset list row: the key plus lightweight metadata, no content.

  • keystringnullable
  • sizeinteger (int64)nullable
  • content_typestringnullable
  • updated_atstring (date-time)nullable

ThemeAssetResponse

Envelope returned by PUT /admin/themes/{id}/assets. Always a single asset — the upsert addresses one key.

ThemeAssetsResponse

Envelope returned by GET /admin/themes/{id}/assets, whose body depends on the request: ?key= returns the single asset under asset, and the keyless form returns the whole key list under assets. Exactly one of the two members is present on any given response — the other is omitted entirely, never sent as null.

  • assetsThemeAssetDto[]nullable

    Every text asset in the theme — key plus metadata, no content. Present only for the keyless form; read a single key to get its value.

ThemeDataAssetDto

A binary theme-media asset (the themes/{id}/assets/data surface): key + metadata + the served URL. The bytes themselves stream over the wire, not through this JSON. url is the same address the storefront's asset_url resolves to, so it is directly usable.

  • keystringnullable
  • sizeinteger (int64)nullable
  • content_typestringnullable
  • updated_atstring (date-time)nullable
  • urlstringnullable

ThemeDataAssetListResponse

Envelope returned by the keyless GET /admin/themes/{id}/assets/data. The ?key= form of that same route does not return this — it streams the asset's raw bytes with the asset's own content type, so a client must branch on the response's Content-Type, not assume JSON.

  • assetsThemeDataAssetDto[]nullable

    Every binary asset in the theme — key, metadata and the served url, never the bytes. Always present; an empty array when the theme carries no media.

ThemeDataAssetResponse

Envelope returned by PUT /admin/themes/{id}/assets/data.

ThemeDto

Admin representation of a theme (the themes resource, backed by the existing ShopTheme domain). Serialized snake_case via explicit [JsonPropertyName] attributes, because the host's global JSON policy is camelCase. role follows Shopify: main for the single active theme, else unpublished.

  • idstring (uuid)
  • namestringnullable
  • rolestringnullable

    Publication role: main (the active theme) or unpublished.

  • theme_keystringnullable

    The library theme this was created from (e.g. vineyard); null for custom themes.

  • created_atstring (date-time)
  • updated_atstring (date-time)nullable

ThemeListResponse

Envelope returned by GET /admin/themes. Unpaged: a tenant has a handful of themes, so every one is returned in a single response — there is no Link header and no page_info here.

  • themesThemeDto[]nullable

    Every theme of the tenant. Always present, and never empty in practice: a tenant always keeps at least the active one, so exactly one row carries role: "main".

ThemeResponse

Envelope returned by GET /admin/themes/{id} and PUT /admin/themes/{id}.

UpdateThemeRequest

Body for PUT /api/{version}/admin/themes/{id}. Both fields are optional; only the supplied ones are applied. Setting role to main publishes the theme (activating it and deactivating any other). unpublished is accepted but is a no-op — the API never leaves a tenant with no active theme (that would 503 the storefront).

  • namestringnullable
  • rolestringnullable