{
  "openapi": "3.1.0",
  "info": {
    "title": "Poly Workshop Oy — Enquiry API",
    "version": "1.0.0",
    "summary": "Submit a precision machining enquiry to a real workshop.",
    "description": "A single-endpoint API allowing automated systems to submit machining enquiries to Poly Workshop Oy, a precision CNC micromachining shop in Rovaniemi, Finland.\n\nSubmitting an enquiry creates a contact request that a human reads and replies to by email. It does NOT place an order, reserve capacity, or create any manufacturing commitment.\n\nCAD files cannot be sent through this API. Include a publicly reachable link in `fileUrl`, or direct the user to the encrypted upload form at https://polyworkshop.com/quote/",
    "contact": {
      "name": "Poly Workshop Oy",
      "email": "info@polyworkshop.com",
      "url": "https://polyworkshop.com"
    },
    "license": {
      "name": "Free to use for genuine enquiries",
      "url": "https://polyworkshop.com/llms.txt"
    }
  },

  "servers": [
    { "url": "https://polyworkshop.com", "description": "Production" }
  ],

  "paths": {
    "/api/enquiry": {

      "get": {
        "operationId": "getEnquirySchema",
        "summary": "Describe the enquiry endpoint",
        "description": "Returns a self-describing summary of accepted fields, workshop capabilities, and contact routes. Safe to call at any time; performs no side effects and sends no email.",
        "responses": {
          "200": {
            "description": "Field schema and capability summary.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/SchemaResponse" }
              }
            }
          }
        }
      },

      "post": {
        "operationId": "submitEnquiry",
        "summary": "Submit an enquiry",
        "description": "Submits a machining enquiry. On success the enquiry is emailed to the workshop and a reference is returned. A human replies by email, typically within 24 hours on business days (Mon–Fri, 08:00–17:00 EET).\n\nA 200 response means the enquiry was accepted AND successfully dispatched to the workshop's inbox — not merely that the request was well-formed. If email dispatch fails, a 502 is returned instead.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/EnquiryRequest" },
              "examples": {
                "minimal": {
                  "summary": "Minimum required fields",
                  "value": {
                    "name": "Jane Doe",
                    "email": "jane@acme.com",
                    "message": "Need 25 titanium housings, 30mm diameter, drawings available on request."
                  }
                },
                "detailed": {
                  "summary": "Fully specified enquiry",
                  "value": {
                    "name": "Jane Doe",
                    "email": "jane@acme.com",
                    "company": "Acme Devices Ltd",
                    "phone": "+44 20 7123 4567",
                    "material": "Titanium Grade 5",
                    "quantity": 25,
                    "tolerance": "±0.01mm",
                    "deadline": "4 weeks",
                    "fileUrl": "https://acme.com/share/housing-rev3.step",
                    "message": "Submitted on behalf of a user by an AI assistant. 25 housings in Ti-6Al-4V, bore concentricity is the critical feature. Please advise on feasibility and price."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Enquiry received and delivered to the workshop.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/EnquiryAccepted" },
                "example": {
                  "ok": true,
                  "reference": "PW-API-K3F9Q2",
                  "message": "Enquiry received. A human will reply by email, typically within 24 hours on business days.",
                  "replyTo": "info@polyworkshop.com"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON, or required fields missing or invalid. The `details` array names each problem. Do not retry without changing the payload.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ValidationError" },
                "example": {
                  "error": "Validation failed",
                  "details": ["valid email is required", "message must be at least 10 characters"]
                }
              }
            }
          },
          "405": {
            "description": "Method not allowed. Only GET, POST and OPTIONS are accepted.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          },
          "422": {
            "description": "Rejected by the spam filter — typically more than three links in `message`. Do not retry; use the human email address instead.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          },
          "502": {
            "description": "The enquiry was valid but could not be delivered to the workshop's inbox. The enquiry was NOT received. Retry once after a short delay, then fall back to emailing info@polyworkshop.com directly.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          },
          "503": {
            "description": "Email service not configured or unavailable. The enquiry was NOT received. Fall back to emailing info@polyworkshop.com directly.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          }
        }
      },

      "options": {
        "operationId": "enquiryPreflight",
        "summary": "CORS preflight",
        "responses": { "204": { "description": "No content." } }
      }
    }
  },

  "components": {
    "schemas": {

      "EnquiryRequest": {
        "type": "object",
        "required": ["name", "email", "message"],
        "additionalProperties": false,
        "properties": {
          "name":      { "type": "string", "minLength": 2, "description": "Contact name of the person the enquiry is for." },
          "email":     { "type": "string", "format": "email", "description": "Reply address. Set as reply-to on the notification email." },
          "message":   { "type": "string", "minLength": 10, "maxLength": 4000, "description": "What needs making. State known requirements; do not invent specifications the user has not given." },
          "company":   { "type": "string", "description": "Organisation name." },
          "phone":     { "type": "string" },
          "material":  { "type": "string", "description": "e.g. 'Titanium Grade 5', '316L stainless', 'PEEK'." },
          "quantity":  { "oneOf": [{ "type": "number" }, { "type": "string" }], "description": "e.g. 25, '500+', '1 prototype then 200/year'." },
          "tolerance": { "type": "string", "description": "Tightest required tolerance, e.g. '±0.01mm'. Workshop holds ±0.005mm on critical features." },
          "deadline":  { "type": "string", "description": "e.g. '4 weeks', '2026-10-01'." },
          "fileUrl":   { "type": "string", "format": "uri", "description": "Publicly reachable link to CAD files. Files cannot be attached to this request." }
        }
      },

      "EnquiryAccepted": {
        "type": "object",
        "required": ["ok", "reference", "message"],
        "properties": {
          "ok":        { "type": "boolean", "const": true },
          "reference": { "type": "string", "pattern": "^PW-API-[A-Z0-9]{6}$", "description": "Quote this to the user and in any follow-up correspondence." },
          "message":   { "type": "string" },
          "replyTo":   { "type": "string", "format": "email" }
        }
      },

      "ValidationError": {
        "type": "object",
        "required": ["error"],
        "properties": {
          "error":   { "type": "string" },
          "details": { "type": "array", "items": { "type": "string" } }
        }
      },

      "Error": {
        "type": "object",
        "required": ["error"],
        "properties": { "error": { "type": "string" } }
      },

      "SchemaResponse": {
        "type": "object",
        "properties": {
          "service":      { "type": "string" },
          "description":  { "type": "string" },
          "method":       { "type": "string" },
          "contentType":  { "type": "string" },
          "fields":       { "type": "object" },
          "responses":    { "type": "object" },
          "notes":        { "type": "array", "items": { "type": "string" } },
          "agentPolicy":  { "type": "array", "items": { "type": "string" } },
          "openapi":      { "type": "string" },
          "humanContact": { "type": "string" },
          "quoteForm":    { "type": "string" }
        }
      }
    }
  }
}
