{"openapi":"3.1.0","info":{"title":"Sourabh Pradhan Portfolio API","version":"1.0.0","summary":"Public contact API and machine-readable resources for Sourabh Pradhan's portfolio.","description":"The Sourabh Pradhan Portfolio API exposes a single public endpoint for sending a contact message to the site owner, plus machine-readable resources (llms.txt, sitemap.xml, markdown mirrors) for agents.\n\nAuthentication: none (public). Rate limiting: 5 requests per minute per IP on POST /api/contact.\n\nEvery page of this site also supports markdown content negotiation: send `Accept: text/markdown` to receive the page as text/markdown instead of HTML.","contact":{"name":"Sourabh Pradhan","email":"sourabh.p2030i@iimbg.ac.in","url":"https://sourabh08.vercel.app"}},"servers":[{"url":"https://sourabh08.vercel.app","description":"Production"}],"tags":[{"name":"contact","description":"Send a message to the site owner."}],"externalDocs":{"description":"Developer portal","url":"https://sourabh08.vercel.app/developers"},"paths":{"/api/contact":{"post":{"tags":[{"name":"contact"}],"operationId":"submitContactMessage","summary":"Send a contact message to Sourabh Pradhan.","description":"Relays a short message to the site owner by email. No authentication required. Limited to 5 requests per minute per IP address; exceeding the limit returns 429 with code 'rate_limited'. Control characters are stripped from name and message before delivery.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactRequest"},"examples":{"valid":{"summary":"A valid message","value":{"name":"Ada Lovelace","email":"ada@example.com","message":"Hello — I enjoyed your stochastic calculus notes."}},"missingFields":{"summary":"Missing fields (triggers 400)","value":{"name":"Ada Lovelace"}}}}}},"responses":{"200":{"description":"Message accepted and queued for email delivery.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactSuccess"}}}},"400":{"description":"Validation failure. Use the `code` field to branch; `hint` explains how to fix the request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"invalidJson":{"value":{"error":"Invalid request","code":"invalid_json","hint":"Body must be valid JSON with Content-Type: application/json."}},"missingFields":{"value":{"error":"Missing fields","code":"missing_fields","hint":"Include non-empty 'name', 'email', and 'message' string fields."}},"invalidEmail":{"value":{"error":"Invalid email","code":"invalid_email","hint":"Provide a valid email address (max 254 characters)."}}}}}},"405":{"description":"Method not allowed. Only POST is supported on this path.","headers":{"Allow":{"description":"Allowed methods for this path.","schema":{"type":"string","example":"POST"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Method not allowed","code":"method_not_allowed","hint":"Use POST with a JSON body: {name, email, message}. See POST /api/contact."}}}},"429":{"description":"Rate limit exceeded (5 requests per minute per IP). Retry after 60 seconds.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Too many requests","code":"rate_limited","hint":"Wait 60 seconds before sending another message."}}}},"500":{"description":"Email delivery failed unexpectedly. Safe to retry once.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Failed to send message","code":"delivery_failed","hint":"Retry once; if it persists, email sourabh.p2030i@iimbg.ac.in directly."}}}},"503":{"description":"Email service not configured (temporary server-side condition).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Service unavailable","code":"service_unavailable","hint":"Try again later or email sourabh.p2030i@iimbg.ac.in directly."}}}}}},"parameters":[]}},"components":{"schemas":{"ContactRequest":{"type":"object","additionalProperties":false,"required":["name","email","message"],"properties":{"name":{"type":"string","maxLength":200,"minLength":1,"description":"Sender's name. Newlines and control characters are stripped.","examples":["Ada Lovelace"]},"email":{"type":"string","format":"email","maxLength":254,"minLength":1,"description":"Reply-to email address for the sender.","examples":["ada@example.com"]},"message":{"type":"string","maxLength":5000,"minLength":1,"description":"Message body. Newlines and control characters are stripped.","examples":["Hello — I enjoyed your stochastic calculus notes."]}}},"ContactSuccess":{"type":"object","additionalProperties":false,"required":["success"],"properties":{"success":{"type":"boolean","const":true,"description":"Always true on successful acceptance."}}},"Error":{"type":"object","additionalProperties":false,"required":["error","code","hint"],"properties":{"error":{"type":"string","description":"Short human-readable summary of what went wrong."},"code":{"type":"string","description":"Stable machine-readable error identifier, e.g. 'invalid_json', 'missing_fields', 'invalid_name', 'invalid_email', 'invalid_message', 'method_not_allowed', 'not_found', 'rate_limited', 'delivery_failed', 'service_unavailable'."},"hint":{"type":"string","description":"Actionable guidance for fixing or retrying the request."}}}}}}