Table of contents
The IvyForms REST API lets you list forms, read their fields, pull entries, and submit new ones from your own scripts or applications.
These endpoints require either the Agency or Elite plan and a valid API key with the right scope. For setup, see How to use the REST API feature in IvyForms.
All endpoints share the same base path, and only the endpoint part changes:
{site}/wp-json/ivyforms-public/v1
Every request also needs the X-IvyForms-Api-Key header described in the setup documentation.
If your site doesn’t use pretty permalinks, you can reach the same endpoints through the query-string form instead: {site}/?rest_route=/ivyforms-public/v1/forms.
You can list every form on your site by sending a GET request to /forms, using a key with the read scope.
Method: GET
Endpoint: /forms
1
2
curl --location '{site}/wp-json/ivyforms-public/v1/forms' \
--header 'X-IvyForms-Api-Key: YOUR_API_KEY'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
{
"data": [
{
"id": 71,
"name": "Contact form",
"fields": [
{
"id": 4,
"type": "email",
"fieldIndex": 0,
"label": "Email",
"required": true
},
{
"id": 5,
"type": "textarea",
"fieldIndex": 1,
"label": "Message",
"required": false
}
]
}
]
}
You can fetch one form, including its full field list, by sending a GET request to /forms/{form_id}, using a key with the read scope.
Method: GET
Endpoint: /forms/{form_id}
1
2
curl --location '{site}/wp-json/ivyforms-public/v1/forms/71' \
--header 'X-IvyForms-Api-Key: YOUR_API_KEY'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{
"id": 71,
"name": "Contact form",
"fields": [
{
"id": 4,
"type": "email",
"fieldIndex": 0,
"label": "Email",
"required": true
},
{
"id": 5,
"type": "textarea",
"fieldIndex": 1,
"label": "Message",
"required": false
}
]
}
You can list every entry submitted on a form by sending a GET request to /forms/{form_id}/entries, using a key with the read scope.
Method: GET
Endpoint: /forms/{form_id}/entries
1
2
curl --location '{site}/wp-json/ivyforms-public/v1/forms/71/entries' \
--header 'X-IvyForms-Api-Key: YOUR_API_KEY'
1
2
3
4
5
6
7
8
9
10
11
12
13
{
"data": [
{
"id": 132,
"form_id": 71,
"submitted_at": "2026-07-14 10:32:00",
"values": {
"4": "[email protected]",
"5": "Hi, I'd like a quote."
}
}
]
}
You can fetch one entry by sending a GET request to /entries/{entry_id}, using a key with the read scope.
Method: GET
Endpoint: /entries/{entry_id}
1
2
curl --location '{site}/wp-json/ivyforms-public/v1/entries/7' \
--header 'X-IvyForms-Api-Key: YOUR_API_KEY'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
{
"entry": {
"id": 7,
"formId": 7,
"userId": 1,
"author": "root",
"dateCreated": "2026-07-21 12:29:44",
"dateEdited": "2026-07-21 12:29:53",
"status": "read",
"ipAddress": "",
"userAgent": "Google Chrome",
"sourceURL": "{site}/?ivyforms_preview=7&_wpNonce=849532fd45",
"starred": false,
"lifecycleStatus": "draft",
"expiresAt": "2026-08-20 12:29:44",
"draftMeta": "{\"currentPageId\":\"page_1\",\"completedPages\":[]}",
"hasResumeToken": true
},
"fields": [
{ "id": "65", "entryId": "7", "fieldId": "75", "fieldValue": "iva" },
{ "id": "66", "entryId": "7", "fieldId": "76", "fieldValue": "2" },
{ "id": "67", "entryId": "7", "fieldId": "77", "fieldValue": "" }
]
}
The response has two parts: an entry object with metadata, and a fields array with the actual submitted values.
Each item in fields links a fieldId to its fieldValue, always returned as a string, even for numeric or single-choice fields.
You can create a new entry by sending a POST request to /forms/{form_id}/submissions, with field values keyed by field ID.
A key with the submit scope can post entries directly. Without that scope, submissions still work if you include a valid form render nonce instead, the same way an embedded form would submit.
Method: POST
Endpoint: /forms/{form_id}/submissions
Required properties:
1
2
3
4
5
6
7
8
9
10
11
curl --location '{site}/wp-json/ivyforms-public/v1/forms/1/submissions' \
--header 'X-IvyForms-Api-Key: YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"values": {
"1": "Jane Doe",
"2": "[email protected]",
"6": "Hi, I would like a quote.",
"25": "0"
}
}'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
"data": {
"success": true,
"entry": {
"stored": true,
"id": 8
},
"confirmation": "Thanks for reaching out! We've received your message and will get back to you shortly.",
"confirmationResult": {
"id": 1,
"type": "successMessage",
"message": "Thanks for reaching out! We've received your message and will get back to you shortly.",
"showForm": false,
"url": "",
"pageUrl": "",
"isDefault": true
}
}
}
confirmationResult mirrors whatever confirmation is configured on the form itself. This example shows a success message; a form configured to redirect after submission would likely return a different type with url or pageUrl populated instead.
If you’re building an integration on top of these endpoints, test on a staging site first and log both requests and responses while you build.
turnstile_{fieldIndex}; there’s no way to bypass it through the API.