{"openapi":"3.1.0","info":{"title":"hmu.support intake","version":"1.2.0","description":"Public support lookup and ticket intake. Lookup is read-only. Ticket submissions require a matching order email and number and may send confirmation email. Submissions are not idempotent; do not automatically retry ambiguous failures."},"servers":[{"url":"https://hmu-support.vercel.app"}],"paths":{"/api/resolve":{"post":{"operationId":"findSupportForOrder","summary":"Find the support team from email and order number","description":"Read-only lookup across connected desks. Does not create tickets or send email. If status is needs_domain, ask the customer which website they ordered from and repeat with domain. matchedBy=domain identifies only the store; it does not verify the order. An ambiguous or incomplete search must not be treated as an exact order match.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["customerEmail","orderName"],"properties":{"customerEmail":{"type":"string","format":"email","maxLength":320},"orderName":{"type":"string","minLength":1,"maxLength":64},"domain":{"type":"string","minLength":1,"maxLength":2048,"description":"Store domain or order-confirmation URL; provide only when needed."}}}}}},"responses":{"200":{"description":"Support team identified, or store domain needed","content":{"application/json":{"schema":{"oneOf":[{"type":"object","required":["status","matchedBy","brand"],"properties":{"status":{"const":"matched"},"matchedBy":{"enum":["order","domain"]},"brand":{"type":"object","required":["slug","name"],"properties":{"slug":{"type":"string"},"name":{"type":"string"},"supportEmail":{"type":"string","format":"email"}}}}},{"type":"object","required":["status","reason","message"],"properties":{"status":{"const":"needs_domain"},"reason":{"enum":["not_found","ambiguous","unavailable","unknown_domain"]},"message":{"type":"string"}}}]}}}},"400":{"description":"Invalid email, order number, or domain"},"413":{"description":"Body exceeds 8192 bytes"},"415":{"description":"JSON body required"},"429":{"description":"Too many attempts; response may be non-JSON"},"503":{"description":"Support lookup unavailable"}}}},"/api/brands":{"get":{"operationId":"listBrands","summary":"List connected support brands","responses":{"200":{"description":"Public brand slugs and names","content":{"application/json":{"schema":{"type":"object","required":["brands"],"properties":{"brands":{"type":"array","items":{"type":"object","required":["slug","name"],"properties":{"slug":{"type":"string"},"name":{"type":"string"},"supportEmail":{"type":"string","format":"email","description":"Brand main support mailbox, when available"}}}}}}}}}}}},"/api/tickets":{"post":{"operationId":"createSupportTicket","summary":"Submit a customer support message","description":"Obtain the customer's permission before submitting. This saves a message and may send email. Include brand explicitly. Do not automatically retry: the operation is not idempotent.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"brand":{"type":"string","maxLength":64,"pattern":"^[a-z0-9]+(?:-[a-z0-9]+)*$"},"customerEmail":{"type":"string","maxLength":320,"format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"orderName":{"type":"string","minLength":1,"maxLength":64},"message":{"type":"string","minLength":1,"maxLength":10000},"subject":{"type":"string","minLength":1,"maxLength":200}},"required":["brand","customerEmail","orderName","message"],"additionalProperties":false}}}},"responses":{"200":{"description":"Message saved to an existing conversation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ticket"}}}},"201":{"description":"New conversation opened","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ticket"}}}},"400":{"description":"Invalid input or brand required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown brand or order not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Body exceeds 48000 bytes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"JSON content type required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream failure; ticket may have been saved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Connection not configured or unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"schemas":{"Ticket":{"type":"object","required":["ok","brand","ticketRef","orderName","confirmationSent"],"properties":{"ok":{"const":true},"brand":{"type":"string"},"ticketRef":{"type":"string"},"orderName":{"type":"string"},"confirmationSent":{"type":"boolean"},"ticketEmail":{"type":"string","format":"email","description":"Private reply address for this ticket, supplied by the brand desk"},"supportEmail":{"type":"string","format":"email","description":"Main support mailbox for the brand"},"created":{"type":"boolean"}}},"Error":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"},"fields":{"type":"array","items":{"type":"string"}}}}}}}