{"openapi":"3.0.3","info":{"title":"TDS Lead Submission API","version":"1.0.0","description":"Public AI-ready APIs for submitting TDS contact and quote enquiries. Agents must have user consent before sending personal data."},"servers":[{"url":"https://www.tdsltd.ie"}],"paths":{"/api/internal-doors/estimate":{"post":{"operationId":"estimateInternalDoorPrice","summary":"Estimate OC Slimline internal door price without submitting personal data","description":"Returns deterministic indicative supply-only pricing, lead time, and validation status for internal steel glazed door configurations. Use before asking for customer contact details.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalDoorEstimateRequest"}}}},"responses":{"200":{"description":"Estimate calculated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalDoorEstimateResponse"}}}},"400":{"description":"Invalid request"},"415":{"description":"Content-Type must be application/json"},"429":{"description":"Rate limit exceeded"}}}},"/api/internal-doors/recommend":{"post":{"operationId":"recommendInternalDoorConfiguration","summary":"Compare feasible OC Slimline configurations for the same opening","description":"Returns deterministic configuration alternatives, estimated prices, savings and practical tradeoffs without submitting personal data. Use when the user is comparing possible layouts for the same wall opening.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalDoorRecommendRequest"}}}},"responses":{"200":{"description":"Recommendations calculated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalDoorRecommendResponse"}}}},"400":{"description":"Invalid request"},"415":{"description":"Content-Type must be application/json"},"429":{"description":"Rate limit exceeded"}}}},"/api/contact":{"post":{"operationId":"submitContactEnquiry","summary":"Submit a general contact enquiry","description":"Creates a contact request for TDS. Use when the user wants TDS to contact them but the enquiry is not specific to internal glazed doors or security doors.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactRequest"}}}},"responses":{"200":{"description":"Enquiry accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubmissionResponse"}}}},"400":{"description":"Invalid request"},"429":{"description":"Rate limit exceeded"}}}},"/api/quote/internal-doors":{"post":{"operationId":"submitInternalDoorsQuote","summary":"Submit an OC Slimline internal glazed doors quote request","description":"Creates a quote request for internal steel glazed doors. Agents can provide text requirements and optional attachment/reference URLs when available.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteRequest"}}}},"responses":{"200":{"description":"Quote request accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubmissionResponse"}}}},"400":{"description":"Invalid request"},"429":{"description":"Rate limit exceeded"}}}},"/api/quote/security-doors":{"post":{"operationId":"submitSecurityDoorsQuote","summary":"Submit a security doors quote request","description":"Creates a quote request for high-security, RC-rated, fire-rated, bullet-resistant, blast-resistant or specialist security doors.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteRequest"}}}},"responses":{"200":{"description":"Quote request accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubmissionResponse"}}}},"400":{"description":"Invalid request"},"429":{"description":"Rate limit exceeded"}}}}},"components":{"schemas":{"Customer":{"type":"object","required":["name","email"],"properties":{"name":{"type":"string","minLength":3},"email":{"type":"string","format":"email"},"phone":{"type":"string"},"company":{"type":"string"}}},"Attachment":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"type":{"type":"string","example":"architectural_plan_photo"},"description":{"type":"string","maxLength":400},"expiresAt":{"type":"string","description":"Optional date/time when the external file link expires."}}},"Door":{"type":"object","properties":{"doorType":{"type":"string","example":"Single Door"},"opWidth":{"type":"string","example":"1200"},"opHeight":{"type":"string","example":"2100"},"bifoldConfig":{"type":"string","enum":["2L","3L","4L"],"example":"3L"}}},"InternalDoorEstimateDoor":{"type":"object","properties":{"preset":{"type":"string","example":"single-door"},"doorType":{"type":"string","example":"Single"},"doorTypeKey":{"type":"string","enum":["SINGLE_HINGED","DOUBLE_HINGED","DOUBLE_HINGED_ACTIVE_PASSIVE","SLIDING","DOUBLE_SLIDING","PIVOT","FIX_PANEL","BIFOLD"],"example":"SINGLE_HINGED"},"opWidth":{"type":"string","example":"900","description":"Wall opening width in mm."},"opHeight":{"type":"string","example":"2100","description":"Wall opening height in mm."},"doorLeafWidth":{"type":"string","example":"900","description":"Required when side panels or active/passive leaves are used."},"doorHeightMm":{"type":"string","example":"2100","description":"Required when a transom is used."},"leftPanels":{"type":"string","example":"0"},"rightPanels":{"type":"string","example":"0"},"topPanel":{"type":"string","example":"0"},"bifoldConfig":{"type":"string","enum":["2L","3L","4L"],"example":"3L","description":"Required for bi-fold doors."}}},"InternalDoorEstimateRequest":{"type":"object","required":["doors"],"properties":{"doors":{"type":"array","items":{"$ref":"#/components/schemas/InternalDoorEstimateDoor"},"minItems":1,"maxItems":20}}},"InternalDoorEstimateResponse":{"type":"object","properties":{"priceEstimate":{"type":"number","example":1652},"leadTimeWeeks":{"type":"number","example":10},"currency":{"type":"string","example":"EUR"},"doorsCount":{"type":"number","example":1},"valid":{"type":"boolean","example":true},"validationIssue":{"type":"object","nullable":true},"recovery":{"type":"object","nullable":true,"description":"Procedural recovery guidance when dimensions are outside the selected door type limits.","properties":{"kind":{"type":"string","example":"width"},"introText":{"type":"string"},"optionsIntroText":{"type":"string"},"panelRequiredOnly":{"type":"boolean"},"transomRequiredOnly":{"type":"boolean"},"suggestions":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","example":"add-side-panel"},"label":{"type":"string","example":"Add fixed side panel"},"message":{"type":"string"},"doorTypeKey":{"type":"string"},"doorLeafWidth":{"type":"string"},"panelWidth":{"type":"string"}}}}}},"doors":{"type":"array","items":{"allOf":[{"$ref":"#/components/schemas/InternalDoorEstimateDoor"},{"type":"object","properties":{"estimatedPrice":{"type":"number","example":1652},"valid":{"type":"boolean","example":true},"validationMessage":{"type":"string","nullable":true}}}]}}}},"InternalDoorRecommendRequest":{"type":"object","required":["opening","selectedDoor"],"properties":{"opening":{"type":"object","required":["widthMm","heightMm"],"properties":{"widthMm":{"type":"number","example":1250},"heightMm":{"type":"number","example":2100}}},"selectedDoor":{"$ref":"#/components/schemas/InternalDoorEstimateDoor"},"preferences":{"type":"object","properties":{"needsFullWidthAccess":{"type":"boolean","example":false},"budgetSensitive":{"type":"boolean","example":true}}}}},"InternalDoorRecommendationOption":{"type":"object","properties":{"id":{"type":"string","example":"single-with-fix-panel"},"label":{"type":"string","example":"Single Door + fixed side panel"},"selected":{"type":"boolean","example":false},"valid":{"type":"boolean","example":true},"door":{"$ref":"#/components/schemas/InternalDoorEstimateDoor"},"estimatedPrice":{"type":"number","example":2294},"chargeableAreaM2":{"type":"number","example":2.63},"savingsComparedToSelected":{"type":"number","example":328},"savingsPercentComparedToSelected":{"type":"number","example":13},"pros":{"type":"array","items":{"type":"string"}},"tradeoffs":{"type":"array","items":{"type":"string"}},"validationMessage":{"type":"string","nullable":true}}},"InternalDoorRecommendResponse":{"type":"object","properties":{"opening":{"type":"object","properties":{"widthMm":{"type":"number","example":1250},"heightMm":{"type":"number","example":2100}}},"selectedOptionId":{"type":"string","example":"selected:DOUBLE_HINGED"},"recommendedOptionId":{"type":"string","nullable":true,"example":"single-with-fix-panel"},"reason":{"type":"string","example":"Single Door + fixed side panel is estimated 13% cheaper than the selected configuration while fitting the same opening."},"preferences":{"type":"object"},"options":{"type":"array","items":{"$ref":"#/components/schemas/InternalDoorRecommendationOption"}}}},"QuoteRequest":{"type":"object","required":["customer"],"properties":{"source":{"type":"string","example":"chatgpt"},"sourceId":{"type":"string"},"customer":{"$ref":"#/components/schemas/Customer"},"project":{"type":"object","properties":{"message":{"type":"string","maxLength":2500,"description":"Natural-language project requirements."},"fromPage":{"type":"string","format":"uri"}}},"product":{"type":"string"},"comments":{"type":"string","maxLength":2500},"doors":{"type":"array","items":{"$ref":"#/components/schemas/Door"},"maxItems":20},"supplyAndInstall":{"type":"boolean"},"eirCode":{"type":"string"},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/Attachment"},"maxItems":10}}},"ContactRequest":{"type":"object","required":["customer","message"],"properties":{"source":{"type":"string","example":"chatgpt"},"sourceId":{"type":"string"},"customer":{"$ref":"#/components/schemas/Customer"},"message":{"type":"string","minLength":5,"maxLength":1500}}},"SubmissionResponse":{"type":"object","properties":{"success":{"type":"boolean"},"id":{"type":"string"},"collection":{"type":"string"},"message":{"type":"string"}}}}}}