{
  "openapi": "3.1.0",
  "info": {
    "title": "Hystore theme API",
    "version": "1.0.0",
    "description": "Code theme of a Hystore store: draft files, checks, preview links, publish requests, versions and assets. The store is always the one of the credential (a theme key `hys_theme_...` created in the dashboard, or a session of the hystore tool). Nothing here reaches orders, payments, players or settings. Requests from web pages (with an Origin header) are refused. Limits: 120 reads and 30 writes per minute per credential (429 with Retry-After). AI apps (Claude, Cursor and others) connect at https://mcp.hystore.com.br/mcp with the OAuth login of the dashboard; those tokens open only /mcp, and the tokens of this API never open /mcp. Errors: `{ \"errors\": [{ \"code\", \"message\", \"path\"?, \"line\"? }] }`."
  },
  "servers": [
    {
      "url": "https://theme.hystore.com.br"
    }
  ],
  "components": {
    "securitySchemes": {
      "bearer": {
        "type": "http",
        "scheme": "bearer",
        "description": "Theme key (hys_theme_...) or access token of the hystore tool (hys_at_...). Scopes: theme:read, theme:write, theme:publish-request, never more than the role of the person who created it allows."
      },
      "aiApp": {
        "type": "oauth2",
        "description": "Login of an AI app: the person approves it in the dashboard, chooses the store and the scopes. PKCE (S256) is required; clients register themselves (RFC 7591). Only for /mcp.",
        "flows": {
          "authorizationCode": {
            "authorizationUrl": "https://app.hystore.com.br/oauth/authorize",
            "tokenUrl": "https://mcp.hystore.com.br/v1/oauth/token",
            "refreshUrl": "https://mcp.hystore.com.br/v1/oauth/token",
            "scopes": {
              "theme:read": "Read the theme, versions and the public catalog",
              "theme:write": "Change the draft and its images",
              "theme:publish-request": "Ask the store to publish (a person approves)"
            }
          }
        }
      }
    },
    "responses": {
      "Error": {
        "description": "Error",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Errors"
            }
          }
        }
      }
    },
    "schemas": {
      "Errors": {
        "type": "object",
        "properties": {
          "errors": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "code": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                },
                "path": {
                  "type": "string"
                },
                "line": {
                  "type": "integer"
                },
                "currentSha": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              },
              "required": [
                "code",
                "message"
              ]
            }
          }
        }
      },
      "Problem": {
        "type": "object",
        "properties": {
          "path": {
            "type": "string"
          },
          "line": {
            "type": "integer"
          },
          "code": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "severity": {
            "enum": [
              "error",
              "warning"
            ]
          }
        },
        "required": [
          "path",
          "code",
          "message",
          "severity"
        ]
      },
      "FileSummary": {
        "type": "object",
        "properties": {
          "path": {
            "type": "string"
          },
          "sha256": {
            "type": "string"
          },
          "bytes": {
            "type": "integer"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Asset": {
        "type": "object",
        "properties": {
          "path": {
            "type": "string",
            "example": "assets/logo.webp"
          },
          "contentType": {
            "type": "string"
          },
          "bytes": {
            "type": "integer"
          },
          "sha256": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          }
        }
      },
      "Change": {
        "type": "object",
        "required": [
          "path",
          "content"
        ],
        "properties": {
          "path": {
            "type": "string"
          },
          "content": {
            "type": [
              "string",
              "null"
            ],
            "description": "null deletes the file"
          },
          "baseSha": {
            "type": [
              "string",
              "null"
            ],
            "description": "The sha256 you read: the change is refused (409) if the file changed since. null: the file must not exist yet. Absent: write anyway."
          }
        }
      }
    }
  },
  "paths": {
    "/v1/health": {
      "get": {
        "summary": "Service health",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "const": "ok"
                    }
                  }
                }
              }
            }
          }
        },
        "security": []
      }
    },
    "/v1/me": {
      "get": {
        "summary": "Who the credential is: store, scopes",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "storeId": {
                      "type": "string"
                    },
                    "store": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": "string"
                        },
                        "domain": {
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      }
                    },
                    "scopes": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "credential": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "kind": {
                          "enum": [
                            "api-key",
                            "oauth"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ]
      }
    },
    "/v1/theme": {
      "get": {
        "summary": "Draft revision and file list",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "revision": {
                      "type": "integer"
                    },
                    "files": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/FileSummary"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": [
          {
            "bearer": [
              "theme:read"
            ]
          }
        ],
        "x-scope": "theme:read"
      }
    },
    "/v1/theme/files": {
      "get": {
        "summary": "File list of the draft",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "files": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/FileSummary"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": [
          {
            "bearer": [
              "theme:read"
            ]
          }
        ],
        "x-scope": "theme:read"
      },
      "post": {
        "summary": "Write several files at once (all or nothing, up to 100 changes)",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "revision": {
                      "type": "integer"
                    },
                    "files": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "path": {
                            "type": "string"
                          },
                          "sha256": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        }
                      }
                    },
                    "warnings": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Problem"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "409": {
            "$ref": "#/components/responses/Error"
          },
          "422": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": [
          {
            "bearer": [
              "theme:write"
            ]
          }
        ],
        "x-scope": "theme:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "changes"
                ],
                "properties": {
                  "changes": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/Change"
                    },
                    "maxItems": 100
                  },
                  "expectedRevision": {
                    "type": "integer",
                    "description": "Refused (409) if the draft is at another revision."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/theme/file": {
      "get": {
        "summary": "Read one file of the draft",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "path": {
                      "type": "string"
                    },
                    "content": {
                      "type": "string"
                    },
                    "sha256": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": [
          {
            "bearer": [
              "theme:read"
            ]
          }
        ],
        "x-scope": "theme:read",
        "parameters": [
          {
            "name": "path",
            "in": "query",
            "required": true,
            "description": "Theme path, such as sections/hero.liquid",
            "schema": {
              "type": "string"
            }
          }
        ]
      },
      "put": {
        "summary": "Write one file (checked: 422 with the problems and lines when refused)",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "revision": {
                      "type": "integer"
                    },
                    "sha256": {
                      "type": "string"
                    },
                    "warnings": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Problem"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "409": {
            "$ref": "#/components/responses/Error"
          },
          "422": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": [
          {
            "bearer": [
              "theme:write"
            ]
          }
        ],
        "x-scope": "theme:write",
        "parameters": [
          {
            "name": "path",
            "in": "query",
            "required": true,
            "description": "Theme path, such as sections/hero.liquid",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "content"
                ],
                "properties": {
                  "content": {
                    "type": "string"
                  },
                  "baseSha": {
                    "type": [
                      "string",
                      "null"
                    ]
                  }
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Delete one file",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "revision": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "409": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": [
          {
            "bearer": [
              "theme:write"
            ]
          }
        ],
        "x-scope": "theme:write",
        "parameters": [
          {
            "name": "path",
            "in": "query",
            "required": true,
            "description": "Theme path, such as sections/hero.liquid",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "baseSha",
            "in": "query",
            "required": false,
            "description": "sha256 the file must still have",
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/v1/theme/check": {
      "post": {
        "summary": "Check the whole draft",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "problems": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Problem"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": [
          {
            "bearer": [
              "theme:read"
            ]
          }
        ],
        "x-scope": "theme:read"
      }
    },
    "/v1/theme/publish-requests": {
      "post": {
        "summary": "Ask to publish the current draft (someone with permission approves in the dashboard)",
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "requestId": {
                      "type": "string"
                    },
                    "draftRevision": {
                      "type": "integer"
                    },
                    "reused": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "422": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": [
          {
            "bearer": [
              "theme:publish-request"
            ]
          }
        ],
        "x-scope": "theme:publish-request",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "note": {
                    "type": "string",
                    "maxLength": 500
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/theme/export": {
      "get": {
        "summary": "Every text file of the draft with its content and hash",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "revision": {
                      "type": "integer"
                    },
                    "files": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "path": {
                            "type": "string"
                          },
                          "content": {
                            "type": "string"
                          },
                          "sha256": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": [
          {
            "bearer": [
              "theme:read"
            ]
          }
        ],
        "x-scope": "theme:read"
      }
    },
    "/v1/theme/versions": {
      "get": {
        "summary": "The last 30 published versions",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "versions": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "version": {
                            "type": "integer"
                          },
                          "source": {
                            "enum": [
                              "DASHBOARD",
                              "CLI",
                              "API",
                              "MCP"
                            ]
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": [
          {
            "bearer": [
              "theme:read"
            ]
          }
        ],
        "x-scope": "theme:read"
      }
    },
    "/v1/theme/versions/{version}/file": {
      "get": {
        "summary": "A text file as it was in a version (content null when the version did not have it)",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "version": {
                      "type": "integer"
                    },
                    "path": {
                      "type": "string"
                    },
                    "content": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": [
          {
            "bearer": [
              "theme:read"
            ]
          }
        ],
        "x-scope": "theme:read",
        "parameters": [
          {
            "name": "version",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "path",
            "in": "query",
            "required": true,
            "description": "Theme path, such as sections/hero.liquid",
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/v1/theme/versions/{version}/restore": {
      "post": {
        "summary": "Bring a version back to the draft (the live store does not change)",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "draftRevision": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": [
          {
            "bearer": [
              "theme:write"
            ]
          }
        ],
        "x-scope": "theme:write",
        "parameters": [
          {
            "name": "version",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ]
      }
    },
    "/v1/theme/preview": {
      "post": {
        "summary": "A 24-hour link that opens the draft on the store's address and reloads when it changes",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "url": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "uri"
                    },
                    "expiresAt": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": [
          {
            "bearer": [
              "theme:read"
            ]
          }
        ],
        "x-scope": "theme:read"
      }
    },
    "/v1/theme/assets": {
      "get": {
        "summary": "Images and fonts of the draft",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "assets": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Asset"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": [
          {
            "bearer": [
              "theme:read"
            ]
          }
        ],
        "x-scope": "theme:read"
      }
    },
    "/v1/theme/asset": {
      "put": {
        "summary": "Upload an image (png, jpg, webp, gif, avif up to 3 MB) or font (woff, woff2 up to 1 MB); the type is read from the bytes",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "revision": {
                      "type": "integer"
                    },
                    "asset": {
                      "$ref": "#/components/schemas/Asset"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "413": {
            "$ref": "#/components/responses/Error"
          },
          "422": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": [
          {
            "bearer": [
              "theme:write"
            ]
          }
        ],
        "x-scope": "theme:write",
        "parameters": [
          {
            "name": "path",
            "in": "query",
            "required": true,
            "description": "assets/<name>.<ext>, lower case",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/octet-stream": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Delete an image or font",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "revision": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": [
          {
            "bearer": [
              "theme:write"
            ]
          }
        ],
        "x-scope": "theme:write",
        "parameters": [
          {
            "name": "path",
            "in": "query",
            "required": true,
            "description": "assets/<name>.<ext>",
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/v1/oauth/device": {
      "post": {
        "summary": "Start the login of a tool (device flow): the person approves the code in the dashboard",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "device_code": {
                      "type": "string"
                    },
                    "user_code": {
                      "type": "string",
                      "example": "BCDF-GHJK"
                    },
                    "verification_uri": {
                      "type": "string"
                    },
                    "verification_uri_complete": {
                      "type": "string"
                    },
                    "expires_in": {
                      "type": "integer"
                    },
                    "interval": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": [],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "client_name": {
                    "type": "string",
                    "maxLength": 80
                  },
                  "scope": {
                    "type": "string",
                    "example": "theme:read theme:write theme:publish-request"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/oauth/token": {
      "post": {
        "summary": "Exchange an approved device code (hystore tool) or an authorization code with its PKCE verifier (AI app), or renew with the refresh token (it rotates; reusing an old one revokes the session)",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "access_token": {
                      "type": "string"
                    },
                    "token_type": {
                      "const": "Bearer"
                    },
                    "expires_in": {
                      "type": "integer"
                    },
                    "refresh_token": {
                      "type": "string"
                    },
                    "scope": {
                      "type": "string"
                    },
                    "store_id": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "OAuth error: authorization_pending, slow_down, access_denied, expired_token, invalid_grant, invalid_target, invalid_client",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    },
                    "error_description": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "grant_type"
                ],
                "properties": {
                  "grant_type": {
                    "enum": [
                      "urn:ietf:params:oauth:grant-type:device_code",
                      "authorization_code",
                      "refresh_token"
                    ]
                  },
                  "device_code": {
                    "type": "string"
                  },
                  "refresh_token": {
                    "type": "string"
                  },
                  "code": {
                    "type": "string",
                    "description": "authorization_code: the one-use code (hys_ac_...), valid for 60 seconds"
                  },
                  "code_verifier": {
                    "type": "string",
                    "description": "authorization_code: the PKCE verifier"
                  },
                  "redirect_uri": {
                    "type": "string",
                    "description": "authorization_code: the same address of the authorization"
                  },
                  "client_id": {
                    "type": "string",
                    "description": "authorization_code: the id from the registration (hys_cl_...)"
                  },
                  "resource": {
                    "type": "string",
                    "description": "authorization_code: https://mcp.hystore.com.br/mcp"
                  }
                }
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": [
                  "grant_type"
                ],
                "properties": {
                  "grant_type": {
                    "enum": [
                      "urn:ietf:params:oauth:grant-type:device_code",
                      "authorization_code",
                      "refresh_token"
                    ]
                  },
                  "device_code": {
                    "type": "string"
                  },
                  "refresh_token": {
                    "type": "string"
                  },
                  "code": {
                    "type": "string",
                    "description": "authorization_code: the one-use code (hys_ac_...), valid for 60 seconds"
                  },
                  "code_verifier": {
                    "type": "string",
                    "description": "authorization_code: the PKCE verifier"
                  },
                  "redirect_uri": {
                    "type": "string",
                    "description": "authorization_code: the same address of the authorization"
                  },
                  "client_id": {
                    "type": "string",
                    "description": "authorization_code: the id from the registration (hys_cl_...)"
                  },
                  "resource": {
                    "type": "string",
                    "description": "authorization_code: https://mcp.hystore.com.br/mcp"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/oauth/revoke": {
      "post": {
        "summary": "Log out: ends the whole session (always 200)",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "token"
                ],
                "properties": {
                  "token": {
                    "type": "string"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/oauth/register": {
      "post": {
        "summary": "Register an AI app (RFC 7591): public client, no secret. The name is the one the app gives; the dashboard shows it with the address the access goes to",
        "servers": [
          {
            "url": "https://mcp.hystore.com.br"
          }
        ],
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "redirect_uris"
                ],
                "properties": {
                  "client_name": {
                    "type": "string",
                    "description": "Shown on the consent screen, cut to 80 characters (letters, numbers and simple punctuation)"
                  },
                  "redirect_uris": {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 10,
                    "items": {
                      "type": "string"
                    },
                    "description": "https, http only for localhost, 127.0.0.1 or [::1], or an app scheme. No fragment, no user in the address"
                  },
                  "client_uri": {
                    "type": "string"
                  },
                  "token_endpoint_auth_method": {
                    "const": "none"
                  },
                  "grant_types": {
                    "type": "array",
                    "items": {
                      "enum": [
                        "authorization_code",
                        "refresh_token"
                      ]
                    }
                  },
                  "response_types": {
                    "type": "array",
                    "items": {
                      "const": "code"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Registered",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "client_id": {
                      "type": "string"
                    },
                    "client_id_issued_at": {
                      "type": "integer"
                    },
                    "client_name": {
                      "type": "string"
                    },
                    "redirect_uris": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "grant_types": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "response_types": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "token_endpoint_auth_method": {
                      "const": "none"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "invalid_redirect_uri or invalid_client_metadata",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    },
                    "error_description": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/.well-known/oauth-protected-resource/mcp": {
      "get": {
        "summary": "Protected resource metadata of /mcp (RFC 9728): which authorization server issues its tokens",
        "servers": [
          {
            "url": "https://mcp.hystore.com.br"
          }
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "resource": {
                      "type": "string"
                    },
                    "authorization_servers": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "scopes_supported": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "bearer_methods_supported": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "resource_documentation": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/.well-known/oauth-protected-resource": {
      "get": {
        "summary": "The same metadata at the root path (for clients that look there)",
        "servers": [
          {
            "url": "https://mcp.hystore.com.br"
          }
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "resource": {
                      "type": "string"
                    },
                    "authorization_servers": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "scopes_supported": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "bearer_methods_supported": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "resource_documentation": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/.well-known/oauth-authorization-server": {
      "get": {
        "summary": "Authorization server metadata (RFC 8414): the login page in the dashboard, the token and registration endpoints, PKCE S256",
        "servers": [
          {
            "url": "https://mcp.hystore.com.br"
          }
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "issuer": {
                      "type": "string"
                    },
                    "authorization_endpoint": {
                      "type": "string"
                    },
                    "token_endpoint": {
                      "type": "string"
                    },
                    "registration_endpoint": {
                      "type": "string"
                    },
                    "revocation_endpoint": {
                      "type": "string"
                    },
                    "code_challenge_methods_supported": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "scopes_supported": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/mcp": {
      "post": {
        "summary": "MCP (Streamable HTTP, protocol 2025-11-25, also 2025-06-18 and 2025-03-26): one JSON-RPC message per request, one JSON answer. Methods: initialize, ping, tools/list, tools/call. Tools only for the theme (read_theme_guide, get_store, list_theme_files, read_theme_file, write_theme_files, check_theme, get_preview_link, request_publish, list_versions, read_version_file, restore_version, list_assets, upload_asset, delete_asset, read_catalog)",
        "servers": [
          {
            "url": "https://mcp.hystore.com.br"
          }
        ],
        "security": [
          {
            "aiApp": [
              "theme:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "MCP-Protocol-Version",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "After initialize. An unknown version is refused (400)"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "jsonrpc"
                ],
                "properties": {
                  "jsonrpc": {
                    "const": "2.0"
                  },
                  "id": {
                    "type": [
                      "string",
                      "number"
                    ]
                  },
                  "method": {
                    "type": "string"
                  },
                  "params": {
                    "type": "object"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JSON-RPC answer",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "202": {
            "description": "Notification accepted (no body)"
          },
          "400": {
            "description": "Not a JSON-RPC message, or unknown MCP-Protocol-Version"
          },
          "401": {
            "description": "No token or not an AI app token. WWW-Authenticate: Bearer resource_metadata=\"https://mcp.hystore.com.br/.well-known/oauth-protected-resource/mcp\""
          },
          "403": {
            "$ref": "#/components/responses/Error",
            "description": "Request from a web page (Origin), or the plan of the store does not include AI apps (AI_CONNECT_UNAVAILABLE) or the code theme (CODE_THEME_UNAVAILABLE)"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "get": {
        "summary": "No server stream: 405",
        "servers": [
          {
            "url": "https://mcp.hystore.com.br"
          }
        ],
        "security": [],
        "responses": {
          "405": {
            "description": "Use POST"
          }
        }
      },
      "delete": {
        "summary": "No sessions to end: 405",
        "servers": [
          {
            "url": "https://mcp.hystore.com.br"
          }
        ],
        "security": [],
        "responses": {
          "405": {
            "description": "Use POST"
          }
        }
      }
    },
    "/a/{store}/{version}/{app}/{file}": {
      "get": {
        "summary": "A file of an isolated app in the store's live version (content domain). Opened inside the store's sandboxed frame; opened on its own it keeps the same sandbox",
        "servers": [
          {
            "url": "https://hystoreapps.cloud"
          }
        ],
        "security": [],
        "parameters": [
          {
            "name": "store",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "version",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "app",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$"
            }
          },
          {
            "name": "file",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z0-9][a-z0-9_-]{0,59}\\.(html|js|css|json)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The file, with a sandbox Content-Security-Policy (scripts only, no network, no storage, no forms, no popups, no navigation)",
            "content": {
              "text/html": {},
              "text/javascript": {},
              "text/css": {},
              "application/json": {}
            }
          },
          "404": {
            "description": "No such file, the version is not the live one, or the store does not draw the code theme"
          },
          "429": {
            "description": "Too many requests from this address"
          }
        }
      }
    },
    "/d/{token}/{app}/{file}": {
      "get": {
        "summary": "A file of an isolated app in the draft, by a preview link (hys_pv_), while it lasts",
        "servers": [
          {
            "url": "https://hystoreapps.cloud"
          }
        ],
        "security": [],
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^hys_pv_[0-9A-Za-z]{43}$"
            }
          },
          {
            "name": "app",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "file",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The file, with a sandbox Content-Security-Policy (scripts only, no network, no storage, no forms, no popups, no navigation)",
            "content": {
              "text/html": {},
              "text/javascript": {},
              "text/css": {},
              "application/json": {}
            }
          },
          "404": {
            "description": "No such file, the version is not the live one, or the store does not draw the code theme"
          },
          "429": {
            "description": "Too many requests from this address"
          }
        }
      }
    },
    "/sdk/v1.js": {
      "get": {
        "summary": "The bridge script of the apps (window.hystore): products, categories, addToCart, navigate, open, context, customer, resize, autosize",
        "servers": [
          {
            "url": "https://hystoreapps.cloud"
          }
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "JavaScript",
            "content": {
              "text/javascript": {}
            }
          }
        }
      }
    }
  }
}