Public API
The Item to Form public API lets developers create and manage Item to Form forms with service tokens. The implemented public surface is the form management API at /v1/forms, served from the branded host https://i2f.prodactive-software.com/api/{region} where {region} is one of us, eu, au, il (matching the deployment that owns each form).
Authentication
Every public API request must include a service token in the Authorization header. Service tokens are created inside the authenticated Item to Form app and can expire after 30, 60, or 90 days, or be created without an expiration. A token is shown only once when it is created.
Authorization: Bearer fill_sk_live_...
Content-Type: application/jsonoauth_required.Common Fields
| Field | Type | Required | Meaning |
|---|---|---|---|
| target | item | board | Yes | Whether the form updates existing items or creates new board items. |
| form.columns | array | Yes on create | Column configuration. Each object requires id and can include validations, readonly, allowed people, linked item allowlists, and description. |
| form.settings | object | No | Form behavior: notification flag, editing after submit, password, message, and expiration. |
| conflictStrategy | skip | overwrite | No | Item-target creation behavior when an item already has a form. |
| mode | single_use | permanent | No | Board-target link mode. Defaults to permanent. |
Settings Fields
notifyOnSubmitboolean, optional, defaultfalse: send a monday.com notification when a form is submitted.allowEditingAfterSubmitboolean, optional, defaultfalse: allow the same link to submit updated answers.passwordstring or null, optional: set or clear password protection. Non-empty passwords must be at least 6 characters. Passwords are never returned by the API.customMessagestring or null, optional: message shown above the public form fields.expirationDateISO 8601 UTC string or null, optional: date after which the form stops accepting submissions.
Column Input Fields
idstring, required: monday.com column ID.validationsarray, optional: rules withoperatorandvalue. Operators include required, numeric comparisons, text checks, list inclusion, and date comparisons.readonlyboolean, optional: show the current monday value without allowing edits.allowedPeoplearray, optional: allowed People column choices, each withidandname.allowedLinkedItemIdsarray, optional: allowed item IDs for Connected Boards columns.descriptionstring, optional: helper text shown below the field label, up to 5,000 characters.
Response Shape
Successful public API responses wrap the payload in { "data": ... }. Form responses include:
id: Item to Form form ID.target:itemorboard.config.mode: returned for board forms only.form.settings: public-safe settings. Password values are never returned.form.columns: stored form columns with monday title and type metadata.formUrl: public form URL, ornullif the URL cannot be generated.acceptingSubmissions,createdAt, and optionalupdatedAt.
Usage & limits
Throttling for /v1/forms uses 60-second windows. Each request is counted per service token and per account, separately for reads (GET) and writes (POST / PATCH / DELETE). There is also a per client IP counter for the same routes. With default configuration every bucket is 60 requests per minute, so the documented ceiling is consistent whether you read the IP row or the token rows below.
| Limit | Scope | Default | Window |
|---|---|---|---|
Reads (GET) | Per service token and per account — aggregated across all callers using that token. | 60 requests / minute | 60 seconds |
Writes (POST / PATCH / DELETE) | Per service token and per account. | 60 requests / minute | 60 seconds |
| Extra: per client IP | All requests to /v1/forms from the same IP share one counter (reads and writes combined). Extra safeguard on top of token/account limits. | 60 requests / minute | 60 seconds |
Each request still has to satisfy every limit that applies (IP, token, and account). If your deployment raises one variable above another, those layers can diverge again — use the X-RateLimit-* headers on each response.
Response headers
Successful responses include rate-limit headers you can use to throttle:
| Header | Meaning |
|---|---|
| X-RateLimit-Limit | Your read or write budget for this request — the primary limit for tuning clients. |
| X-RateLimit-Auth-Limit | The additional per-IP layer budget for this window. |
| X-RateLimit-Window-Seconds | Window length — currently 60 seconds. |
When the limit is exceeded
Expect HTTP 429 Too Many Requests with rate_limited and a details.limit showing the cap that fired. When several buckets share the same number (often 60 under defaults), use the message: Public API authentication rate limit exceeded means the per-IP counter tripped; Public API rate limit exceeded means a token or account counter tripped.
{
"error": {
"code": "rate_limited",
"message": "Public API rate limit exceeded",
"details": {
"limit": 60,
"windowSeconds": 60
}
}
} X-RateLimit-* headers from your most recent response rather than hard-coding numbers into your client.POST /v1/forms
Create Forms
Create one or more Item to Form forms. Item targets can create up to 50 forms in one request. Board targets create one board-backed link.
Authentication
Required: Bearer service token.
Required headers
Authorization. Add Content-Type: application/json when sending a JSON body.
Path parameters
None
Query parameters
None
Request body
For target item: target, config.itemIds, optional config.conflictStrategy, form.columns, optional form.settings. For target board: target, config.boardId, optional config.mode, form.columns, optional form.settings.
Success response
200 OK with data.forms array.
Example request
curl -X POST "{{baseUrl}}/v1/forms" \
-H "Authorization: Bearer {{serviceToken}}" \
-H "Content-Type: application/json" \
-d '{
"target": "item",
"config": {
"itemIds": ["123456789"],
"conflictStrategy": "skip"
},
"form": {
"settings": {
"notifyOnSubmit": true,
"allowEditingAfterSubmit": false,
"customMessage": "Please confirm the details below.",
"expirationDate": "2026-06-01T00:00:00.000Z",
"password": "client-intake"
},
"columns": [
{
"id": "email",
"validations": [{ "operator": "required", "value": true }]
},
{
"id": "status",
"readonly": true,
"description": "Current project status"
}
]
}
}'Board-backed example
curl -X POST "{{baseUrl}}/v1/forms" \
-H "Authorization: Bearer {{serviceToken}}" \
-H "Content-Type: application/json" \
-d '{
"target": "board",
"config": {
"boardId": "987654321",
"mode": "permanent"
},
"form": {
"columns": [
{ "id": "name" },
{ "id": "email" },
{ "id": "status" }
]
}
}'Example success response
{
"data": {
"forms": [
{
"id": "65f1a6f8c2d1e9a123456789",
"target": "item",
"form": {
"settings": {
"notifyOnSubmit": true,
"allowEditingAfterSubmit": false,
"customMessage": "Please confirm the details below.",
"expirationDate": "2026-06-01T00:00:00.000Z"
},
"columns": [
{
"id": "email",
"title": "Email",
"type": "email",
"validations": [{ "operator": "required", "value": true }]
}
]
},
"formUrl": "https://...",
"acceptingSubmissions": true,
"createdAt": "2026-04-30T15:25:00.000Z",
"updatedAt": "2026-04-30T15:25:00.000Z"
}
]
}
}GET /v1/forms
List Forms
Return a paginated list of forms for the token account, newest first.
Authentication
Required: Bearer service token.
Required headers
Authorization. Add Content-Type: application/json when sending a JSON body.
Path parameters
None
Query parameters
page integer min 1 default 1; limit integer 1-100 default 10; itemId optional string; boardId optional string.
Request body
None
Success response
200 OK with data.forms and data.pagination.
Example request
curl "{{baseUrl}}/v1/forms?page=1&limit=10&boardId=987654321" \
-H "Authorization: Bearer {{serviceToken}}"Example success response
{
"data": {
"forms": [
{
"id": "65f1a6f8c2d1e9a123456789",
"target": "board",
"config": { "mode": "permanent" },
"form": {
"settings": {
"notifyOnSubmit": false,
"allowEditingAfterSubmit": false,
"customMessage": null,
"expirationDate": null
},
"columns": []
},
"formUrl": "https://...",
"acceptingSubmissions": true,
"createdAt": "2026-04-30T15:25:00.000Z"
}
],
"pagination": {
"page": 1,
"limit": 10,
"total": 1,
"totalPages": 1
}
}
}GET /v1/forms/:formId
Get a Form
Fetch one form by Item to Form form ID.
Authentication
Required: Bearer service token.
Required headers
Authorization. Add Content-Type: application/json when sending a JSON body.
Path parameters
formId string, Mongo ObjectId format.
Query parameters
None
Request body
None
Success response
200 OK with data.form.
Example request
curl "{{baseUrl}}/v1/forms/65f1a6f8c2d1e9a123456789" \
-H "Authorization: Bearer {{serviceToken}}"Example success response
{
"data": {
"form":
{
"id": "65f1a6f8c2d1e9a123456789",
"target": "item",
"form": {
"settings": {
"notifyOnSubmit": true,
"allowEditingAfterSubmit": false,
"customMessage": "Please confirm the details below.",
"expirationDate": "2026-06-01T00:00:00.000Z"
},
"columns": [
{
"id": "email",
"title": "Email",
"type": "email",
"validations": [{ "operator": "required", "value": true }]
}
]
},
"formUrl": "https://...",
"acceptingSubmissions": true,
"createdAt": "2026-04-30T15:25:00.000Z",
"updatedAt": "2026-04-30T15:25:00.000Z"
}
}
}PATCH /v1/forms/:formId
Update a Form
Update form settings, columns, or both. At least one of form.settings or form.columns is required.
Authentication
Required: Bearer service token.
Required headers
Authorization. Add Content-Type: application/json when sending a JSON body.
Path parameters
formId string, Mongo ObjectId format.
Query parameters
None
Request body
form object with optional settings and optional columns.
Success response
200 OK with data.form.
Example request
curl -X PATCH "{{baseUrl}}/v1/forms/65f1a6f8c2d1e9a123456789" \
-H "Authorization: Bearer {{serviceToken}}" \
-H "Content-Type: application/json" \
-d '{
"form": {
"settings": {
"allowEditingAfterSubmit": true,
"expirationDate": null
},
"columns": [
{
"id": "email",
"validations": [{ "operator": "required", "value": true }]
}
]
}
}'Example success response
{
"data": {
"form":
{
"id": "65f1a6f8c2d1e9a123456789",
"target": "item",
"form": {
"settings": {
"notifyOnSubmit": true,
"allowEditingAfterSubmit": false,
"customMessage": "Please confirm the details below.",
"expirationDate": "2026-06-01T00:00:00.000Z"
},
"columns": [
{
"id": "email",
"title": "Email",
"type": "email",
"validations": [{ "operator": "required", "value": true }]
}
]
},
"formUrl": "https://...",
"acceptingSubmissions": true,
"createdAt": "2026-04-30T15:25:00.000Z",
"updatedAt": "2026-04-30T15:25:00.000Z"
}
}
}PATCH /v1/forms/:formId/active
Pause or Resume a Form
Toggle whether a form accepts new submissions. Used-up single-use links cannot be reactivated.
Authentication
Required: Bearer service token.
Required headers
Authorization. Add Content-Type: application/json when sending a JSON body.
Path parameters
formId string, Mongo ObjectId format.
Query parameters
None
Request body
active boolean, required.
Success response
200 OK with data.form.
Example request
curl -X PATCH "{{baseUrl}}/v1/forms/65f1a6f8c2d1e9a123456789/active" \
-H "Authorization: Bearer {{serviceToken}}" \
-H "Content-Type: application/json" \
-d '{ "active": false }'Example success response
{
"data": {
"form":
{
"id": "65f1a6f8c2d1e9a123456789",
"target": "item",
"form": {
"settings": {
"notifyOnSubmit": true,
"allowEditingAfterSubmit": false,
"customMessage": "Please confirm the details below.",
"expirationDate": "2026-06-01T00:00:00.000Z"
},
"columns": [
{
"id": "email",
"title": "Email",
"type": "email",
"validations": [{ "operator": "required", "value": true }]
}
]
},
"formUrl": "https://...",
"acceptingSubmissions": true,
"createdAt": "2026-04-30T15:25:00.000Z",
"updatedAt": "2026-04-30T15:25:00.000Z"
}
}
}DELETE /v1/forms/:formId
Delete a Form
Delete an Item to Form form by ID.
Authentication
Required: Bearer service token.
Required headers
Authorization. Add Content-Type: application/json when sending a JSON body.
Path parameters
formId string, Mongo ObjectId format.
Query parameters
None
Request body
None
Success response
200 OK with deleted form ID and deletion timestamp.
Example request
curl -X DELETE "{{baseUrl}}/v1/forms/65f1a6f8c2d1e9a123456789" \
-H "Authorization: Bearer {{serviceToken}}"Example success response
{
"data": {
"formId": "65f1a6f8c2d1e9a123456789",
"deletedAt": "2026-04-30T15:30:00.000Z"
}
}Errors
Error responses use { "error": { "code", "message" } }and may include details. Implemented public API error codes include invalid_request, invalid_token, token_revoked, token_expired, oauth_required, rate_limited, quota_exceeded, form_not_found, target_not_accessible, conflict, and validation_failed.
{
"error": {
"code": "invalid_token",
"message": "Missing service token"
}
}{
"error": {
"code": "validation_failed",
"message": "Validation failed",
"details": [
{
"field": "form.columns",
"message": "At least one column is required"
}
]
}
}{
"error": {
"code": "conflict",
"message": "Some items already have active forms",
"details": {
"conflicts": ["123456789"]
}
}
}Postman collection
Import the collection, set baseUrl to https://i2f.prodactive-software.com/api/{region} (substituting your form's region), and set serviceToken to an Item to Form service token.