{
  "openapi": "3.1.0",
  "info": {
    "title": "Submitbox API",
    "version": "1.0.0",
    "description": "Backend-less form submission service. Public submit endpoint plus an authenticated dashboard API. A remote MCP server is also available at /mcp.",
    "contact": { "name": "Submitbox", "url": "https://submitbox.dev" }
  },
  "servers": [{ "url": "/", "description": "Same-origin" }],
  "tags": [
    { "name": "Submit", "description": "Public form submission" },
    { "name": "Auth", "description": "Account auth + tokens" },
    { "name": "Forms", "description": "Manage forms (access keys)" },
    { "name": "Submissions", "description": "Read submissions" },
    { "name": "Billing", "description": "Plans and Stripe billing" }
  ],
  "paths": {
    "/submit": {
      "post": {
        "tags": ["Submit"],
        "summary": "Submit a form",
        "description": "Accepts application/json, application/x-www-form-urlencoded, or multipart/form-data (for file uploads). Include access_key plus arbitrary fields. Returns JSON when Accept: application/json, otherwise redirects.",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["access_key"],
                "properties": {
                  "access_key": { "type": "string", "description": "The form's access key." },
                  "email": { "type": "string" },
                  "message": { "type": "string" },
                  "redirect": { "type": "string", "description": "Optional override redirect URL." },
                  "botcheck": { "type": "string", "description": "Honeypot — leave empty." }
                },
                "additionalProperties": true
              }
            },
            "multipart/form-data": { "schema": { "type": "object", "additionalProperties": true } },
            "application/x-www-form-urlencoded": { "schema": { "type": "object", "additionalProperties": true } }
          }
        },
        "responses": {
          "200": { "description": "Accepted (JSON mode)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SubmitResult" } } } },
          "303": { "description": "Redirect to thank-you page (non-AJAX mode)" },
          "400": { "description": "Bad request / failed CAPTCHA" },
          "403": { "description": "Origin not in the form's domain allowlist" },
          "404": { "description": "Invalid or inactive access key" },
          "429": { "description": "Rate limited or monthly quota reached" }
        }
      }
    },
    "/s/{accessKey}": {
      "post": {
        "tags": ["Submit"],
        "summary": "Submit a form (key in path)",
        "security": [],
        "parameters": [{ "name": "accessKey", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": { "200": { "description": "Accepted" } }
      }
    },
    "/api/auth/register": {
      "post": {
        "tags": ["Auth"], "summary": "Create an account", "security": [],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Credentials" } } } },
        "responses": { "200": { "description": "Token + user", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AuthResult" } } } }, "409": { "description": "Email already exists" } }
      }
    },
    "/api/auth/login": {
      "post": {
        "tags": ["Auth"], "summary": "Sign in", "security": [],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Credentials" } } } },
        "responses": { "200": { "description": "Token + user", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AuthResult" } } } }, "401": { "description": "Invalid credentials" } }
      }
    },
    "/api/auth/me": {
      "get": { "tags": ["Auth"], "summary": "Current user", "responses": { "200": { "description": "User" } } }
    },
    "/api/auth/mcp-token": {
      "post": {
        "tags": ["Auth"],
        "summary": "Mint a long-lived MCP/automation token",
        "description": "Returns a 1-year bearer token for use with the MCP server or API automation.",
        "responses": { "200": { "description": "Token", "content": { "application/json": { "schema": { "type": "object", "properties": { "token": { "type": "string" }, "expiresInDays": { "type": "integer" } } } } } } }
      }
    },
    "/api/forms": {
      "get": { "tags": ["Forms"], "summary": "List forms", "responses": { "200": { "description": "Forms" } } },
      "post": {
        "tags": ["Forms"], "summary": "Create a form",
        "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "name": { "type": "string" }, "toEmails": { "type": "array", "items": { "type": "string" } } } } } } },
        "responses": { "200": { "description": "Created form with access key" } }
      }
    },
    "/api/forms/{accessKey}": {
      "get": { "tags": ["Forms"], "summary": "Get a form", "parameters": [{ "name": "accessKey", "in": "path", "required": true, "schema": { "type": "string" } }], "responses": { "200": { "description": "Form" } } },
      "patch": { "tags": ["Forms"], "summary": "Update form settings", "parameters": [{ "name": "accessKey", "in": "path", "required": true, "schema": { "type": "string" } }], "responses": { "200": { "description": "Updated form" } } },
      "delete": { "tags": ["Forms"], "summary": "Delete a form", "parameters": [{ "name": "accessKey", "in": "path", "required": true, "schema": { "type": "string" } }], "responses": { "200": { "description": "Deleted" } } }
    },
    "/api/forms/{accessKey}/submissions": {
      "get": {
        "tags": ["Submissions"], "summary": "List submissions",
        "parameters": [
          { "name": "accessKey", "in": "path", "required": true, "schema": { "type": "string" } },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 50 } },
          { "name": "cursor", "in": "query", "schema": { "type": "string" } }
        ],
        "responses": { "200": { "description": "Submissions page" } }
      }
    },
    "/api/forms/{accessKey}/submissions/{id}": {
      "get": { "tags": ["Submissions"], "summary": "Get a submission", "parameters": [{ "name": "accessKey", "in": "path", "required": true, "schema": { "type": "string" } }, { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }], "responses": { "200": { "description": "Submission" } } },
      "delete": { "tags": ["Submissions"], "summary": "Delete a submission", "parameters": [{ "name": "accessKey", "in": "path", "required": true, "schema": { "type": "string" } }, { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }], "responses": { "200": { "description": "Deleted" } } }
    },
    "/api/forms/{accessKey}/export": {
      "get": { "tags": ["Submissions"], "summary": "Export submissions as CSV", "parameters": [{ "name": "accessKey", "in": "path", "required": true, "schema": { "type": "string" } }], "responses": { "200": { "description": "CSV", "content": { "text/csv": {} } } } }
    },
    "/api/stats": { "get": { "tags": ["Forms"], "summary": "Account overview stats", "responses": { "200": { "description": "Stats" } } } },
    "/api/billing": { "get": { "tags": ["Billing"], "summary": "Plan + usage + plan catalogue", "responses": { "200": { "description": "Billing state" } } } },
    "/api/billing/checkout": { "post": { "tags": ["Billing"], "summary": "Start Stripe Checkout", "responses": { "200": { "description": "Checkout URL" } } } },
    "/api/billing/portal": { "post": { "tags": ["Billing"], "summary": "Open Stripe customer portal", "responses": { "200": { "description": "Portal URL" } } } },
    "/mcp": {
      "post": {
        "tags": ["Auth"],
        "summary": "MCP server (JSON-RPC 2.0)",
        "description": "Model Context Protocol endpoint over Streamable HTTP. Methods: initialize, tools/list, tools/call, ping. Bearer auth required.",
        "responses": { "200": { "description": "JSON-RPC response" }, "401": { "description": "Authentication required" } }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": { "type": "http", "scheme": "bearer", "bearerFormat": "JWT" }
    },
    "schemas": {
      "Credentials": { "type": "object", "required": ["email", "password"], "properties": { "email": { "type": "string" }, "password": { "type": "string", "minLength": 8 }, "name": { "type": "string" } } },
      "AuthResult": { "type": "object", "properties": { "success": { "type": "boolean" }, "token": { "type": "string" }, "user": { "type": "object" } } },
      "SubmitResult": { "type": "object", "properties": { "success": { "type": "boolean" }, "message": { "type": "string" }, "id": { "type": "string" } } }
    }
  },
  "security": [{ "bearerAuth": [] }]
}
