FormalyFormaly
FeaturesWhyComparePricingBlog
Developers

Formaly REST API Reference

The Formaly REST API is versioned under `/api/v1` and authenticated with a Formaly API key. Base URL: `https://www.formaly.io/api/v1`. A machine-readable OpenAPI 3.1 description of everything on this page is published at [/openapi.json](/openapi.json).

› Developers

Endpoints

MethodPathScopeDescription
GET/api/v1/formsforms:readList forms, paginated
POST/api/v1/formsforms:writeCreate a form
GET/api/v1/forms/{id}forms:readRead one form, including its version
PATCH/api/v1/forms/{id}forms:writeUpdate a form
DELETE/api/v1/forms/{id}forms:writeDelete a form permanently
GET/api/v1/forms/{id}/schemaforms:readCanonical machine-readable form schema
GET/api/v1/forms/{id}/responsesanalytics:readList submitted responses, paginated
GET/api/v1/forms/{id}/analyticsanalytics:readCompletion, drop-off, and per-question stats
GET/api/v1/creditsforms:readCredit balance, cost table, and history

List forms

GET /api/v1/forms returns the authenticated account's forms, newest first.

curl "https://www.formaly.io/api/v1/forms?status=active&limit=50" \
  -H "Authorization: Bearer $FORMALY_API_KEY"
Query parameterTypeDefaultNotes
pageinteger ≥ 11Page number
limitinteger 1-10020Page size
statusdraft \| active \| closedallFilter by publication status

Create a form

POST /api/v1/forms creates a form from a structured script. Always send an `Idempotency-Key` so a retried request cannot create a duplicate.

title, prompt, and script are required. script.questions must contain at least one question; each question needs an id, a type (open, rating, multiple_choice, or nps), and a prompt.

curl -X POST https://www.formaly.io/api/v1/forms \
  -H "Authorization: Bearer $FORMALY_API_KEY" \
  -H "Idempotency-Key: 6f1c2b64-1c9e-4c3f-9d6a-3f3f8f1f7a11" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Onboarding feedback",
    "prompt": "Find out where new users get stuck in week one",
    "status": "active",
    "script": {
      "title": "Onboarding feedback",
      "opening": "Thanks for trying us out - two quick questions.",
      "questions": [
        { "id": "q1", "type": "open", "prompt": "What were you trying to do first?" },
        { "id": "q2", "type": "rating", "prompt": "How easy was setup?", "scale": 5 }
      ],
      "closing": "That is all - thank you."
    }
  }'

Read, update, and delete a form

GET /api/v1/forms/{id} returns the full form plus a version string. Pass that value back as expected_version on the next PATCH (or as an If-Match header) and the update is rejected with CONFLICT (409) if anything changed in between.

PATCH accepts any subset of title, description, prompt, script, status, collectContactInfo, defaultSurveyMode, and systemPrompt. Setting status to active publishes the form; closed stops accepting responses; draft unpublishes it.

DELETE /api/v1/forms/{id} is permanent and removes the form's responses with it. Confirm with a human before calling it.

curl -X PATCH https://www.formaly.io/api/v1/forms/$FORM_ID \
  -H "Authorization: Bearer $FORMALY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "status": "active", "expected_version": "3-1751414400000" }'

Form schema

GET /api/v1/forms/{id}/schema returns the canonical machine-readable description of a form: its fields, their types, their options, and their validation rules. This is the endpoint to use when you are rendering the form somewhere Formaly does not control - a Slack modal, a Discord thread, a CLI, or an agent constructing an answer set.

Responses and analytics

GET /api/v1/forms/{id}/responses lists submitted responses with page and limit query parameters, including structured answers and the conversation transcript where the respondent used chat mode.

GET /api/v1/forms/{id}/analytics returns aggregate performance: view and completion counts, completion rate, drop-off by question, and per-question breakdowns. Both require the analytics:read scope.

Credits

GET /api/v1/credits returns the current balance, lifetime totals, the cost table for every billable action, and - unless you pass history=false - recent transactions. Reads are free; generating a form costs credits. Check the balance before a batch of writes rather than discovering INSUFFICIENT_CREDITS (402) halfway through.

curl "https://www.formaly.io/api/v1/credits?history=false" \
  -H "Authorization: Bearer $FORMALY_API_KEY"
FormalyFormaly

Talk to build. Talk to answer.

© 2026 Formaly

AboutDocsBlogComparePrivacyTermsContact

Made by Arindam

Formaly