{
  "openapi": "3.1.0",
  "jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
  "info": {
    "title": "Ahner Industrial public agent API",
    "version": "1.0.0",
    "description": "Discover Ahner Industrial's published fabrication services and submit a customer-authorized request for human quote review. A submission is not an acceptance, price, production commitment, or order.",
    "contact": {
      "name": "Ahner Industrial",
      "email": "office@ahner-industrial.com",
      "url": "https://www.ahner-industrial.com/contact"
    }
  },
  "servers": [{ "url": "https://www.ahner-industrial.com" }],
  "paths": {
    "/upload-encryption-key.json": {
      "get": {
        "operationId": "getUploadEncryptionKey",
        "summary": "Get Ahner's current public key for browser-encrypted attachments",
        "responses": { "200": { "description": "Current RSA-OAEP public-key descriptor" } }
      }
    },
    "/upload-encryption-spec.json": {
      "get": {
        "operationId": "getUploadEncryptionSpecification",
        "summary": "Get the encrypted attachment envelope specification",
        "responses": { "200": { "description": "Versioned binary envelope specification" } }
      }
    },
    "/services.json": {
      "get": {
        "operationId": "getFabricationServices",
        "summary": "Get the authoritative public service and quote-path catalog",
        "responses": {
          "200": {
            "description": "Current public fabrication service catalog",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/ServiceCatalog" } }
            }
          }
        }
      }
    },
    "/api/submissions": {
      "post": {
        "operationId": "submitCustomQuoteRequest",
        "summary": "Submit a customer-authorized custom fabrication quote request for human review",
        "description": "Call only after the customer explicitly confirms the contact information, project details, and files being sent. Use type=quote and authorizedByCustomer=true. Generate a 256-bit lowercase hexadecimal requestToken and reuse it when retrying the same request. The request does not create an order or promise price, feasibility, capacity, lead time, material availability, or delivery.",
        "x-agent-policy": {
          "customerAuthorizationRequired": true,
          "humanReviewRequired": true,
          "idempotentRetrySupported": true,
          "idempotencyField": "requestToken"
        },
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": ["type", "requestToken", "authorizedByCustomer", "details"],
                "properties": {
                  "type": { "type": "string", "const": "quote" },
                  "requestToken": {
                    "type": "string",
                    "pattern": "^[a-f0-9]{64}$",
                    "description": "A caller-generated 256-bit idempotency token. Reuse it when retrying the same request."
                  },
                  "authorizedByCustomer": {
                    "type": "string",
                    "const": "true",
                    "description": "Confirms that the customer explicitly approved the contact information, project details, and files being submitted."
                  },
                  "firstName": { "type": "string", "maxLength": 120 },
                  "lastName": { "type": "string", "maxLength": 120 },
                  "company": { "type": "string", "maxLength": 200 },
                  "email": { "type": "string", "format": "email", "maxLength": 180 },
                  "phone": { "type": "string", "maxLength": 60 },
                  "projectType": {
                    "type": "string",
                    "enum": ["Laser cutting", "Forming", "Welding", "Robotic welding", "Heavy fabrication", "Short-run fabrication", "Replacement or obsolete part", "Custom cart or rack", "Tube or structural fabrication", "Assembly or finishing", "Overflow or subcontract support", "Contract manufacturing", "Other"]
                  },
                  "projectStage": {
                    "type": "string",
                    "enum": ["Production-ready CAD", "Drawing needs review", "Photo or sketch", "Sample or existing part", "Problem needs definition"]
                  },
                  "quantity": { "type": "string", "maxLength": 120 },
                  "timing": { "type": "string", "maxLength": 200 },
                  "source": { "type": "string", "maxLength": 200 },
                  "utm_source": { "type": "string", "maxLength": 300 },
                  "utm_medium": { "type": "string", "maxLength": 300 },
                  "utm_campaign": { "type": "string", "maxLength": 300 },
                  "utm_term": { "type": "string", "maxLength": 300 },
                  "utm_content": { "type": "string", "maxLength": 300 },
                  "gclid": { "type": "string", "maxLength": 500 },
                  "msclkid": { "type": "string", "maxLength": 500 },
                  "details": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 12000,
                    "description": "Include material, quantity, dimensions, tolerances, finish, timing, delivery location, and other known requirements."
                  },
                  "attachment": {
                    "type": "array",
                    "maxItems": 8,
                    "items": { "type": "string", "format": "binary" },
                    "description": "Optional Ahner encrypted-upload envelopes using the legacy .ahner-e2ee extension and application/vnd.ahner.e2ee content type. Attachments are encrypted before upload, remain encrypted at rest, and can be decrypted in memory by Ahner's authorized service for protected staff downloads. Original files may be PDF, DXF, DWG, STEP, STP, JPG, JPEG, PNG, ZIP, DOC, or DOCX; each original file must be 25 MB or smaller and all originals must total 100 MB or less. Fetch the current key and format specification before encrypting."
                  },
                  "attachmentsEncrypted": {
                    "type": "string",
                    "const": "true",
                    "description": "Required whenever attachment is present. Confirms that every attachment is an Ahner encrypted-upload envelope."
                  },
                  "uploadEncryptionKeyId": {
                    "type": "string",
                    "description": "The exact keyId from /upload-encryption-key.json used to encrypt the attachments."
                  }
                },
                "anyOf": [
                  { "required": ["email"] },
                  { "required": ["phone"] }
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Request stored for human review",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": ["ok", "reference", "deduplicated"],
                  "properties": {
                    "ok": { "type": "boolean", "const": true },
                    "reference": { "type": "string", "description": "Reference to retain for follow-up with Ahner Industrial." },
                    "deduplicated": { "type": "boolean", "const": false }
                  }
                }
              }
            }
          },
          "200": {
            "description": "The requestToken was already used; the original request reference is returned without creating a duplicate.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": ["ok", "reference", "deduplicated"],
                  "properties": {
                    "ok": { "type": "boolean", "const": true },
                    "reference": { "type": "string" },
                    "deduplicated": { "type": "boolean", "const": true }
                  }
                }
              }
            }
          },
          "400": { "description": "Unknown submission type, missing required contact/project information, invalid requestToken, or missing customer authorization" },
          "413": { "description": "An original attachment exceeds 25 MB or all original attachments exceed 100 MB" },
          "429": { "description": "Rate limit exceeded" },
          "500": { "description": "The request could not be stored" }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "ServiceCatalog": {
        "type": "object",
        "required": ["schemaVersion", "authority", "provider", "services", "quotePaths", "agentPolicy"],
        "properties": {
          "schemaVersion": { "type": "string" },
          "authority": { "type": "string", "format": "uri" },
          "provider": { "type": "object" },
          "services": { "type": "array", "items": { "type": "object" } },
          "quotePaths": { "type": "object" },
          "agentPolicy": { "type": "object" }
        }
      }
    }
  }
}
