{"openapi":"3.1.0","info":{"title":"nady4.com API","summary":"Public API surface of the nady4.com portfolio site, including the newsletter subscription endpoint and machine-readable site resources.","description":"nady4.com exposes a small, fully public API. No API key, OAuth token, or registration is required today: every endpoint is unauthenticated and declared with `security: []`.\n\nScoped permissions are declared in the RFC 9728 protected-resource metadata at https://www.nady4.com/.well-known/oauth-protected-resource (`scopes_supported` is currently empty — the API is public). If authenticated endpoints are added later, their OAuth scopes will be declared there and mirrored in this spec's security schemes.\n\nError responses are always JSON objects with a stable `message` code and an optional structured `error` object containing `code`, `message`, and `hint`.","version":"1.0.0","contact":{"name":"Nadya Jerochim","email":"dev@nady4.com","url":"https://www.nady4.com/contact"},"license":{"name":"CC BY-SA 4.0","url":"https://creativecommons.org/licenses/by-sa/4.0/"}},"servers":[{"url":"https://www.nady4.com","description":"Production (canonical, www)"},{"url":"https://nady4.com","description":"Production (apex, redirects to www)"}],"paths":{"/api/newsletter":{"post":{"operationId":"subscribeToNewsletter","summary":"Subscribe an email address to the newsletter","description":"Adds an email address to the nady4.com newsletter subscriber list. The endpoint is public and rate-unlimited at the edge; it requires no authentication. Returns 200 with `{ok:true}` on success. Duplicate subscriptions are idempotent (the backing store is a set).","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email"],"properties":{"email":{"type":"string","format":"email","maxLength":254,"description":"Subscriber email address, trimmed before validation.","example":"you@example.com"}}}}}},"responses":{"200":{"description":"Subscribed successfully.","content":{"application/json":{"schema":{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","const":true}}}}}},"400":{"description":"Invalid or missing email address.","content":{"application/json":{"schema":{"type":"object","required":["ok","message"],"properties":{"ok":{"type":"boolean","const":false},"message":{"type":"string","description":"Stable machine-readable error code.","example":"invalid_email"},"error":{"type":"object","properties":{"code":{"type":"string","example":"invalid_email"},"message":{"type":"string"},"hint":{"type":"string","description":"Resolution guidance for the caller."}}}}}}}},"405":{"description":"Method not allowed (only POST is supported).","content":{"application/json":{"schema":{"type":"object","required":["ok","message"],"properties":{"ok":{"type":"boolean","const":false},"message":{"type":"string","description":"Stable machine-readable error code.","example":"method_not_allowed"},"error":{"type":"object","properties":{"code":{"type":"string","example":"method_not_allowed"},"message":{"type":"string"},"hint":{"type":"string","description":"Resolution guidance for the caller."}}}}}}}},"500":{"description":"Storage backend unavailable.","content":{"application/json":{"schema":{"type":"object","required":["ok","message"],"properties":{"ok":{"type":"boolean","const":false},"message":{"type":"string","description":"Stable machine-readable error code.","example":"storage_failure"},"error":{"type":"object","properties":{"code":{"type":"string","example":"storage_failure"},"message":{"type":"string"},"hint":{"type":"string","description":"Resolution guidance for the caller."}}}}}}}}},"security":[]}},"/openapi.json":{"get":{"operationId":"getOpenApiJson","summary":"OpenAPI 3.1 specification (JSON)","description":"Returns this specification. Agents use it to discover the API surface automatically.","responses":{"200":{"description":"OpenAPI document, serialized as JSON.","content":{"application/json":{"schema":{"type":"object"}}}}},"security":[]}},"/openapi.yaml":{"get":{"operationId":"getOpenApiYaml","summary":"OpenAPI 3.1 specification (YAML)","description":"Returns this specification, serialized as YAML for tooling that prefers it.","responses":{"200":{"description":"OpenAPI document, serialized as YAML.","content":{"text/yaml":{"schema":{"type":"string"}}}}},"security":[]}},"/llms.txt":{"get":{"operationId":"getLlmstxt","summary":"Agent-facing site guide (llms.txt)","description":"Markdown guide describing when to use the site, its developer resources, and the API. Follows the llms.txt convention.","responses":{"200":{"description":"Markdown site guide.","content":{"text/markdown":{"schema":{"type":"string"}}}}},"security":[]}},"/sitemap.xml":{"get":{"operationId":"getSitemap","summary":"XML sitemap","description":"Lists all indexable URLs with lastmod dates and hreflang alternates.","responses":{"200":{"description":"Sitemap XML document.","content":{"application/xml":{"schema":{"type":"string"}}}}},"security":[]}},"/.well-known/oauth-protected-resource":{"get":{"operationId":"getProtectedResourceMetadata","summary":"RFC 9728 protected-resource metadata","description":"Machine-readable declaration of the API's scoped permissions. `scopes_supported` is currently empty because the API is fully public.","responses":{"200":{"description":"Protected-resource metadata document.","content":{"application/json":{"schema":{"type":"object"}}}}},"security":[]}}},"components":{"securitySchemes":{}},"security":[]}