Ask Frase Answers a question (SSE)
Developer-API equivalent of the Answers widget's ask endpoint: the same retrieval and generation pipeline, streamed back as Server-Sent Events. Requires the answers:ask scope.
Gates, in the order they run - each returns immediately:
- API key auth (401 bad/missing key, 403 missing scope, 429 tier budget).
- The answers_v1 feature flag, resolved for the organization. Not enabled means 404 Endpoint not found. - the route is made to look nonexistent rather than admitting it exists.
- Body validation: the body must be JSON, siteId and question are required strings.
- siteId must belong to the authenticated organization and must not be trashed. A cross-org or deleted site returns the same 404 Site not found. as one that never existed.
- Per-site Answers entitlement, resolved against the target site's tier. An org admin who turned Answers off for the site gets 403 site_feature_disabled; a site whose Answers tier does not include developer-API access gets 403 plan_required. Trial-plan organizations skip this gate entirely.
- A widget must already be configured for the site. With none, 400 site_not_configured - set one up at /settings/answers first. When several non-revoked widgets exist the oldest is used; they share one knowledge base, and its branding flag drives the credit cap below.
- The question is sanitized (control characters stripped, whitespace normalized, 1-10,000 characters) and screened for prompt injection. Failures are 400 invalid_param or disallowed_content.
- A per-key Answers rate limit of 60 requests/minute, layered on top of the org-wide tier limit. Exceeding it is 429 rate_limited with Retry-After and X-RateLimit-* headers.
Billing: Answers is metered per CONVERSATION, not per message. The first message of a new conversation reserves one Answers conversation credit; follow-ups that pass the returned conversationId back in are free ONLY while the conversation is still live: the row must match the same visitorFingerprint AND have been active within the last 120 minutes - an idle conversation is silently replaced by a NEW one, which charges another credit. When the cap is reached the just-created conversation is deleted (so it cannot linger as a 0-message row counting against the cap forever) and the call returns 429 with code usage_limit_reached, or subscription_inactive when the refusal came from the subscription rather than the cap.
Omit conversationId to start a new conversation. visitorFingerprint is optional here (unlike the widget): it defaults to api:<apiKeyId>, a stable key-scoped identity, so multi-turn continuity works without minting visitor IDs. Once the stream opens the response is always HTTP 200 - failures inside generation arrive as an SSE error event followed by a message-finish event with answerType: "error". Failures BEFORE the stream opens (credit reservation, conversation setup) surface as a plain 500 with no v1 envelope.
Request
- Base URL: https://next.frase.io/api/v1
- URL: https://next.frase.io/api/v1/answers/ask
- Auth: API key in header X-API-KEY
Request body
Response
SSE stream. Events are emitted as event: <type> / data: <json> pairs. Types, in order: conversation (once, first in the normal case - carries conversationId, messageId and the retrieved sources), zero or more text-delta (each carrying a delta string to append), an optional error when generation fails mid-stream, and message-finish (once, last). When generation fails before its first token the stream can consist of just error + message-finish, with no preceding conversation frame.
Changes
No recorded changes to this operation across all 1 revision of this API.