{
  "openapi": "3.0.4",
  "info": {
    "title": "agentView Store API",
    "description": "Public template store: anonymous catalog discovery and template content, plus the authenticated install / send / copy flow under /api/v1/store.",
    "version": "v1"
  },
  "paths": {
    "/api/v1/store/templates": {
      "get": {
        "tags": [
          "TemplateStore"
        ],
        "parameters": [
          {
            "name": "language",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "category",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "search",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "tag",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.ListStoreTemplatesResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.ListStoreTemplatesResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.ListStoreTemplatesResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.ErrorResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.ErrorResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/store/templates/{slug}": {
      "get": {
        "tags": [
          "TemplateStore"
        ],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "language",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.StoreTemplateDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.StoreTemplateDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.StoreTemplateDto"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.ErrorResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.ErrorResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.ErrorResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.ErrorResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/store/templates/{slug}/agent-artifacts": {
      "get": {
        "tags": [
          "TemplateStore"
        ],
        "summary": "Public, anonymous list of agent artifacts shipped by a template.\nCompanion to the template detail page — the customer can see WHAT\nthey'll get for their bots (system prompt? Claude Code skill? MCP\nconfig?) before they install. Bodies are not returned in the list;\nthey're available via the per-artifact /raw endpoint with the\nplaceholders intact (post-install personalisation lives on\n/api/v1/owner/displays/{id}/agent-artifacts/{key}).",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "language",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.ListAgentArtifactsResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.ListAgentArtifactsResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.ListAgentArtifactsResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.ErrorResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.ErrorResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.ErrorResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.ErrorResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/store/templates/{slug}/agent-artifacts/{artifactKey}/raw": {
      "get": {
        "tags": [
          "TemplateStore"
        ],
        "summary": "Public, anonymous read of a single agent artifact body, placeholders\nintact (raw template content). The customer reads this on the public\ndetail page to evaluate the integration shape; the personalised\nversion with substituted slot slugs lives on the per-display endpoint.",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "artifactKey",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              },
              "application/json": {
                "schema": {
                  "type": "string"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/markdown": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.ErrorResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.ErrorResponse"
                }
              },
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/store/templates/{slug}/content": {
      "get": {
        "tags": [
          "TemplateStore"
        ],
        "summary": "Public, anonymous content fetch for a store template. Returns the raw\ndisplay HTML body (`{{asset:NAME}}` placeholders resolved to public\nURLs, `{{slot:KEY.prop}}` placeholders left intact), the static slot\ndefinitions, and the template's allowed external origins — everything an\neditor needs to insert the template as an editable slide in a single call.\nOnly the current published version is served; an explicit\nversion that no longer matches the published version\nreturns 404 so drafts never leak.",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "version",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.StoreTemplateContentResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.StoreTemplateContentResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.StoreTemplateContentResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.ErrorResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.ErrorResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/store/starter-templates": {
      "get": {
        "tags": [
          "TemplateStore"
        ],
        "summary": "The short list somebody picks from before they have an account: a handful\nof curated templates with the fields they can fill in right there.\n            \n\nCurated means the ones an admin already ordered for the landing\npage, falling back to the featured ones. A visitor who has just typed the\ncode off their screen is two clicks from content; a wall of two hundred\ntemplates is not that.\nEach template carries its slots with the bundle's own sample data,\nwhich is what the fields start filled with. Nothing here is per-account,\nso it stays anonymous like the rest of the public store.",
        "parameters": [
          {
            "name": "language",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 6
            }
          },
          {
            "name": "placement",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "viewportWidth",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "viewportHeight",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.ListStarterTemplatesResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.ListStarterTemplatesResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.ListStarterTemplatesResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/store/categories": {
      "get": {
        "tags": [
          "TemplateStore"
        ],
        "parameters": [
          {
            "name": "language",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.ListStoreCategoriesResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.ListStoreCategoriesResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.ListStoreCategoriesResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.ErrorResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.ErrorResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/store/templates/{slug}/try-on": {
      "post": {
        "tags": [
          "TemplateStoreDelivery"
        ],
        "summary": "Puts this template on a screen to look at, without installing it.\nOpens a fitting-room lease on the screen if there is none, and extends it\non every call.",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Screen.Central.Controllers.TemplateStoreDeliveryController.StoreTemplateTryOnRequest"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/Screen.Central.Controllers.TemplateStoreDeliveryController.StoreTemplateTryOnRequest"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/Screen.Central.Controllers.TemplateStoreDeliveryController.StoreTemplateTryOnRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Controllers.StoreTemplateTryOnResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Controllers.StoreTemplateTryOnResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Controllers.StoreTemplateTryOnResponse"
                }
              }
            }
          }
        },
        "security": [
          { }
        ]
      }
    },
    "/api/v1/store/try-on/{displayId}/back": {
      "post": {
        "tags": [
          "TemplateStoreDelivery"
        ],
        "summary": "Puts the candidate shown before the current one back on the screen.",
        "parameters": [
          {
            "name": "displayId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Controllers.StoreTemplateTryOnResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Controllers.StoreTemplateTryOnResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Controllers.StoreTemplateTryOnResponse"
                }
              }
            }
          }
        },
        "security": [
          { }
        ]
      }
    },
    "/api/v1/store/try-on/{displayId}/end": {
      "post": {
        "tags": [
          "TemplateStoreDelivery"
        ],
        "summary": "Ends the round and puts back whatever the screen was showing before it\nstarted. The most common outcome of a fitting room is no decision, so this\npath matters as much as the keeping one.",
        "parameters": [
          {
            "name": "displayId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Controllers.StoreTemplateTryOnResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Controllers.StoreTemplateTryOnResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Controllers.StoreTemplateTryOnResponse"
                }
              }
            }
          }
        },
        "security": [
          { }
        ]
      }
    },
    "/api/v1/store/try-on/{displayId}": {
      "get": {
        "tags": [
          "TemplateStoreDelivery"
        ],
        "summary": "What is running in this screen's fitting room, so a page reloaded\nmid-round can pick the round up instead of starting over.",
        "parameters": [
          {
            "name": "displayId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Controllers.StoreTemplateTryOnResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Controllers.StoreTemplateTryOnResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Controllers.StoreTemplateTryOnResponse"
                }
              }
            }
          }
        },
        "security": [
          { }
        ]
      }
    },
    "/api/v1/store/templates/{slug}/install-options": {
      "get": {
        "tags": [
          "TemplateStoreDelivery"
        ],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.StoreTemplateInstallOptionsResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.StoreTemplateInstallOptionsResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.StoreTemplateInstallOptionsResponse"
                }
              }
            }
          }
        },
        "security": [
          { }
        ]
      }
    },
    "/api/v1/store/templates/{slug}/send": {
      "post": {
        "tags": [
          "TemplateStoreDelivery"
        ],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Screen.Central.Controllers.TemplateStoreDeliveryController.StoreTemplateSendRequest"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/Screen.Central.Controllers.TemplateStoreDeliveryController.StoreTemplateSendRequest"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/Screen.Central.Controllers.TemplateStoreDeliveryController.StoreTemplateSendRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.StoreTemplateSendResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.StoreTemplateSendResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.StoreTemplateSendResponse"
                }
              }
            }
          }
        },
        "security": [
          { }
        ]
      }
    },
    "/api/v1/store/templates/{slug}/copy": {
      "post": {
        "tags": [
          "TemplateStoreDelivery"
        ],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.StoreTemplateCopyResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.StoreTemplateCopyResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.StoreTemplateCopyResponse"
                }
              }
            }
          }
        },
        "security": [
          { }
        ]
      }
    },
    "/api/v1/store/templates/{slug}/preview-share": {
      "post": {
        "tags": [
          "TemplateStoreDelivery"
        ],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Controllers.StoreTemplatePreviewShareResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Controllers.StoreTemplatePreviewShareResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Controllers.StoreTemplatePreviewShareResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/store/templates/{slug}/materialize": {
      "post": {
        "tags": [
          "TemplateStoreDelivery"
        ],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Screen.Central.Controllers.TemplateStoreDeliveryController.StoreTemplateMaterializeRequest"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/Screen.Central.Controllers.TemplateStoreDeliveryController.StoreTemplateMaterializeRequest"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/Screen.Central.Controllers.TemplateStoreDeliveryController.StoreTemplateMaterializeRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.StoreTemplateMaterializeResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.StoreTemplateMaterializeResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/Screen.Central.Contracts.StoreTemplateMaterializeResponse"
                }
              }
            }
          }
        },
        "security": [
          { }
        ]
      }
    }
  },
  "components": {
    "schemas": {
      "Screen.Central.Contracts.ErrorResponse": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "nullable": true
          },
          "message": {
            "type": "string",
            "nullable": true
          },
          "hint": {
            "type": "string",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "Error response shape — unified error envelope used across all controllers."
      },
      "Screen.Central.Contracts.ListAgentArtifactsResponse": {
        "type": "object",
        "properties": {
          "artifacts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Screen.Central.Services.Store.AgentArtifactSummary"
            },
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "The agent-facing files that ship with a template: what an AI agent needs to\nread to fill it in. The bodies are fetched one at a time from the raw\nendpoint."
      },
      "Screen.Central.Contracts.ListStarterTemplatesResponse": {
        "type": "object",
        "properties": {
          "templates": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Screen.Central.Contracts.StarterTemplateDto"
            },
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "Public, anonymous response for `GET /api/v1/store/starter-templates`:\nthe short list somebody picks from before they have an account, each with\nthe fields they can fill in on the spot."
      },
      "Screen.Central.Contracts.ListStoreCategoriesResponse": {
        "type": "object",
        "properties": {
          "categories": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Screen.Central.Contracts.StoreCategoryDto"
            },
            "nullable": true
          }
        },
        "additionalProperties": false
      },
      "Screen.Central.Contracts.ListStoreTemplatesResponse": {
        "type": "object",
        "properties": {
          "templates": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Screen.Central.Contracts.StoreTemplateDto"
            },
            "nullable": true
          },
          "total": {
            "type": "integer",
            "format": "int32"
          },
          "offset": {
            "type": "integer",
            "format": "int32"
          },
          "limit": {
            "type": "integer",
            "format": "int32"
          }
        },
        "additionalProperties": false,
        "description": "Screen.Central.Contracts.ListStoreTemplatesResponse.Total counts every template that matched the filters, not the\n            page. Screen.Central.Contracts.ListStoreTemplatesResponse.Limit is the clamped limit actually applied, which can be\n            lower than the one requested."
      },
      "Screen.Central.Contracts.StarterTemplateDto": {
        "type": "object",
        "properties": {
          "slug": {
            "type": "string",
            "description": "Canonical template slug, which is what a choice stores.",
            "nullable": true
          },
          "title": {
            "type": "string",
            "description": "Display title in the requested language.",
            "nullable": true
          },
          "shortDescription": {
            "type": "string",
            "description": "One line under the title.",
            "nullable": true
          },
          "previewUrl": {
            "type": "string",
            "description": "The embeddable preview shell on the display origin. Add the choice note as\n`m` to see the visitor's own fields in it.",
            "nullable": true
          },
          "fields": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Screen.Central.Contracts.StarterTemplateFieldDto"
            },
            "description": "The template's data slots, in the order they are shown.",
            "nullable": true
          },
          "imageUrl": {
            "type": "string",
            "description": "The card picture, the same one the store shows. Null when the template has\nno screenshot yet, which is a caller's problem to fall back from rather than\na reason to hide the template.",
            "nullable": true
          },
          "imagePortraitUrl": {
            "type": "string",
            "description": "The portrait crop, when the template has one. A phone standing in for a\nscreen is the common case on this route, and a 16:9 card above a portrait\nscreen promises the wrong shape.",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "One template on that list: enough to show a card and a preview, and the\nfields behind it."
      },
      "Screen.Central.Contracts.StarterTemplateFieldDto": {
        "type": "object",
        "properties": {
          "key": {
            "type": "string",
            "description": "Slot key, which is what a choice sends back as an override.",
            "nullable": true
          },
          "label": {
            "type": "string",
            "description": "Human label for the field.",
            "nullable": true
          },
          "slotType": {
            "type": "string",
            "description": "The slot's declared type.",
            "nullable": true
          },
          "required": {
            "type": "boolean",
            "description": "Whether the template needs this slot to render sensibly."
          },
          "defaultJson": {
            "type": "string",
            "description": "The bundle's sample data as JSON: what the field is prefilled with.",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "One editable field: a data slot, with the bundle's own sample as the value\nthe form starts from."
      },
      "Screen.Central.Contracts.StoreCategoryDto": {
        "type": "object",
        "properties": {
          "slug": {
            "type": "string",
            "nullable": true
          },
          "title": {
            "type": "string",
            "nullable": true
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "templateCount": {
            "type": "integer",
            "format": "int32"
          }
        },
        "additionalProperties": false
      },
      "Screen.Central.Contracts.StoreTemplateContentResponse": {
        "type": "object",
        "properties": {
          "slug": {
            "type": "string",
            "description": "Canonical template slug.",
            "nullable": true
          },
          "version": {
            "type": "string",
            "description": "The published version id (`stpv_…`) this body belongs to.",
            "nullable": true
          },
          "html": {
            "type": "string",
            "description": "The display HTML body. `{{asset:NAME}}` placeholders are resolved to\ntheir public URLs; `{{slot:KEY.prop}}` placeholders are left intact so\nthe consumer can wire up its own slot bindings using Screen.Central.Contracts.StoreTemplateContentResponse.Slots.",
            "nullable": true
          },
          "slots": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Screen.Central.Services.Store.StoreTemplateSlotRequirement"
            },
            "description": "Static slot definitions for this template — identical in shape to the\n`requiredDataSlots` returned by `install-options`.",
            "nullable": true
          },
          "allowedExternalOrigins": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "External origins the template is allowed to reference, for CSP / embed hints.\nEmpty when the template declares none.",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "Public, anonymous response for\n`GET /api/v1/store/templates/{slug}/content`. Carries everything an\neditor needs to insert a store template as an editable slide in a single\ncall: the raw display HTML, the static slot definitions, and the template's\nallowed external origins (for CSP / embed hints)."
      },
      "Screen.Central.Contracts.StoreTemplateCopyResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "templateSlug": {
            "type": "string",
            "nullable": true
          },
          "templateId": {
            "type": "string",
            "nullable": true
          },
          "name": {
            "type": "string",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "Response for `POST /api/v1/store/templates/{slug}/copy`: the private\ntemplate created from the store template."
      },
      "Screen.Central.Contracts.StoreTemplateDto": {
        "type": "object",
        "properties": {
          "slug": {
            "type": "string",
            "nullable": true
          },
          "sourceExampleId": {
            "type": "string",
            "nullable": true
          },
          "title": {
            "type": "string",
            "nullable": true
          },
          "shortDescription": {
            "type": "string",
            "nullable": true
          },
          "category": {
            "$ref": "#/components/schemas/Screen.Central.Contracts.StoreCategoryDto"
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          },
          "theme": {
            "type": "string",
            "nullable": true
          },
          "designStyle": {
            "type": "string",
            "nullable": true
          },
          "features": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          },
          "previewUrl": {
            "type": "string",
            "nullable": true
          },
          "detailUrl": {
            "type": "string",
            "nullable": true
          },
          "fileName": {
            "type": "string",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "One template in the store.\nScreen.Central.Contracts.StoreTemplateDto.PreviewUrl renders it and Screen.Central.Contracts.StoreTemplateDto.DetailUrl is its public\npage; both are paths on this host, not absolute URLs."
      },
      "Screen.Central.Contracts.StoreTemplateInstallOptionsResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "templateSlug": {
            "type": "string",
            "nullable": true
          },
          "displays": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Screen.Central.Services.Store.StoreTemplateInstallDisplay"
            },
            "nullable": true
          },
          "requiredDataSlots": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Screen.Central.Services.Store.StoreTemplateSlotRequirement"
            },
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "Response for `GET /api/v1/store/templates/{slug}/install-options`:\nthe displays the caller can install onto and the data slots the template\nneeds."
      },
      "Screen.Central.Contracts.StoreTemplateMaterializeResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "templateSlug": {
            "type": "string",
            "nullable": true
          },
          "versionId": {
            "type": "string",
            "nullable": true
          },
          "html": {
            "type": "string",
            "nullable": true
          },
          "installedSlots": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Screen.Central.Services.Store.StoreTemplateInstalledSlot"
            },
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "Response for `POST /api/v1/store/templates/{slug}/materialize`: the\nrendered, display-scoped HTML plus the slots materialised for that display."
      },
      "Screen.Central.Contracts.StoreTemplateSendResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "templateSlug": {
            "type": "string",
            "nullable": true
          },
          "versionId": {
            "type": "string",
            "nullable": true
          },
          "displayId": {
            "type": "string",
            "nullable": true
          },
          "fileName": {
            "type": "string",
            "nullable": true
          },
          "contentVersionId": {
            "type": "string",
            "nullable": true
          },
          "installedSlots": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Screen.Central.Services.Store.StoreTemplateInstalledSlot"
            },
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "Response for `POST /api/v1/store/templates/{slug}/send`: the published\nversion that was delivered to the display plus the data slots that were\nmaterialised (or reused) during the install."
      },
      "Screen.Central.Controllers.StoreTemplatePreviewShareResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "slug": {
            "type": "string",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "Echoes the template the share was recorded for."
      },
      "Screen.Central.Controllers.StoreTemplateTryOnResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "description": "Whether the call succeeded."
          },
          "running": {
            "type": "boolean",
            "description": "Whether a round is open on this screen."
          },
          "templateSlug": {
            "type": "string",
            "description": "The candidate currently on the screen, when there is one.",
            "nullable": true
          },
          "displayId": {
            "type": "string",
            "description": "The screen this round belongs to.",
            "nullable": true
          },
          "expiresAt": {
            "type": "string",
            "description": "When the round gives up by itself and the screen goes back to what it was\nshowing. Every call pushes this out again.",
            "format": "date-time",
            "nullable": true
          },
          "shownSlugs": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The candidates shown in this round, oldest first, so a client can offer a way\nback to the one somebody liked.",
            "nullable": true
          },
          "previousSlug": {
            "type": "string",
            "description": "The candidate one step back, or null at the start of a round. Lets a client\nenable or disable its back control without keeping its own list.",
            "nullable": true
          },
          "ended": {
            "type": "boolean",
            "description": "True when this call closed the round."
          }
        },
        "additionalProperties": false,
        "description": "State of a screen's fitting room after a try-on call."
      },
      "Screen.Central.Controllers.TemplateStoreDeliveryController.StoreTemplateMaterializeRequest": {
        "type": "object",
        "properties": {
          "displayId": {
            "type": "string",
            "nullable": true
          }
        },
        "additionalProperties": false
      },
      "Screen.Central.Controllers.TemplateStoreDeliveryController.StoreTemplateSendRequest": {
        "type": "object",
        "properties": {
          "displayId": {
            "type": "string",
            "description": "Target display id.",
            "nullable": true
          },
          "slotOverrides": {
            "type": "object",
            "additionalProperties": { },
            "description": "Optional per-slot content overrides, keyed by the template's slot\n`Key`. Each value is arbitrary JSON (object, array, or scalar) that\npre-fills the slot when the template is sent, so a template can be rolled\nout with content in one call. Unknown keys are ignored; oversize or\nnon-JSON values are rejected.",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "Body for `POST /api/v1/store/templates/{slug}/send`."
      },
      "Screen.Central.Controllers.TemplateStoreDeliveryController.StoreTemplateTryOnRequest": {
        "type": "object",
        "properties": {
          "displayId": {
            "type": "string",
            "description": "The screen to show the candidate on.",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "Body for `POST /api/v1/store/templates/{slug}/try-on`."
      },
      "Screen.Central.Services.Store.AgentArtifactSummary": {
        "type": "object",
        "properties": {
          "key": {
            "type": "string",
            "nullable": true
          },
          "kind": {
            "type": "string",
            "nullable": true
          },
          "fileName": {
            "type": "string",
            "nullable": true
          },
          "contentType": {
            "type": "string",
            "nullable": true
          },
          "sizeBytes": {
            "type": "integer",
            "format": "int32"
          },
          "label": {
            "type": "string",
            "nullable": true
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "sortOrder": {
            "type": "integer",
            "format": "int32"
          }
        },
        "additionalProperties": false
      },
      "Screen.Central.Services.Store.StoreTemplateInstallDisplay": {
        "type": "object",
        "properties": {
          "displayId": {
            "type": "string",
            "description": "The screen's profile id, which a send or try-on addresses.",
            "nullable": true
          },
          "name": {
            "type": "string",
            "description": "Display name, falling back to the id when unnamed.",
            "nullable": true
          },
          "scope": {
            "type": "string",
            "description": "\"personal\" or \"group\", mirroring where the screen lives.",
            "nullable": true
          },
          "groupId": {
            "type": "string",
            "description": "Owning group when the scope is group, otherwise null.",
            "nullable": true
          },
          "isLocked": {
            "type": "boolean",
            "description": "A locked screen takes no content; the fitting room filters these out."
          },
          "hasOwnContent": {
            "type": "boolean",
            "description": "True when the screen currently shows stored content of its own, so a try-on\nwould replace something somebody put there. It is what the fitting room warns\nabout once per screen; on an empty screen there is nothing to warn about, and\na warning that fires either way teaches people to ignore it.\nMeasured against the stored file, not merely the recorded file name, because\na name whose file is gone is not content."
          },
          "isPortrait": {
            "type": "boolean",
            "description": "True when the screen reported a viewport taller than it is wide. The fitting\nroom swaps every candidate's thumbnail to its portrait render while such a\nscreen is selected. A screen that never connected is false, which is what\nevery card already assumed."
          }
        },
        "additionalProperties": false
      },
      "Screen.Central.Services.Store.StoreTemplateInstalledSlot": {
        "type": "object",
        "properties": {
          "key": {
            "type": "string",
            "nullable": true
          },
          "placeholderName": {
            "type": "string",
            "nullable": true
          },
          "slug": {
            "type": "string",
            "nullable": true
          },
          "readUrl": {
            "type": "string",
            "nullable": true
          },
          "groupId": {
            "type": "string",
            "nullable": true
          },
          "slotType": {
            "type": "string",
            "nullable": true
          }
        },
        "additionalProperties": false
      },
      "Screen.Central.Services.Store.StoreTemplateSlotRequirement": {
        "type": "object",
        "properties": {
          "key": {
            "type": "string",
            "nullable": true
          },
          "label": {
            "type": "string",
            "nullable": true
          },
          "slotType": {
            "type": "string",
            "nullable": true
          },
          "placeholderName": {
            "type": "string",
            "nullable": true
          },
          "required": {
            "type": "boolean"
          },
          "defaultJson": {
            "type": "string",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "One slot a template needs, and the bundle's own sample for it.\n            \n\n`DefaultJson` is what an editor starts filled with. Without it a\nform would ask somebody to type JSON from nothing, which is not editing, it\nis authoring. The pairing chooser has carried this since it was written; the\nstore's send path had the slot list but not the values, so it could only ever\ninstall the samples unseen."
      }
    },
    "securitySchemes": {
      "Bearer": {
        "type": "http",
        "description": "Bearer token returned by the agent session flow.",
        "scheme": "Bearer",
        "bearerFormat": "JWT"
      }
    }
  },
  "tags": [
    {
      "name": "TemplateStore"
    },
    {
      "name": "TemplateStoreDelivery"
    }
  ]
}