{"openapi":"3.1.0","info":{"title":"Surveyish Public API","version":"1.0.0","description":"Programmatic access to Surveyish surveys, responses, recipients, and deliveries.\n\n## Authentication\nAll endpoints require a Bearer API key. Create one at Settings → API Keys\n(Pro plan required). The key inherits an organization role (viewer / editor /\nowner) chosen at creation.\n\n```\nAuthorization: Bearer sd_live_...\n```\n\n## Rate limits\nDefault: 60 requests per 60 seconds per key. Response headers `RateLimit-Limit`,\n`RateLimit-Remaining`, `RateLimit-Reset` (and legacy `X-RateLimit-*`) report\ncurrent state. On 429, `Retry-After` reports seconds until reset.\n\n## ID format\nEvery integer ID crosses the wire as a Sqids-encoded string (e.g. `NBHUAdng`).\nRound-trips are stable — pass back exactly what you received.\n\n## Response envelope\nSuccess: `{ success: true, data: {...} }`. Failure: `{ success: false, error: { message, code, details? } }`."},"servers":[{"url":"https://www.surveyish.com/api/v1","description":"Production"},{"url":"http://localhost:3001/api/v1","description":"Local dev"}],"tags":[{"name":"Authentication","description":"Credential diagnostics."},{"name":"Surveys","description":"Read surveys and their questions."},{"name":"Responses","description":"Read raw responses and aggregated stats."},{"name":"Recipients","description":"Read recipients belonging to your organization."},{"name":"Deliveries","description":"Read the delivery log for a survey."}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"sd_live_<random>","description":"API key created at Settings → API Keys."}},"schemas":{"Envelope":{"type":"object","required":["success"],"properties":{"success":{"type":"boolean"},"data":{"description":"Present when success is true. Schema varies by endpoint."},"error":{"$ref":"#/components/schemas/ErrorObject"}}},"ErrorObject":{"type":"object","required":["message"],"properties":{"message":{"type":"string","example":"Rate limit exceeded"},"code":{"type":"string","description":"Machine-readable error code. Stable across releases.","enum":["AUTH_REQUIRED","INVALID_API_KEY","PLAN_LIMIT_EXCEEDED","ORG_SUSPENDED","FORBIDDEN","RATE_LIMIT_EXCEEDED","VALIDATION_ERROR"]},"details":{"description":"Optional structured detail (e.g. Zod validation issues)."},"upgrade":{"type":"boolean","description":"Set to true when the error is fixable by upgrading the org plan."}}},"Organization":{"type":"object","properties":{"id":{"type":"string","description":"Sqids-encoded identifier. Same value round-trips in and out of the API.","example":"NBHUAdng"},"name":{"type":"string","example":"Acme Marketing"},"plan":{"type":"string","enum":["free","pro"],"example":"pro"},"role":{"type":"string","enum":["owner","editor","viewer"],"example":"editor"},"is_suspended":{"type":"boolean","example":false}}},"Survey":{"type":"object","properties":{"id":{"type":"string","description":"Sqids-encoded identifier. Same value round-trips in and out of the API.","example":"NBHUAdng"},"user_id":{"type":"string","description":"Creator (attribution only — not the access-control field).","example":"NBHUAdng"},"title":{"type":"string","example":"Q3 2026 NPS"},"description":{"type":"string","nullable":true},"share_id":{"type":"string","description":"Public share slug used in /s/<share_id> URLs."},"is_active":{"type":"boolean"},"survey_type":{"type":"string","enum":["standard","ai_insight","nps","poll"],"example":"nps"},"settings":{"type":"object","nullable":true,"description":"Type-specific settings. `ai_prompt` for AI, `slack_webhook_url` for polls.","additionalProperties":true},"allow_multiple_responses":{"type":"boolean"},"created_at":{"type":"string","format":"date-time","example":"2026-07-12T14:23:11Z"},"updated_at":{"type":"string","format":"date-time","example":"2026-07-12T14:23:11Z"},"published_at":{"type":"string","format":"date-time","example":"2026-07-12T14:23:11Z","nullable":true},"closed_at":{"type":"string","format":"date-time","example":"2026-07-12T14:23:11Z","nullable":true}}},"Question":{"type":"object","properties":{"id":{"type":"string","description":"Sqids-encoded identifier. Same value round-trips in and out of the API.","example":"NBHUAdng"},"survey_id":{"type":"string","description":"Sqids-encoded identifier. Same value round-trips in and out of the API.","example":"NBHUAdng"},"question_text":{"type":"string"},"question_type":{"type":"string","enum":["single_choice","multiple_choice","text_short","text_long","rating_scale","yes_no"]},"is_required":{"type":"boolean"},"order_index":{"type":"integer"},"options":{"type":"object","description":"Type-specific config. `{choices: [...]}` for choice types; `{min, max}` for rating_scale.","additionalProperties":true},"created_at":{"type":"string","format":"date-time","example":"2026-07-12T14:23:11Z"},"updated_at":{"type":"string","format":"date-time","example":"2026-07-12T14:23:11Z"}}},"SurveyWithQuestions":{"allOf":[{"$ref":"#/components/schemas/Survey"},{"type":"object","properties":{"questions":{"type":"array","items":{"$ref":"#/components/schemas/Question"}}}}]},"SurveySummary":{"type":"object","description":"Trimmed survey identity used inside export/results payloads.","properties":{"id":{"type":"string","description":"Sqids-encoded identifier. Same value round-trips in and out of the API.","example":"NBHUAdng"},"title":{"type":"string"},"survey_type":{"type":"string"}}},"Answer":{"type":"object","properties":{"answer_text":{"type":"string","nullable":true,"description":"Set for text_short, text_long, and yes_no. Null otherwise."},"answer_options":{"type":"object","nullable":true,"description":"`{selected: [...]}` for single/multiple_choice; `{value: N}` for rating_scale.","additionalProperties":true}}},"ResponseRow":{"type":"object","properties":{"id":{"type":"string","description":"Sqids-encoded identifier. Same value round-trips in and out of the API.","example":"NBHUAdng"},"created_at":{"type":"string","format":"date-time","example":"2026-07-12T14:23:11Z"},"wave_label":{"type":"string","nullable":true,"description":"NPS wave label the response arrived in. Null for non-NPS surveys."},"answers":{"type":"object","description":"Keyed by encoded question_id. Each value is an Answer.","additionalProperties":{"$ref":"#/components/schemas/Answer"}}}},"ResponsesExport":{"type":"object","properties":{"survey":{"$ref":"#/components/schemas/SurveySummary"},"questions":{"type":"array","items":{"$ref":"#/components/schemas/Question"}},"responses":{"type":"array","items":{"$ref":"#/components/schemas/ResponseRow"}}}},"OptionCount":{"type":"object","properties":{"value":{"type":"string","example":"Yes"},"count":{"type":"integer","example":42},"percentage":{"type":"integer","example":68}}},"QuestionStats":{"type":"object","properties":{"question_id":{"type":"string","description":"Sqids-encoded identifier. Same value round-trips in and out of the API.","example":"NBHUAdng"},"question_text":{"type":"string"},"question_type":{"type":"string"},"total_answers":{"type":"integer"},"option_counts":{"type":"array","nullable":true,"items":{"$ref":"#/components/schemas/OptionCount"},"description":"Present for yes_no, single_choice, multiple_choice."},"rating_counts":{"type":"array","nullable":true,"items":{"$ref":"#/components/schemas/OptionCount"},"description":"Present for rating_scale. Value is the rating; count is the number of responses."},"average":{"type":"number","nullable":true,"description":"Present for rating_scale."},"text_answers":{"type":"array","nullable":true,"items":{"type":"string"},"description":"Present for text_short, text_long."}}},"SurveyStats":{"type":"object","properties":{"survey_id":{"type":"string","description":"Sqids-encoded identifier. Same value round-trips in and out of the API.","example":"NBHUAdng"},"total_responses":{"type":"integer"},"questions":{"type":"array","items":{"$ref":"#/components/schemas/QuestionStats"}}}},"NpsSegmentBreakdown":{"type":"object","properties":{"total_responses":{"type":"integer"},"promoters":{"type":"integer"},"passives":{"type":"integer"},"detractors":{"type":"integer"},"score":{"type":"integer","nullable":true,"description":"promoters − detractors, normalized to −100..100."}}},"NpsFollowup":{"type":"object","properties":{"text":{"type":"string"},"segment":{"type":"string","enum":["promoters","passives","detractors"]}}},"NpsWaveStats":{"allOf":[{"$ref":"#/components/schemas/NpsSegmentBreakdown"},{"type":"object","properties":{"wave_id":{"type":"string","description":"Sqids-encoded identifier. Same value round-trips in and out of the API.","example":"NBHUAdng"},"label":{"type":"string"},"sent_at":{"type":"string","format":"date-time","example":"2026-07-12T14:23:11Z"},"closed_at":{"type":"string","format":"date-time","example":"2026-07-12T14:23:11Z","nullable":true},"followup_answers":{"type":"array","items":{"$ref":"#/components/schemas/NpsFollowup"}}}}]},"NpsDirectStats":{"allOf":[{"$ref":"#/components/schemas/NpsSegmentBreakdown"},{"type":"object","properties":{"followup_answers":{"type":"array","items":{"$ref":"#/components/schemas/NpsFollowup"}}}}]},"NpsStats":{"type":"object","properties":{"survey_id":{"type":"string","description":"Sqids-encoded identifier. Same value round-trips in and out of the API.","example":"NBHUAdng"},"title":{"type":"string"},"nps_question":{"type":"string"},"followup_question":{"type":"string","nullable":true,"description":"Text of the optional open-ended follow-up question. Null for rating-only NPS."},"overall":{"$ref":"#/components/schemas/NpsSegmentBreakdown"},"waves":{"type":"array","items":{"$ref":"#/components/schemas/NpsWaveStats"}},"direct":{"allOf":[{"$ref":"#/components/schemas/NpsDirectStats"}],"nullable":true,"description":"Wave-less responses (respondents who hit the share link before any wave was sent). Null if all responses are in waves."}}},"AiInsightCategory":{"type":"object","properties":{"name":{"type":"string"},"sentiment":{"type":"string","enum":["positive","negative","neutral","mixed"]},"sentiment_score":{"type":"number"},"summary":{"type":"string"},"response_count":{"type":"integer"},"key_quotes":{"type":"array","items":{"type":"string"}}}},"AiAnalysis":{"type":"object","properties":{"prompt":{"type":"string"},"total_responses":{"type":"integer"},"has_new_responses":{"type":"boolean","description":"True if responses have arrived since the last completed analysis."},"analysis":{"type":"object","nullable":true,"properties":{"id":{"type":"string","description":"Sqids-encoded identifier. Same value round-trips in and out of the API.","example":"NBHUAdng"},"status":{"type":"string","enum":["pending","processing","completed","failed"]},"provider":{"type":"string","nullable":true},"model":{"type":"string","nullable":true},"response_count":{"type":"integer"},"error_message":{"type":"string","nullable":true},"tokens_used":{"type":"integer","nullable":true},"created_at":{"type":"string","format":"date-time","example":"2026-07-12T14:23:11Z"},"completed_at":{"type":"string","format":"date-time","example":"2026-07-12T14:23:11Z","nullable":true},"results":{"type":"object","nullable":true,"properties":{"summary":{"type":"string"},"categories":{"type":"array","items":{"$ref":"#/components/schemas/AiInsightCategory"}},"response_count_analyzed":{"type":"integer"}}}}}}},"Recipient":{"type":"object","properties":{"id":{"type":"string","description":"Sqids-encoded identifier. Same value round-trips in and out of the API.","example":"NBHUAdng"},"name":{"type":"string"},"email":{"type":"string","nullable":true,"format":"email"},"phone":{"type":"string","nullable":true},"created_at":{"type":"string","format":"date-time","example":"2026-07-12T14:23:11Z"},"updated_at":{"type":"string","format":"date-time","example":"2026-07-12T14:23:11Z"}}},"Delivery":{"type":"object","properties":{"id":{"type":"string","description":"Sqids-encoded identifier. Same value round-trips in and out of the API.","example":"NBHUAdng"},"survey_id":{"type":"string","description":"Sqids-encoded identifier. Same value round-trips in and out of the API.","example":"NBHUAdng"},"recipient_id":{"type":"string","description":"Sqids-encoded identifier. Same value round-trips in and out of the API.","example":"NBHUAdng"},"channel":{"type":"string","enum":["email","sms"]},"status":{"type":"string","enum":["pending","sent","delivered","failed","bounced"]},"provider":{"type":"string","nullable":true},"provider_message_id":{"type":"string","nullable":true},"error_message":{"type":"string","nullable":true},"sent_at":{"type":"string","format":"date-time","example":"2026-07-12T14:23:11Z","nullable":true},"delivered_at":{"type":"string","format":"date-time","example":"2026-07-12T14:23:11Z","nullable":true},"recipient_name":{"type":"string","nullable":true},"recipient_email":{"type":"string","nullable":true},"recipient_phone":{"type":"string","nullable":true},"created_at":{"type":"string","format":"date-time","example":"2026-07-12T14:23:11Z"},"updated_at":{"type":"string","format":"date-time","example":"2026-07-12T14:23:11Z"}}},"MeResponse":{"type":"object","properties":{"authenticated_via":{"type":"string","enum":["api_key"]},"organization":{"$ref":"#/components/schemas/Organization"}}},"QuestionInput":{"type":"object","required":["question_text","question_type","order_index"],"properties":{"question_text":{"type":"string","minLength":1,"maxLength":1000},"question_type":{"type":"string","enum":["single_choice","multiple_choice","text_short","text_long","rating_scale","yes_no"]},"is_required":{"type":"boolean","default":false},"order_index":{"type":"integer","minimum":0},"options":{"type":"object","additionalProperties":true,"description":"Type-specific: `{choices: [...]}` for choice; `{min, max}` for rating."}}},"CreateSurveyRequest":{"type":"object","required":["title"],"properties":{"title":{"type":"string","minLength":1,"maxLength":500},"description":{"type":"string","maxLength":2000,"nullable":true},"is_active":{"type":"boolean","default":false},"allow_multiple_responses":{"type":"boolean","default":false},"questions":{"type":"array","items":{"$ref":"#/components/schemas/QuestionInput"}}}},"UpdateSurveyRequest":{"type":"object","description":"All fields optional. If `questions` is provided it replaces the current question set (existing questions with matching `id` are preserved, others deleted).","properties":{"title":{"type":"string","minLength":1,"maxLength":500},"description":{"type":"string","maxLength":2000,"nullable":true},"is_active":{"type":"boolean"},"allow_multiple_responses":{"type":"boolean"},"questions":{"type":"array","items":{"allOf":[{"$ref":"#/components/schemas/QuestionInput"},{"type":"object","properties":{"id":{"type":"string","description":"Present to update an existing question; omit to create.","example":"NBHUAdng"}}}]}}}},"CreateNpsSurveyRequest":{"type":"object","required":["title"],"properties":{"title":{"type":"string","minLength":1,"maxLength":500},"nps_question":{"type":"string","maxLength":1000,"description":"Defaults to standard NPS phrasing if omitted."},"followup_question":{"type":"string","maxLength":1000,"description":"Optional open-ended follow-up."}}},"CreatePollRequest":{"type":"object","required":["title","question_text","question_type"],"properties":{"title":{"type":"string","minLength":1,"maxLength":500},"question_text":{"type":"string","minLength":1,"maxLength":1000},"question_type":{"type":"string","enum":["single_choice","yes_no","rating_scale"]},"options":{"type":"object","additionalProperties":true},"slack_webhook_url":{"type":"string","format":"uri","description":"Optional Slack incoming webhook; posted to on publish."}}},"CreateAiInsightSurveyRequest":{"type":"object","required":["prompt"],"properties":{"prompt":{"type":"string","minLength":10,"maxLength":1000},"title":{"type":"string","minLength":1,"maxLength":500}}},"CreateRecipientRequest":{"type":"object","required":["name"],"description":"Requires at least one of `email` or `phone`.","properties":{"name":{"type":"string","minLength":1,"maxLength":255},"email":{"type":"string","format":"email","nullable":true},"phone":{"type":"string","maxLength":50,"nullable":true}}},"BulkCreateRecipientsRequest":{"type":"object","required":["recipients"],"properties":{"recipients":{"type":"array","minItems":1,"items":{"$ref":"#/components/schemas/CreateRecipientRequest"}}}},"SendNotificationsRequest":{"type":"object","required":["channels"],"properties":{"channels":{"type":"array","minItems":1,"items":{"type":"string","enum":["email","sms"]},"description":"One or more channels to fan out to. Recipients missing the channel are skipped."}}}}},"paths":{"/me":{"get":{"tags":["Authentication"],"summary":"Return caller identity and org context","description":"Diagnostic endpoint. Confirms credentials work and reports which organization the API key operates in.","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/MeResponse"}}}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"404":{"description":"Resource not found in the caller's organization.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"429":{"description":"Rate limit exceeded. See `Retry-After` header for wait time.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds until the limit resets."},"RateLimit-Limit":{"schema":{"type":"integer"}},"RateLimit-Remaining":{"schema":{"type":"integer"}},"RateLimit-Reset":{"schema":{"type":"integer"},"description":"Seconds until reset."}},"content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}}}}},"/surveys":{"get":{"tags":["Surveys"],"summary":"List surveys in the active organization","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"array","items":{"$ref":"#/components/schemas/Survey"}}}}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"404":{"description":"Resource not found in the caller's organization.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"429":{"description":"Rate limit exceeded. See `Retry-After` header for wait time.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds until the limit resets."},"RateLimit-Limit":{"schema":{"type":"integer"}},"RateLimit-Remaining":{"schema":{"type":"integer"}},"RateLimit-Reset":{"schema":{"type":"integer"},"description":"Seconds until reset."}},"content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}}}},"post":{"tags":["Surveys"],"summary":"Create a standard multi-question survey","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSurveyRequest"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/SurveyWithQuestions"}}}}}},"400":{"description":"Request body failed Zod validation. `error.details` carries the field-level issues.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"403":{"description":"Viewer key attempting a write, or org is suspended, or feature is Pro-gated. `error.code` distinguishes: `FORBIDDEN` (role), `ORG_SUSPENDED`, `PLAN_LIMIT_EXCEEDED`.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"404":{"description":"Resource not found in the caller's organization.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"429":{"description":"Rate limit exceeded. See `Retry-After` header for wait time.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds until the limit resets."},"RateLimit-Limit":{"schema":{"type":"integer"}},"RateLimit-Remaining":{"schema":{"type":"integer"}},"RateLimit-Reset":{"schema":{"type":"integer"},"description":"Seconds until reset."}},"content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}}}}},"/surveys/{id}":{"get":{"tags":["Surveys"],"summary":"Get a survey with its questions","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","description":"Sqids-encoded identifier. Same value round-trips in and out of the API.","example":"NBHUAdng"},"description":"Sqids-encoded survey ID."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/SurveyWithQuestions"}}}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"404":{"description":"Resource not found in the caller's organization.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"429":{"description":"Rate limit exceeded. See `Retry-After` header for wait time.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds until the limit resets."},"RateLimit-Limit":{"schema":{"type":"integer"}},"RateLimit-Remaining":{"schema":{"type":"integer"}},"RateLimit-Reset":{"schema":{"type":"integer"},"description":"Seconds until reset."}},"content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}}}},"patch":{"tags":["Surveys"],"summary":"Update a survey","description":"Partial update. Include `questions` to replace the question set; questions with matching `id` are preserved.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","description":"Sqids-encoded identifier. Same value round-trips in and out of the API.","example":"NBHUAdng"},"description":"Sqids-encoded survey ID."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSurveyRequest"}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/SurveyWithQuestions"}}}}}},"400":{"description":"Request body failed Zod validation. `error.details` carries the field-level issues.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"403":{"description":"Viewer key attempting a write, or org is suspended, or feature is Pro-gated. `error.code` distinguishes: `FORBIDDEN` (role), `ORG_SUSPENDED`, `PLAN_LIMIT_EXCEEDED`.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"404":{"description":"Resource not found in the caller's organization.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"429":{"description":"Rate limit exceeded. See `Retry-After` header for wait time.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds until the limit resets."},"RateLimit-Limit":{"schema":{"type":"integer"}},"RateLimit-Remaining":{"schema":{"type":"integer"}},"RateLimit-Reset":{"schema":{"type":"integer"},"description":"Seconds until reset."}},"content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}}}},"delete":{"tags":["Surveys"],"summary":"Delete a survey","description":"Permanent. Cascades to questions, responses, answers, deliveries.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","description":"Sqids-encoded identifier. Same value round-trips in and out of the API.","example":"NBHUAdng"},"description":"Sqids-encoded survey ID."}],"responses":{"204":{"description":"Deleted"},"400":{"description":"Request body failed Zod validation. `error.details` carries the field-level issues.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"403":{"description":"Viewer key attempting a write, or org is suspended, or feature is Pro-gated. `error.code` distinguishes: `FORBIDDEN` (role), `ORG_SUSPENDED`, `PLAN_LIMIT_EXCEEDED`.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"404":{"description":"Resource not found in the caller's organization.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"429":{"description":"Rate limit exceeded. See `Retry-After` header for wait time.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds until the limit resets."},"RateLimit-Limit":{"schema":{"type":"integer"}},"RateLimit-Remaining":{"schema":{"type":"integer"}},"RateLimit-Reset":{"schema":{"type":"integer"},"description":"Seconds until reset."}},"content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}}}}},"/surveys/{id}/responses":{"get":{"tags":["Responses"],"summary":"List all responses for a survey","description":"Returns questions and responses in a normalized shape — each response's `answers` are keyed by `question_id`. NPS responses include `wave_label`.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","description":"Sqids-encoded identifier. Same value round-trips in and out of the API.","example":"NBHUAdng"},"description":"Sqids-encoded survey ID."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/ResponsesExport"}}}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"404":{"description":"Resource not found in the caller's organization.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"429":{"description":"Rate limit exceeded. See `Retry-After` header for wait time.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds until the limit resets."},"RateLimit-Limit":{"schema":{"type":"integer"}},"RateLimit-Remaining":{"schema":{"type":"integer"}},"RateLimit-Reset":{"schema":{"type":"integer"},"description":"Seconds until reset."}},"content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}}}}},"/surveys/{id}/results":{"get":{"tags":["Responses"],"summary":"Aggregated stats per question","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","description":"Sqids-encoded identifier. Same value round-trips in and out of the API.","example":"NBHUAdng"},"description":"Sqids-encoded survey ID."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/SurveyStats"}}}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"404":{"description":"Resource not found in the caller's organization.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"429":{"description":"Rate limit exceeded. See `Retry-After` header for wait time.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds until the limit resets."},"RateLimit-Limit":{"schema":{"type":"integer"}},"RateLimit-Remaining":{"schema":{"type":"integer"}},"RateLimit-Reset":{"schema":{"type":"integer"},"description":"Seconds until reset."}},"content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}}}}},"/surveys/{id}/nps-stats":{"get":{"tags":["Responses"],"summary":"Per-wave NPS breakdown","description":"Only works for surveys of type `nps`. Returns per-wave score, segment counts, and follow-up verbatims tagged by segment.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","description":"Sqids-encoded identifier. Same value round-trips in and out of the API.","example":"NBHUAdng"},"description":"Sqids-encoded survey ID."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/NpsStats"}}}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"404":{"description":"Resource not found in the caller's organization.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"429":{"description":"Rate limit exceeded. See `Retry-After` header for wait time.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds until the limit resets."},"RateLimit-Limit":{"schema":{"type":"integer"}},"RateLimit-Remaining":{"schema":{"type":"integer"}},"RateLimit-Reset":{"schema":{"type":"integer"},"description":"Seconds until reset."}},"content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}}}}},"/surveys/{id}/insights":{"get":{"tags":["Responses"],"summary":"Latest AI insight analysis","description":"Only works for surveys of type `ai_insight`. Returns the latest analysis (may be null if none has been run) plus a `has_new_responses` flag indicating whether re-analysis is warranted.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","description":"Sqids-encoded identifier. Same value round-trips in and out of the API.","example":"NBHUAdng"},"description":"Sqids-encoded survey ID."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/AiAnalysis"}}}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"404":{"description":"Resource not found in the caller's organization.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"429":{"description":"Rate limit exceeded. See `Retry-After` header for wait time.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds until the limit resets."},"RateLimit-Limit":{"schema":{"type":"integer"}},"RateLimit-Remaining":{"schema":{"type":"integer"}},"RateLimit-Reset":{"schema":{"type":"integer"},"description":"Seconds until reset."}},"content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}}}}},"/recipients":{"get":{"tags":["Recipients"],"summary":"List recipients in the active organization","parameters":[{"name":"search","in":"query","required":false,"schema":{"type":"string"},"description":"Case-insensitive substring match on name, email, or phone."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"array","items":{"$ref":"#/components/schemas/Recipient"}}}}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"404":{"description":"Resource not found in the caller's organization.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"429":{"description":"Rate limit exceeded. See `Retry-After` header for wait time.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds until the limit resets."},"RateLimit-Limit":{"schema":{"type":"integer"}},"RateLimit-Remaining":{"schema":{"type":"integer"}},"RateLimit-Reset":{"schema":{"type":"integer"},"description":"Seconds until reset."}},"content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}}}},"post":{"tags":["Recipients"],"summary":"Create a single recipient","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateRecipientRequest"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/Recipient"}}}}}},"400":{"description":"Request body failed Zod validation. `error.details` carries the field-level issues.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"403":{"description":"Viewer key attempting a write, or org is suspended, or feature is Pro-gated. `error.code` distinguishes: `FORBIDDEN` (role), `ORG_SUSPENDED`, `PLAN_LIMIT_EXCEEDED`.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"404":{"description":"Resource not found in the caller's organization.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"429":{"description":"Rate limit exceeded. See `Retry-After` header for wait time.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds until the limit resets."},"RateLimit-Limit":{"schema":{"type":"integer"}},"RateLimit-Remaining":{"schema":{"type":"integer"}},"RateLimit-Reset":{"schema":{"type":"integer"},"description":"Seconds until reset."}},"content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}}}}},"/surveys/{id}/deliveries":{"get":{"tags":["Deliveries"],"summary":"Delivery log for a survey","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","description":"Sqids-encoded identifier. Same value round-trips in and out of the API.","example":"NBHUAdng"},"description":"Sqids-encoded survey ID."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"array","items":{"$ref":"#/components/schemas/Delivery"}}}}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"404":{"description":"Resource not found in the caller's organization.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"429":{"description":"Rate limit exceeded. See `Retry-After` header for wait time.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds until the limit resets."},"RateLimit-Limit":{"schema":{"type":"integer"}},"RateLimit-Remaining":{"schema":{"type":"integer"}},"RateLimit-Reset":{"schema":{"type":"integer"},"description":"Seconds until reset."}},"content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}}}},"post":{"tags":["Deliveries"],"summary":"Send this survey to its assigned recipients","description":"Fires notifications on the given channels. For NPS surveys, opens a new wave. Requires editor+ role, non-suspended org, and the relevant channel entitlement (Pro).","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","description":"Sqids-encoded identifier. Same value round-trips in and out of the API.","example":"NBHUAdng"},"description":"Sqids-encoded survey ID."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendNotificationsRequest"}}}},"responses":{"200":{"description":"Delivery batch accepted. Actual send is fire-and-forget; poll `GET /surveys/{id}/deliveries` for status.","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","additionalProperties":true}}}}}},"400":{"description":"Request body failed Zod validation. `error.details` carries the field-level issues.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"403":{"description":"Viewer key attempting a write, or org is suspended, or feature is Pro-gated. `error.code` distinguishes: `FORBIDDEN` (role), `ORG_SUSPENDED`, `PLAN_LIMIT_EXCEEDED`.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"404":{"description":"Resource not found in the caller's organization.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"429":{"description":"Rate limit exceeded. See `Retry-After` header for wait time.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds until the limit resets."},"RateLimit-Limit":{"schema":{"type":"integer"}},"RateLimit-Remaining":{"schema":{"type":"integer"}},"RateLimit-Reset":{"schema":{"type":"integer"},"description":"Seconds until reset."}},"content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}}}}},"/surveys/nps":{"post":{"tags":["Surveys"],"summary":"Create an NPS survey (Pro)","description":"Auto-generates a 0–10 rating question plus an optional open-ended follow-up.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateNpsSurveyRequest"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/SurveyWithQuestions"}}}}}},"400":{"description":"Request body failed Zod validation. `error.details` carries the field-level issues.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"403":{"description":"Viewer key attempting a write, or org is suspended, or feature is Pro-gated. `error.code` distinguishes: `FORBIDDEN` (role), `ORG_SUSPENDED`, `PLAN_LIMIT_EXCEEDED`.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"404":{"description":"Resource not found in the caller's organization.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"429":{"description":"Rate limit exceeded. See `Retry-After` header for wait time.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds until the limit resets."},"RateLimit-Limit":{"schema":{"type":"integer"}},"RateLimit-Remaining":{"schema":{"type":"integer"}},"RateLimit-Reset":{"schema":{"type":"integer"},"description":"Seconds until reset."}},"content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}}}}},"/surveys/poll":{"post":{"tags":["Surveys"],"summary":"Create a single-question poll","description":"Optionally attach a Slack webhook URL — posted to on publish.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePollRequest"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/SurveyWithQuestions"}}}}}},"400":{"description":"Request body failed Zod validation. `error.details` carries the field-level issues.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"403":{"description":"Viewer key attempting a write, or org is suspended, or feature is Pro-gated. `error.code` distinguishes: `FORBIDDEN` (role), `ORG_SUSPENDED`, `PLAN_LIMIT_EXCEEDED`.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"404":{"description":"Resource not found in the caller's organization.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"429":{"description":"Rate limit exceeded. See `Retry-After` header for wait time.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds until the limit resets."},"RateLimit-Limit":{"schema":{"type":"integer"}},"RateLimit-Remaining":{"schema":{"type":"integer"}},"RateLimit-Reset":{"schema":{"type":"integer"},"description":"Seconds until reset."}},"content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}}}}},"/surveys/ai-insight":{"post":{"tags":["Surveys"],"summary":"Create an AI insight survey (Pro)","description":"Auto-generates a single open-ended question. The prompt is stored on the survey settings and drives the LLM analysis.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAiInsightSurveyRequest"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/SurveyWithQuestions"}}}}}},"400":{"description":"Request body failed Zod validation. `error.details` carries the field-level issues.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"403":{"description":"Viewer key attempting a write, or org is suspended, or feature is Pro-gated. `error.code` distinguishes: `FORBIDDEN` (role), `ORG_SUSPENDED`, `PLAN_LIMIT_EXCEEDED`.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"404":{"description":"Resource not found in the caller's organization.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"429":{"description":"Rate limit exceeded. See `Retry-After` header for wait time.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds until the limit resets."},"RateLimit-Limit":{"schema":{"type":"integer"}},"RateLimit-Remaining":{"schema":{"type":"integer"}},"RateLimit-Reset":{"schema":{"type":"integer"},"description":"Seconds until reset."}},"content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}}}}},"/surveys/{id}/publish":{"post":{"tags":["Surveys"],"summary":"Publish a draft survey","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","description":"Sqids-encoded identifier. Same value round-trips in and out of the API.","example":"NBHUAdng"},"description":"Sqids-encoded survey ID."}],"responses":{"200":{"description":"Published","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/Survey"}}}}}},"400":{"description":"Request body failed Zod validation. `error.details` carries the field-level issues.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"403":{"description":"Viewer key attempting a write, or org is suspended, or feature is Pro-gated. `error.code` distinguishes: `FORBIDDEN` (role), `ORG_SUSPENDED`, `PLAN_LIMIT_EXCEEDED`.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"404":{"description":"Resource not found in the caller's organization.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"429":{"description":"Rate limit exceeded. See `Retry-After` header for wait time.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds until the limit resets."},"RateLimit-Limit":{"schema":{"type":"integer"}},"RateLimit-Remaining":{"schema":{"type":"integer"}},"RateLimit-Reset":{"schema":{"type":"integer"},"description":"Seconds until reset."}},"content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}}}}},"/surveys/{id}/close":{"post":{"tags":["Surveys"],"summary":"Close a survey to new responses","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","description":"Sqids-encoded identifier. Same value round-trips in and out of the API.","example":"NBHUAdng"},"description":"Sqids-encoded survey ID."}],"responses":{"200":{"description":"Closed","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/Survey"}}}}}},"400":{"description":"Request body failed Zod validation. `error.details` carries the field-level issues.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"403":{"description":"Viewer key attempting a write, or org is suspended, or feature is Pro-gated. `error.code` distinguishes: `FORBIDDEN` (role), `ORG_SUSPENDED`, `PLAN_LIMIT_EXCEEDED`.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"404":{"description":"Resource not found in the caller's organization.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"429":{"description":"Rate limit exceeded. See `Retry-After` header for wait time.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds until the limit resets."},"RateLimit-Limit":{"schema":{"type":"integer"}},"RateLimit-Remaining":{"schema":{"type":"integer"}},"RateLimit-Reset":{"schema":{"type":"integer"},"description":"Seconds until reset."}},"content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}}}}},"/recipients/bulk":{"post":{"tags":["Recipients"],"summary":"Create many recipients at once","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkCreateRecipientsRequest"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"array","items":{"$ref":"#/components/schemas/Recipient"}}}}}}},"400":{"description":"Request body failed Zod validation. `error.details` carries the field-level issues.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"403":{"description":"Viewer key attempting a write, or org is suspended, or feature is Pro-gated. `error.code` distinguishes: `FORBIDDEN` (role), `ORG_SUSPENDED`, `PLAN_LIMIT_EXCEEDED`.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"404":{"description":"Resource not found in the caller's organization.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"429":{"description":"Rate limit exceeded. See `Retry-After` header for wait time.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds until the limit resets."},"RateLimit-Limit":{"schema":{"type":"integer"}},"RateLimit-Remaining":{"schema":{"type":"integer"}},"RateLimit-Reset":{"schema":{"type":"integer"},"description":"Seconds until reset."}},"content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}}}}},"/surveys/{id}/analyze":{"post":{"tags":["Responses"],"summary":"Trigger AI analysis on the collected responses","description":"Only for `survey_type=ai_insight`. Starts an asynchronous analysis job — poll `GET /surveys/{id}/insights` for status.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","description":"Sqids-encoded identifier. Same value round-trips in and out of the API.","example":"NBHUAdng"},"description":"Sqids-encoded survey ID."}],"responses":{"202":{"description":"Analysis job started.","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/AiAnalysis"}}}}}},"400":{"description":"Request body failed Zod validation. `error.details` carries the field-level issues.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"401":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"403":{"description":"Viewer key attempting a write, or org is suspended, or feature is Pro-gated. `error.code` distinguishes: `FORBIDDEN` (role), `ORG_SUSPENDED`, `PLAN_LIMIT_EXCEEDED`.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"404":{"description":"Resource not found in the caller's organization.","content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}},"429":{"description":"Rate limit exceeded. See `Retry-After` header for wait time.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds until the limit resets."},"RateLimit-Limit":{"schema":{"type":"integer"}},"RateLimit-Remaining":{"schema":{"type":"integer"}},"RateLimit-Reset":{"schema":{"type":"integer"},"description":"Seconds until reset."}},"content":{"application/json":{"schema":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorObject"}}}}}}}}}}}