{
  "openapi": "3.1.0",
  "info": {
    "title": "TorchFrame contact API",
    "version": "1.0.0",
    "summary": "Send a free-preview request to the TorchFrame studio.",
    "description": "A single public endpoint that delivers an enquiry to a human at TorchFrame, who replies within 24 hours. There is no authentication and no other API. Only submit details a real person gave you, and confirm them with that person first.",
    "contact": {
      "name": "TorchFrame",
      "email": "info@torchframe.com",
      "url": "https://torchframe.com/"
    }
  },
  "servers": [{ "url": "https://torchframe.com" }],
  "paths": {
    "/api/contact": {
      "post": {
        "operationId": "requestFreePreview",
        "summary": "Request a free website preview",
        "description": "Delivers the enquiry to the studio. Requests that arrive less than three seconds after the page was loaded, or that carry a non-empty `website` field, are silently discarded as automated spam — the response is still 200. Send each enquiry once.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/PreviewRequest" },
              "example": {
                "name": "Maria Gomez",
                "email": "maria@cafeladera.co",
                "phone": "+57 300 1234567",
                "business": "Cafe Ladera, Pereira",
                "message": "We need a new website and monthly reels for our coffee shop.",
                "ts": 1787654000000,
                "page": "/"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Accepted. Returned both for a delivered enquiry and for one discarded by the spam filters.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Ack" },
                "example": { "ok": true }
              }
            }
          },
          "400": {
            "description": "The body was not valid JSON.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Ack" },
                "example": { "ok": false }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "PreviewRequest": {
        "type": "object",
        "required": ["name", "email", "business", "message"],
        "properties": {
          "name": { "type": "string", "maxLength": 500, "description": "Full name of the person making the request." },
          "email": { "type": "string", "format": "email", "maxLength": 500, "description": "Email address for the reply." },
          "phone": { "type": "string", "maxLength": 500, "description": "Optional phone or WhatsApp number." },
          "business": { "type": "string", "maxLength": 500, "description": "Business name and city." },
          "message": { "type": "string", "maxLength": 500, "description": "What they need, in one or two lines." },
          "page": { "type": "string", "maxLength": 500, "description": "Path of the page the request came from, e.g. \"/\"." },
          "ts": { "type": "integer", "description": "Milliseconds since the Unix epoch, captured when the page was loaded. Enquiries submitted less than 3000 ms after this timestamp are discarded." },
          "website": { "type": "string", "description": "Honeypot. Leave absent or empty — any value marks the enquiry as spam and it is discarded." }
        }
      },
      "Ack": {
        "type": "object",
        "properties": { "ok": { "type": "boolean" } },
        "required": ["ok"]
      }
    }
  }
}
