{"openapi":"3.1.0","info":{"title":"sendyka.dev public website API","description":"Digital partner for NGOs and SMEs in Poland: web design, IT support, and process automation with privacy-first implementation. Public API includes newsletter, contact, MCP tools (v1.6.0), website chat assistant (Vercel AI Gateway), consultation slot lookup, NLWeb-style /ask queries (v0.2), and OAuth bearer enforcement (opt-in via OAUTH_ENFORCEMENT). OAuth metadata is published for agent discovery; write endpoints are public with rate limits when enforcement is off.","version":"1.8.0"},"servers":[{"url":"https://sendyka.dev"}],"externalDocs":{"description":"Service reliability status and planned maintenance","url":"https://sendyka.dev/status/"},"x-scopes-supported":[{"name":"newsletter:subscribe","description":"Create newsletter subscription requests on behalf of a user."},{"name":"newsletter:unsubscribe","description":"Revoke newsletter subscription for a user email."},{"name":"mcp:read","description":"Read MCP server metadata and tool list without calling tools."},{"name":"mcp:tools:inquiry","description":"Submit service inquiry using MCP tool endpoints."},{"name":"mcp:tools:booking","description":"Create consultation booking requests through MCP transport."},{"name":"ask:query","description":"Run natural-language queries via the NLWeb /ask endpoint."}],"components":{"headers":{"XRateLimitLimit":{"description":"Maximum requests allowed in the current time window.","schema":{"type":"integer"}},"XRateLimitRemaining":{"description":"Requests remaining in the current time window.","schema":{"type":"integer"}},"RetryAfter":{"description":"Seconds to wait before retrying after a rate limit response.","schema":{"type":"integer"}}},"securitySchemes":{"OAuth2":{"type":"oauth2","description":"OAuth 2.0 authorization server for scoped agent access.","flows":{"authorizationCode":{"authorizationUrl":"https://sendyka.dev/.well-known/oauth2/authorize","tokenUrl":"https://sendyka.dev/.well-known/oauth2/token","scopes":{"newsletter:subscribe":"Create newsletter subscription requests on behalf of a user.","newsletter:unsubscribe":"Revoke newsletter subscription for a user email.","mcp:read":"Read MCP metadata and resources.","mcp:tools:inquiry":"Call MCP inquiry tools.","mcp:tools:booking":"Call MCP booking tools.","ask:query":"Run natural-language queries via /ask."}},"clientCredentials":{"tokenUrl":"https://sendyka.dev/.well-known/oauth2/token","scopes":{"newsletter:subscribe":"Create newsletter subscription requests on behalf of a user.","newsletter:unsubscribe":"Revoke newsletter subscription for a user email.","mcp:read":"Read MCP metadata and resources.","mcp:tools:inquiry":"Call MCP inquiry tools.","mcp:tools:booking":"Call MCP booking tools.","ask:query":"Run natural-language queries via /ask."}}}}},"schemas":{"SubscribeRequest":{"type":"object","required":["email","consent"],"properties":{"email":{"type":"string","format":"email","description":"Subscriber email address."},"locale":{"type":"string","enum":["pl","en"],"description":"Preferred content language. Defaults to `pl`."},"consent":{"type":"boolean","description":"Must be `true` to confirm newsletter consent."}}},"ContactRequest":{"type":"object","required":["name","email","message"],"properties":{"name":{"type":"string","minLength":2,"description":"Full name of the person submitting the inquiry."},"email":{"type":"string","format":"email","description":"Contact email address."},"topic":{"type":"string","description":"Subject of the inquiry."},"message":{"type":"string","minLength":10,"description":"Description of the situation or request."},"locale":{"type":"string","enum":["pl","en"],"description":"Preferred language for response. Defaults to `pl`."}}},"UnsubscribeRequest":{"type":"object","required":["email"],"properties":{"email":{"type":"string","format":"email","description":"Email address to remove from newsletter updates."}}},"SuccessResponse":{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","const":true}}},"ErrorResponse":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message","hint","retryable"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"hint":{"type":"string"},"retryable":{"type":"boolean"}}}}},"McpJsonRpcRequest":{"type":"object","required":["jsonrpc","method"],"properties":{"jsonrpc":{"type":"string","const":"2.0"},"id":{"type":["string","number","null"]},"method":{"type":"string"},"params":{"type":"object"}}},"McpServiceInquiryArguments":{"type":"object","required":["fullName","email","supportArea"],"properties":{"fullName":{"type":"string","minLength":3},"email":{"type":"string","format":"email"},"phone":{"type":"string"},"supportArea":{"type":"string","minLength":3},"notes":{"type":"string"}}},"McpConsultationBookingArguments":{"type":"object","required":["fullName","email","timeZone","start"],"properties":{"fullName":{"type":"string","minLength":3},"email":{"type":"string","format":"email"},"phone":{"type":"string"},"timeZone":{"type":"string","example":"Europe/Warsaw"},"start":{"type":"string","format":"date-time"},"notes":{"type":"string"}}},"McpDiscoveryResponse":{"type":"object","required":["name","version","transport","serverCardUrl","wellKnownTransportUrl","tools"],"properties":{"name":{"type":"string"},"version":{"type":"string"},"transport":{"type":"string"},"serverCardUrl":{"type":"string","format":"uri"},"wellKnownTransportUrl":{"type":"string","format":"uri"},"tools":{"type":"array","items":{"type":"object"}}}},"McpSseEvent":{"type":"string","description":"Server-Sent Events stream payload. Events include `start`, `progress`, and `complete` with JSON in each `data:` line."},"McpJsonRpcResponse":{"type":"object","required":["jsonrpc"],"properties":{"jsonrpc":{"type":"string","const":"2.0"},"id":{"type":["string","number","null"]},"result":{"type":"object"},"error":{"type":"object"}}},"AskRequest":{"type":"object","required":["query"],"properties":{"query":{"description":"NLWeb query object (`{ text: \"...\" }`) or legacy string.","oneOf":[{"type":"string","minLength":1},{"type":"object","required":["text"],"properties":{"text":{"type":"string","minLength":1,"description":"Natural language user query (NLWeb shape)."}}}]},"locale":{"type":"string","enum":["pl","en"],"default":"pl"},"context":{"type":"object","additionalProperties":true,"description":"Optional contextual fields for ranking and response shaping."},"prefer":{"type":"object","properties":{"streaming":{"type":"boolean","description":"When true, response is streamed as SSE events."},"mode":{"type":"string","enum":["conversational"],"description":"When conversational and chat is configured, prepend a website chat result."}},"additionalProperties":true},"meta":{"type":"object","additionalProperties":true}}},"AskResult":{"type":"object","required":["id","type","title","url","summary","confidence","source"],"properties":{"id":{"type":"string"},"type":{"type":"string"},"title":{"type":"string"},"url":{"type":"string","format":"uri"},"summary":{"type":"string"},"confidence":{"type":"number","minimum":0,"maximum":1},"source":{"type":"string","format":"uri"}}},"AskResponse":{"type":"object","required":["_meta","query","results"],"properties":{"_meta":{"type":"object","required":["response_type","version"],"properties":{"response_type":{"type":"string","example":"result_set"},"version":{"type":"string","example":"0.2"}}},"query":{"type":"string"},"results":{"type":"array","items":{"$ref":"#/components/schemas/AskResult"}}}},"AskSseEvent":{"type":"string","description":"SSE event stream for /ask endpoint. Events: start, result, complete."},"ChatUiMessage":{"type":"object","required":["role","parts"],"properties":{"id":{"type":"string"},"role":{"type":"string","enum":["user","assistant","system"]},"parts":{"type":"array","minItems":1,"items":{"type":"object"},"description":"AI SDK UI message parts (typically text parts for user/assistant messages)."}}},"ChatRequest":{"type":"object","required":["messages"],"properties":{"messages":{"type":"array","minItems":1,"items":{"$ref":"#/components/schemas/ChatUiMessage"}},"locale":{"type":"string","enum":["pl","en"],"default":"pl","description":"Response language for the website chat assistant."}}},"ChatUiMessageStream":{"type":"string","description":"Vercel AI SDK UI message stream (`text/event-stream`). Response includes header `x-vercel-ai-ui-message-stream: v1`."},"ConsultationSlot":{"type":"object","required":["start","label","date"],"properties":{"start":{"type":"string","format":"date-time"},"end":{"type":"string","format":"date-time"},"label":{"type":"string"},"date":{"type":"string","format":"date"}}},"ConsultationSlotsResponse":{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean"},"mode":{"type":"string","enum":["slots","link_only"]},"bookingUrl":{"type":"string","format":"uri"},"timeZone":{"type":"string"},"slots":{"type":"array","items":{"$ref":"#/components/schemas/ConsultationSlot"}},"range":{"type":"object","properties":{"start":{"type":"string","format":"date"},"end":{"type":"string","format":"date"}}},"error":{"type":"string"}}},"OAuthAuthorizationServerMetadata":{"type":"object","required":["issuer","authorization_endpoint","token_endpoint","code_challenge_methods_supported"],"properties":{"issuer":{"type":"string","format":"uri"},"authorization_endpoint":{"type":"string","format":"uri"},"token_endpoint":{"type":"string","format":"uri"},"code_challenge_methods_supported":{"type":"array","items":{"type":"string"}},"scopes_supported":{"type":"array","items":{"type":"string"}}}},"OAuthTokenResponse":{"type":"object","required":["access_token","token_type","expires_in"],"properties":{"access_token":{"type":"string"},"token_type":{"type":"string"},"expires_in":{"type":"integer"},"scope":{"type":"string"}}},"ApiCatalogResponse":{"type":"object","required":["name","version","docs","endpoints","streaming","errors"],"properties":{"name":{"type":"string"},"version":{"type":"string"},"docs":{"type":"object"},"endpoints":{"type":"array","items":{"type":"object"}},"streaming":{"type":"object"},"errors":{"type":"object"}}},"ErrorContractResponse":{"type":"object","required":["name","version","schema","examples"],"properties":{"name":{"type":"string"},"version":{"type":"string"},"schema":{"type":"object"},"examples":{"type":"array","items":{"type":"object"}}}}},"responses":{"Error400":{"description":"Validation or JSON parsing error.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"Error429":{"description":"Rate limit exceeded.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"Error501":{"description":"Endpoint not configured for current deployment.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"Error502":{"description":"Transient upstream/provider error.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"paths":{"/api/subscribe":{"options":{"operationId":"optionsSubscribePreflight","summary":"CORS preflight for subscribe endpoint","responses":{"204":{"description":"CORS headers returned"}}},"post":{"operationId":"postNewsletterSubscribe","summary":"Subscribe email to newsletter","description":"Adds an email to newsletter list for selected locale.","x-recommended-scopes":["newsletter:subscribe"],"security":[{},{"OAuth2":["newsletter:subscribe"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscribeRequest"}}}},"responses":{"200":{"description":"Subscription accepted.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"$ref":"#/components/responses/Error400"},"429":{"$ref":"#/components/responses/Error429"},"501":{"$ref":"#/components/responses/Error501"},"502":{"$ref":"#/components/responses/Error502"}}}},"/api/contact":{"options":{"operationId":"optionsContactPreflight","summary":"CORS preflight for contact endpoint","responses":{"204":{"description":"CORS headers returned"}}},"post":{"operationId":"postContactInquiry","summary":"Send contact form inquiry","description":"Submits a contact form inquiry. Sends notification email and optionally adds the contact to the Resend audience (segment \"Kontakt\").","security":[{}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactRequest"}}}},"responses":{"200":{"description":"Inquiry submitted successfully.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"$ref":"#/components/responses/Error400"},"429":{"$ref":"#/components/responses/Error429"},"501":{"$ref":"#/components/responses/Error501"},"502":{"$ref":"#/components/responses/Error502"}}}},"/api/newsletter/unsubscribe":{"options":{"operationId":"optionsUnsubscribePreflight","summary":"CORS preflight for unsubscribe endpoint","responses":{"204":{"description":"CORS headers returned"}}},"post":{"operationId":"postNewsletterUnsubscribe","summary":"Unsubscribe email from newsletter","description":"Removes an email from newsletter list.","x-recommended-scopes":["newsletter:unsubscribe"],"security":[{},{"OAuth2":["newsletter:unsubscribe"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnsubscribeRequest"}}}},"responses":{"200":{"description":"Unsubscribe accepted.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"$ref":"#/components/responses/Error400"},"429":{"$ref":"#/components/responses/Error429"},"501":{"$ref":"#/components/responses/Error501"},"502":{"$ref":"#/components/responses/Error502"}}}},"/api/mcp":{"get":{"operationId":"getMcpDiscoveryManifest","summary":"MCP discovery manifest","description":"Returns MCP discovery metadata and tool definitions for service inquiry and consultation booking. Supports SSE streaming when `Accept: text/event-stream` is provided.","x-recommended-scopes":["mcp:read"],"security":[{},{"OAuth2":["mcp:read"]}],"responses":{"200":{"description":"MCP manifest response.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpDiscoveryResponse"}},"text/markdown":{"schema":{"type":"string"}},"text/event-stream":{"schema":{"$ref":"#/components/schemas/McpSseEvent"}}}},"429":{"$ref":"#/components/responses/Error429"}}},"post":{"operationId":"postMcpJsonRpc","summary":"MCP JSON-RPC endpoint","description":"Accepts JSON-RPC requests (`initialize`, `tools/list`, `tools/call`, `resources/list`, `resources/read`). Supported tools include `articles_recommend`, `services_list`, `pricing_get`, `contact_submit`, `service_inquiry_submit`, `consultation_availability`, `consultation_book`, and newsletter tools.","x-recommended-scopes":["mcp:tools:inquiry","mcp:tools:booking"],"security":[{},{"OAuth2":["mcp:tools:inquiry","mcp:tools:booking"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpJsonRpcRequest"}}}},"responses":{"200":{"description":"MCP JSON-RPC success response.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpJsonRpcResponse"}}}},"400":{"description":"Invalid JSON-RPC request.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpJsonRpcResponse"}}}},"404":{"description":"Unknown method.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpJsonRpcResponse"}}}},"429":{"$ref":"#/components/responses/Error429"},"501":{"description":"Method known but not publicly callable.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpJsonRpcResponse"}}}}}}},"/mcp":{"get":{"operationId":"getMcpDiscoveryManifestWeb","summary":"WebMCP discovery manifest","description":"Primary WebMCP transport endpoint. Supports JSON, markdown, and SSE negotiation.","x-recommended-scopes":["mcp:read"],"security":[{},{"OAuth2":["mcp:read"]}],"responses":{"200":{"description":"MCP manifest response.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpDiscoveryResponse"}},"text/markdown":{"schema":{"type":"string"}},"text/event-stream":{"schema":{"$ref":"#/components/schemas/McpSseEvent"}}}},"429":{"$ref":"#/components/responses/Error429"}}},"post":{"operationId":"postMcpJsonRpcWeb","summary":"WebMCP JSON-RPC endpoint","description":"Primary JSON-RPC transport for browser-based and server-based MCP clients. Supported tools include `articles_recommend`, `services_list`, `pricing_get`, `contact_submit`, `service_inquiry_submit`, `consultation_availability`, `consultation_book`, and newsletter tools. Supports `resources/list` and `resources/read` for ui:// resources.","x-recommended-scopes":["mcp:tools:inquiry","mcp:tools:booking"],"security":[{},{"OAuth2":["mcp:tools:inquiry","mcp:tools:booking"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpJsonRpcRequest"}}}},"responses":{"200":{"description":"MCP JSON-RPC success response.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpJsonRpcResponse"}}}},"400":{"description":"Invalid JSON-RPC request.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpJsonRpcResponse"}}}},"404":{"description":"Unknown method.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpJsonRpcResponse"}}}},"429":{"$ref":"#/components/responses/Error429"},"501":{"description":"Method known but not publicly callable.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpJsonRpcResponse"}}}}}}},"/api/consultation/slots":{"options":{"operationId":"optionsConsultationSlotsPreflight","summary":"CORS preflight for consultation slot lookup","responses":{"204":{"description":"CORS headers returned"}}},"get":{"operationId":"getConsultationSlots","summary":"Available Cal.com consultation slots","description":"Returns upcoming free consultation slots from Cal.com for the chat widget and agents. Defaults to the next 14 days in `Europe/Warsaw`. Falls back to the public Cal.com booking URL when the slots API is unavailable. Rate limit: 20 requests per minute per client.","security":[{}],"parameters":[{"name":"locale","in":"query","schema":{"type":"string","enum":["pl","en"],"default":"pl"}},{"name":"timeZone","in":"query","schema":{"type":"string","default":"Europe/Warsaw"}},{"name":"start","in":"query","schema":{"type":"string","format":"date"}},{"name":"end","in":"query","schema":{"type":"string","format":"date"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":30,"default":12}}],"responses":{"200":{"description":"Slot list or link-only fallback.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConsultationSlotsResponse"}}}},"429":{"$ref":"#/components/responses/Error429"}}}},"/api/chat":{"options":{"operationId":"optionsWebsiteChatPreflight","summary":"CORS preflight for website chat assistant","responses":{"204":{"description":"CORS headers returned"}}},"post":{"operationId":"postWebsiteChat","summary":"Streaming website chat assistant","description":"Accepts AI SDK UI messages and streams assistant responses via Vercel AI Gateway (default model `deepseek/deepseek-v4-flash`). Server-side tools mirror MCP capabilities: article recommendations, services, pricing, contact, service inquiry, consultation availability, and consultation booking. Requires `AI_GATEWAY_API_KEY` or Vercel AI Gateway OIDC on deployment. Rate limit: 20 requests per minute per client.","security":[{}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatRequest"}}}},"responses":{"200":{"description":"Assistant response stream started.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"x-vercel-ai-ui-message-stream":{"description":"AI SDK UI message stream protocol version.","schema":{"type":"string","example":"v1"}}},"content":{"text/event-stream":{"schema":{"$ref":"#/components/schemas/ChatUiMessageStream"}}}},"400":{"$ref":"#/components/responses/Error400"},"429":{"$ref":"#/components/responses/Error429"},"503":{"description":"Chat assistant is not configured on the server.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/ask":{"options":{"operationId":"optionsNlwebAskPreflight","summary":"CORS preflight for NLWeb ask endpoint","responses":{"204":{"description":"CORS headers returned"}}},"post":{"operationId":"postNlwebAsk","summary":"NLWeb-style natural language endpoint","description":"Accepts NLWeb `query.text` (or legacy `query` string) and returns ranked articles, services, pricing, contact, and consultation resources. Supports SSE streaming when `prefer.streaming=true`.","x-recommended-scopes":["ask:query"],"security":[{},{"OAuth2":["ask:query"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AskRequest"}}}},"responses":{"200":{"description":"Query processed successfully.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AskResponse"}},"text/event-stream":{"schema":{"$ref":"#/components/schemas/AskSseEvent"}}}},"400":{"$ref":"#/components/responses/Error400"},"429":{"$ref":"#/components/responses/Error429"}}}},"/.well-known/oauth-authorization-server":{"get":{"operationId":"getOauthAuthorizationServerMetadata","summary":"OAuth 2.0 authorization server metadata","description":"RFC 8414 metadata for OAuth discovery including PKCE S256 support.","responses":{"200":{"description":"Authorization server metadata response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthAuthorizationServerMetadata"}}}}}}},"/.well-known/oauth2/authorize":{"get":{"operationId":"getOauthAuthorizeEndpoint","summary":"OAuth 2.0 authorization endpoint","description":"Authorization endpoint supporting code flow and PKCE S256 for agent integrations.","responses":{"200":{"description":"Authorization endpoint available.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid authorization request.","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/.well-known/oauth2/token":{"post":{"operationId":"postOauthTokenEndpoint","summary":"OAuth 2.0 token endpoint","description":"Issues scoped bearer tokens for supported grant types.","requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"grant_type":{"type":"string"},"scope":{"type":"string"},"code_verifier":{"type":"string"}}}},"application/json":{"schema":{"type":"object","properties":{"grant_type":{"type":"string"},"scope":{"type":"string"},"code_verifier":{"type":"string"}}}}}},"responses":{"200":{"description":"Token issued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthTokenResponse"}}}},"400":{"description":"Invalid token request.","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api":{"get":{"operationId":"getApiEndpointCatalog","summary":"Public API endpoint catalog","description":"Provides a machine-readable catalog of API endpoints, docs links, streaming support, and error contract references.","responses":{"200":{"description":"API catalog response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiCatalogResponse"}}}}}}},"/api/error-format":{"get":{"operationId":"getApiErrorContract","summary":"JSON error response contract","description":"Returns machine-readable JSON schema and examples for API error responses.","responses":{"200":{"description":"Error contract response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorContractResponse"}}}}}}}}}