דלג לתוכן מרכזי

Developer docs · Reference

Formy REST API: tokens, abilities, endpoints and errors

Formy's REST API lives at https://formy.co.il/api. You authenticate with a personal access token from your account settings, and each token carries abilities that decide exactly which routes it can call: forms, workspaces, form integrations such as webhooks, and the automation endpoints. API access is part of every plan, Free included.

Responses are the exception. No token can read, export or delete submissions: those routes answer 404 to a token whatever its abilities. To get each response into your system, add a webhook, which Formy calls the moment a response is completed.

Base URL
https://formy.co.il/api
Auth
Authorization: Bearer <token>
Format
JSON in and out
Plans
Every plan, Free included
Rate limits
600 a minute per endpoint on /open, 60 a minute in all on /external
Responses
Not readable by token; use a webhook
By , CTO of FormyPublished Updated

Written with AI assistance and checked against the product on . Approved for publication by Tomer Gal, CTO of Formy. How we write and approve content (Hebrew)

Base URL and request format

Every endpoint on this page is relative to https://formy.co.il/api. Send and accept JSON: set Accept: application/json and, on requests with a body, Content-Type: application/json. There is no version segment in the path.

The API has two groups of routes:

  • /open/..., the product's own API: workspaces, forms and form integrations. A token reaches only the routes listed under [abilities](#abilities).
  • /external/..., small, stable endpoints for automation platforms and scripts: validate a token, list workspaces, forms and fields, subscribe a Make webhook, and send a document for signature. They are documented on Automation endpoints and Signing requests.

Where a path has {form}, you can pass the form's numeric ID or its slug (the last part of its public link, formy.co.il/forms/<slug>). {workspace} is the workspace's numeric ID.

Personal access tokens

A personal access token acts as the person who created it, in every workspace that person belongs to. Abilities narrow what the token may do; the person's role in each workspace still applies on top, so a token belonging to a read-only member cannot edit anything in that workspace.

Create a token

  1. In Formy, open your account settings and the גישה ל-API tab.
  2. Click יצירת API Access Token חדש.
  3. Give it a name under שם that says what will use it, such as CRM sync.
  4. Under הרשאות, keep only what that integration needs. All five abilities are ticked when the dialog opens.
  5. Click יצירת API Access Token and copy the token with העתקת ה-Token. It is shown once.

The same tab lists your tokens with their abilities and deletes them. A deleted token stops working at once and answers 401. Tokens do not expire on their own, so delete the ones you no longer use and keep a separate token for each integration.

Send it

curl https://formy.co.il/api/external/validate \
  -H "Authorization: Bearer $FORMY_TOKEN" \
  -H "Accept: application/json"
{
  "name": "Dana Cohen",
  "email": "dana@example.com"
}
200 OK: the token is valid, and this is the account it acts for.

A token is its number, a |, and 48 letters and digits, such as 123| followed by the rest. Store it as a secret: anyone who has it can do everything its abilities allow, as you.

Abilities and the routes each one opens

Formy decides access per route. Each route a token can call needs one ability, either of two, or both of two, as listed below. A token without the ability gets 403. A route that is not on this list answers 404 to every token, so that a token cannot discover what exists.

Abilities a token can have, and their name in the token dialog
AbilityName in the dialogWhat it opens
forms-readטפסים - קריאהRead forms and their definitions, list a workspace's forms and fields. Never responses.
forms-writeטפסים - כתיבהCreate and update forms, publish or unpublish, rename, restore from the trash, and send documents for signature. Never delete.
manage-integrationsניהול אינטגרציותCreate, change, pause and delete a form's integrations, read their delivery history, subscribe Make hooks. Also reads the form itself.
workspaces-readסביבת עבודה - קריאהList your workspaces and their members.
workspaces-writeסביבת עבודה - כתיבהCreate and rename workspaces, and list pending invitations (workspace admins).

Older tokens may also carry workspace-users-read or workspace-users-write. No route checks either one, and the dialog no longer offers them.

Workspaces

Workspace routes a token can call
RouteAbilityWhat it does
GET /open/workspacesworkspaces-readList the workspaces you belong to, with their members and roles.
POST /open/workspaces/createworkspaces-writeCreate a workspace, within your plan's workspace limit.
PUT /open/workspaces/{workspace}workspaces-writeRename a workspace and set its icon. Not open to read-only members.
GET /open/workspaces/{workspace}/usersworkspaces-readList a workspace's members.
GET /open/workspaces/{workspace}/invitesworkspaces-writeList pending invitations. Workspace admins only.

Forms

Form routes a token can call
RouteAbilityWhat it does
GET /open/formsforms-readEvery form in every workspace you belong to, in one list.
GET /open/workspaces/{workspace}/formsforms-readOne workspace's forms, paginated, with search and filters.
GET /open/workspaces/{workspace}/forms/trashedworkspaces-read and forms-readForms in the workspace's trash.
GET /open/forms/{form}forms-read or manage-integrationsOne form's full definition, with its revision and ETag.
POST /open/formsforms-writeCreate a form from a definition.
PUT /open/forms/{form}forms-writeReplace a form's definition. Needs the revision you read.
POST /open/forms/{slug}/restoreforms-writeTake a form out of the trash.
GET /open/dashboard/formsforms-readThe dashboard's form list for one workspace, 10 a page.
PATCH /open/dashboard/forms/{form}/visibilityforms-writePublish a form or turn it back into a draft.
PATCH /open/dashboard/forms/{form}/renameforms-writeRename a form.

Form integrations

Integration routes a token can call
RouteAbilityWhat it does
GET /open/forms/{form}/integrationsmanage-integrationsA form's integrations, each with its last delivery.
POST /open/forms/{form}/integrationsmanage-integrationsAdd an integration, such as a webhook.
PUT /open/forms/{form}/integrations/{integration}manage-integrationsChange an integration's settings.
PUT /open/forms/{form}/integrations/{integration}/statusmanage-integrationsPause or resume an integration.
DELETE /open/forms/{form}/integrations/{integration}manage-integrationsDelete an integration.
GET /open/forms/{form}/integrations/{integration}/eventsmanage-integrationsAn integration's delivery history.

Automation endpoints

Automation routes a token can call
RouteAbilityWhat it does
GET /external/validateany tokenCheck that a token is valid; answers with its owner's name and email.
GET /external/workspacesworkspaces-readYour workspaces, as {id, name, label, value}.
GET /external/formsforms-readThe forms of one workspace (workspace_id), as {id, name, label, value, slug, visibility}.
GET /external/forms/{form}/fieldsforms-readA form's answerable fields: id, name, type, required, hidden.
POST /external/forms/{form}/signing-requestsforms-writeSend one filled-in document to one person for signature.
POST /external/make/webhookmanage-integrationsSubscribe a Make webhook URL to a form.
DELETE /external/make/webhookmanage-integrationsUnsubscribe it.
GET /external/make/submissions/recentmanage-integrationsOne sample delivery for field mapping.
GET /external/zapier/validateany tokenLegacy copy of /external/validate.
GET /external/zapier/workspacesworkspaces-readLegacy copy of /external/workspaces.
GET /external/zapier/formsforms-readLegacy copy of /external/forms.
POST /external/zapier/webhookmanage-integrationsLegacy: subscribe a Zapier hook.
DELETE /external/zapier/webhookmanage-integrationsLegacy: unsubscribe it.
GET /external/zapier/submissions/recentmanage-integrationsLegacy: recent submissions for Zapier's polling test.

What a token cannot do

These operations exist in the product but only for a person signed in to Formy in a browser. A token gets 404 for each of them, even with every ability. That is deliberate, but it means a 404 here is about permission, not a typo in the path.

  • Read, list, update or delete responses (submissions)
  • Export responses, and poll an export's status
  • A response's PDF or file links
  • Delete a form, empty the trash, duplicate a form or move it to another workspace
  • Delete or leave a workspace
  • Add or remove members, change a role, resend or cancel an invitation
  • Contacts, bulk send, signing-round controls, folders, statistics and the response summary

To get responses into another system, use a webhook (every completed response, signed, retried for a day), Make or Google Sheets. To download them yourself, export from the responses table: see responses and exports.

Workspaces

GET /open/workspaces lists every workspace you belong to, with its members and their roles. GET /external/workspaces returns the short form an automation dropdown needs; see Automation endpoints.

curl https://formy.co.il/api/open/workspaces \
  -H "Authorization: Bearer $FORMY_TOKEN" -H "Accept: application/json"

To create one, POST /open/workspaces/create with a name (required) and an optional emoji for its icon. Your plan sets how many workspaces you can have; over the limit the call answers with a [plan-limit error](#errors). PUT /open/workspaces/{workspace} takes the same two fields and replaces both, so send the emoji again if you want to keep it.

curl -X POST https://formy.co.il/api/open/workspaces/create \
  -H "Authorization: Bearer $FORMY_TOKEN" -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"name": "Clinic intake"}'

Forms

GET /open/forms returns every form in every workspace you belong to, in one unpaginated list. For one workspace, GET /open/workspaces/{workspace}/forms is paginated and accepts:

Query parameters of GET /open/workspaces/{workspace}/forms
ParameterValues
pagePage number, from 1.
per_pageForms per page: 10 by default, 100 at most.
searchText in the form's title, up to 200 characters.
statusall (default), public or draft.
sortrecent (default), created or submissions.
folder_id, tag, favoriteNarrow to a folder, a tag, or your favourites.

GET /open/forms/{form} returns the whole definition: settings, properties (the fields, each with its id, type and name), definition_revision and etag. A token with only manage-integrations can read it too, so an integration can look up the form it serves.

Create and update

POST /open/forms creates a form from a definition. It needs workspace_id, title and properties, plus the presentation settings the editor saves (visibility, language, theme, presentation_style, width, size, border_radius, dark_mode, color, uppercase_labels, no_branding, transparent_background). The definition format is the editor's own, so the reliable way to build one is to read a form you made in the editor and change it.

PUT /open/forms/{form} replaces the definition. Send the whole definition back with the expected_revision you read, or an If-Match header with its ETag; see [revisions](#revisions). Plan limits apply exactly as in the editor: a setting your plan does not include is removed rather than saved, and the response lists what was removed under plan_strip_warnings. The response also carries the new definition_revision and etag.

Smaller writes have their own routes: PATCH /open/dashboard/forms/{form}/visibility with visibility (public or draft) and PATCH /open/dashboard/forms/{form}/rename with title, both with expected_revision. POST /open/forms/{slug}/restore takes a form out of the trash. Deleting a form is not available to tokens.

Form integrations and webhooks by API

Everything on a form's אינטגרציות tab is an integration: email, Slack, Google Sheets, a webhook and the rest. With manage-integrations you can manage them by API. A webhook is the one most often created by code:

curl -X POST https://formy.co.il/api/open/forms/service-agreement/integrations \
  -H "Authorization: Bearer $FORMY_TOKEN" -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
    "integration_id": "webhook",
    "status": "active",
    "data": {
      "webhook_url": "https://example.com/hooks/formy",
      "webhook_secret": "a-long-random-secret-value",
      "webhook_headers": { "X-Api-Key": "your-own-key" }
    },
    "logic": null
  }'

status is active or inactive. logic holds the conditions under which the integration runs, the same ones as מתי האינטגרציה תרוץ? in the product; null runs it on every response. The webhook's own rules (HTTPS only, a public address, a secret of at least 12 characters, at most 10 custom headers) are on the webhooks page.

The response, and GET .../integrations, return each integration with its settings, including the webhook's secret and custom headers. Treat a token with manage-integrations as able to read them.

PUT .../integrations/{integration} changes the settings with the same body, PUT .../integrations/{integration}/status pauses or resumes it, and DELETE removes it. GET .../integrations/{integration}/events returns its delivery history, the same list the product shows under אירועים קודמים.

Revisions: never overwrite someone else's change

Every saved form has a definition_revision, a number that goes up on each save, and an etag built from it. A write that changes a form must say which revision it was based on, as expected_revision in the body or as If-Match: <etag>. If both are sent, they must agree.

Revision outcomes
StatusWhen
428No revision was sent. Read the form first.
412The form changed since you read it. Nothing was saved; the response carries the current definition_revision and etag. Read it again, re-apply your change, and retry.
422The revision is malformed, or the body and the header disagree.

Creating a form needs no revision; the response carries the first one. A signing request also checks the revision, as expected_form_revision, so a document is never sent from a form that changed under you.

Errors

Errors are JSON with a message, in Hebrew except for the missing-ability 403. Validation errors (422) add an errors object keyed by field, and revision errors add a code.

Status codes the API returns
StatusMeaningWhat to do
401No token, an unknown token, or a deleted one.Send Authorization: Bearer <token>, or create a new token.
403The token lacks the ability the route needs, your role in the workspace does not allow it, or a plan limit was reached ("type": "plan_limit").Check the ability table; for a plan limit, read code and target_plan.
404The route is not open to tokens, the form or workspace does not exist, or it is not in your workspaces.Check the route is in the ability table, then the ID or slug.
412The form changed since the revision you sent.Read it again and retry.
422The body did not pass validation.Read errors.
428A write needs a revision and none was sent.Send expected_revision or If-Match.
429Rate limited.Wait for Retry-After seconds.
5xxA failure on Formy's side.Retry later with backoff.
{
  "message": "נדרשת התחברות."
}
401 for a request with no valid token, as production answered on 17 October 2026. The message means "Login required."
{
  "message": "Invalid ability provided."
}
403 for a token without the ability the route needs. This one message is in English.
{
  "message": "המשאב המבוקש לא נמצא."
}
404 for a route that is not open to tokens, or a form outside your workspaces ("The requested resource was not found.").
{
  "type": "plan_limit",
  "code": "workspaces",
  "feature": "workspaces",
  "limit": 1,
  "current": 1,
  "target_plan": "pro",
  "message": "…",
  "context": null
}
403 when a plan limit blocks the action: here a second workspace on a plan that includes one. code names the limit and target_plan the cheapest plan that lifts it.

Rate limits

Limits are counted per person (all of a person's tokens together) and per minute:

Rate limits of the API on formy.co.il
RoutesLimit
/external/...60 requests a minute across all of them
/open/...600 requests a minute for each method and route
POST /open/workspaces/create10 a minute
PATCH /open/dashboard/forms/{form}/visibility and /rename60 a minute

Responses carry X-RateLimit-Limit and X-RateLimit-Remaining. Over the limit you get 429 with Retry-After, the seconds to wait. The MCP server has its own limits.

Questions developers ask

Does the Formy API cost extra, or need a paid plan?

No. Tokens, the API, webhooks and the automation endpoints are on every plan, Free included. What the API does still counts against your plan: a document sent for signature uses your signed-document quota, and a new workspace counts against your workspace limit.

How do I read submissions with the API?

You can't with a token: every submission route answers 404 to one. Add a webhook to the form, and Formy posts each completed response to your server as it arrives, signed and retried for up to a day. For a one-off download, export from the responses table in the product.

Why does my token get 404 on a route that exists?

Because only the routes in the ability table are open to tokens, and every other route answers 404 to a token, so it cannot discover what exists. Check the route is in the table; if it is, check the form or workspace belongs to the token's owner.

Is there an OpenAPI specification or an SDK package?

Not a published one. This reference is the specification, checked against the code; the routes take plain JSON over HTTPS, so any HTTP client works. For embedding forms there is a JavaScript SDK served from formy.co.il.

Can I use OAuth instead of a personal token?

Not for the REST API, which takes personal access tokens only. OAuth is how AI assistants connect to the MCP server, which is a separate endpoint and does not accept API tokens.

Every page of the docs is listed in Formy developer docs .

Try it on a free account

Every plan includes the API, webhooks, the embed SDK and the MCP server, Free included.

Create a free account