REST API, webhooks, SSO, and SCIM - working examples, not placeholders.
Either generate a token from Panel → API Tokens, or trade your login credentials for one directly via POST /survey/api/v1/auth/token - both mint the same kind of token, listed and revocable in the panel either way. The password-grant endpoint doesn't work for accounts with MFA enabled; use the panel for those. Send the token as a bearer token on every other request. Requires a plan with API access.
GET /survey/api/v1/account
Your plan, granted capabilities, per-metric limits and current usage, and your effective API rate limit - the fastest way to see why a request just returned 403/422 instead of guessing.
Every write request (POST/PUT/DELETE) requires an Idempotency-Key header. Replaying the same key returns the original response instead of repeating the action - safe to retry after a timeout without creating duplicates. A response includes Idempotent-Replayed: true when it was served from cache rather than freshly executed.
GET /survey/api/v1/surveys
List your surveys. Supports page-based pagination by default. Pass ?use_cursor=1 for cursor pagination, and ?updated_since=2026-01-01T00:00:00Z to sync only what changed.
POST /survey/api/v1/surveys
Create a survey as a draft. Fields: title (required), description, type (free, subscription, or pay_per_response, required).
GET /survey/api/v1/surveys/{'{id}'} · PUT /survey/api/v1/surveys/{'{id}'}
Fetch a single survey with its questions, or update title/description/is_private/password (plus thank_you_message, thank_you_redirect_url, and closes_at when your plan includes those capabilities).
POST /survey/api/v1/surveys/{'{id}'}/publish
Publishes a survey. Returns 422 if it has no questions yet - add at least one with the Questions endpoints below first.
POST /survey/api/v1/surveys/{'{id}'}/close · DELETE /survey/api/v1/surveys/{'{id}'}
Stop accepting responses, or permanently delete the survey along with its questions, responses, and answers.
Full question CRUD - the piece that lets a survey created via the API actually reach a publishable state without touching the panel UI.
POST /survey/api/v1/surveys/{'{id}'}/questions
Fields depend on type: choice/ranking types take options[], matrix takes matrix_rows[]/matrix_columns[], slider takes slider_min/slider_max/slider_step. file_upload requires a plan with the file-upload-questions capability.
PUT /survey/api/v1/surveys/{'{id}'}/questions/{'{question_id}'} · DELETE /survey/api/v1/surveys/{'{id}'}/questions/{'{question_id}'}
Update or remove a question. The same field rules as creation apply to updates.
GET /survey/api/v1/surveys/{'{id}'}/responses · GET /survey/api/v1/surveys/{'{id}'}/responses/{'{response_id}'}
List completed responses with decoded answers (paginated 50 per page), or fetch one by id.
For large surveys, queue an export instead of waiting on a synchronous download.
POST /survey/api/v1/exports
GET /survey/api/v1/jobs/{'{id}'}
Poll until status is completed (or failed), then fetch download_url.
Register a URL to receive an HTTP POST the moment a respondent completes a survey. Requires a plan with the webhooks capability.
POST /survey/api/v1/webhooks
GET /survey/api/v1/webhooks · DELETE /survey/api/v1/webhooks/{'{id}'}
List or remove your webhooks.
Every delivery is signed with HMAC-SHA256 over the raw request body, sent in the X-Survey-Signature header. Verify it before trusting the payload:
SAML 2.0 and OpenID Connect SSO, plus SCIM 2.0 user/group provisioning, are configured per-organization from the panel rather than via this API - see the Security page for how each protocol is implemented. Your identity provider's own admin console is where you configure the connection; there's no separate developer setup needed beyond what's in the panel.
Errors return a JSON body with an error key and an appropriate HTTP status (401 missing/invalid token, 403 plan doesn't include this capability, 404 not found or not yours, 422 validation failure). Each plan has its own requests-per-minute rate limit (see GET /account for yours); every response carries X-RateLimit-Limit/X-RateLimit-Remaining, and exceeding it returns 429 with a Retry-After header.