Inbound
Web forms
Keep your own form design and still use Nextora’s form engine. Post submissions to a Nextora form: it validates them, stores them, creates a lead and runs the form’s automations — without an API key in your web page.
- Auth
- None — public endpoint
- CORS
- Any origin
- Plan
- Every plan
- Build the form in Nextora: its fields, required answers, what it creates (a lead by default; or a contact, a task, or nothing) and how answers map to record fields. Activate it.
- Fetch its definition once for the field IDs.
- From your page or server, submit the answers keyed by field ID.
| Field type | Answer |
|---|---|
text, textarea, email, phone, hidden | A string. Emails and phone numbers are validated. |
number, rating, scale, nps | A number within the field’s range. |
date | A string, YYYY-MM-DD. |
checkbox | true or false. |
dropdown, radio | One option value from the definition. |
multiselect | An array of option values. |
address | An object with street, line2, city, region, postal_code and country. |
file, booking, signature | Use the hosted form or its embed: they need an upload or a booking step. |
The endpoint accepts requests from any origin, so a static site can post to it directly. Name your inputs after the field IDs and send them as data:
<form id="contact">
<input name="1c3e5a7b-9d1f-4b3d-8e5f-7a9c1e3b5d10" required placeholder="Full name">
<input name="3e5a7c9d-1f3b-4d5f-9a7b-9c1e3a5d7f21" type="email" required placeholder="Work email">
<button>Send</button>
</form>
<script type="module">
const form = document.querySelector('#contact');
form.addEventListener('submit', async event => {
event.preventDefault();
const response = await fetch('https://acme.nextora.co/api/forms/e3f5a7c9-1b3d-4f5a-8c7e-9b1d3f5a7c08/submit', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
data: Object.fromEntries(new FormData(form)),
request_id: crypto.randomUUID(),
source_url: location.href,
}),
});
form.replaceChildren(response.ok ? 'Thanks — we will be in touch.' : 'Something went wrong. Please try again.');
});
</script>- Each form accepts 10 submissions a minute from one IP address; more are refused with
429and aRetry-Afterheader. - When the form uses reCAPTCHA v3 or hCaptcha, send the widget’s token as
captcha_token; without it the submission is refused withcaptcha_required. - Password-protected forms need the access token from their unlock step in the
X-Form-Accessheader. - Answers may total up to 500 KB.
GET/api/forms/{form_id}
Public. Only active forms are returned.
Returns the form’s title, description and fields — with the IDs to key answers by — plus its public settings and branding.
Path parameters
The form’s ID, from its share link or embed code.
Returns
The form definition, not wrapped in data. 404 when the form does not exist or is not active.
curl https://acme.nextora.co/api/forms/e3f5a7c9-1b3d-4f5a-8c7e-9b1d3f5a7c08{
"id": "e3f5a7c9-1b3d-4f5a-8c7e-9b1d3f5a7c08",
"title": "Talk to sales",
"description": "Tell us about your team and we will be in touch within a working day.",
"fields": [
{
"id": "1c3e5a7b-9d1f-4b3d-8e5f-7a9c1e3b5d10",
"type": "text",
"label": "Full name",
"required": true,
"position": 0
},
{
"id": "3e5a7c9d-1f3b-4d5f-9a7b-9c1e3a5d7f21",
"type": "email",
"label": "Work email",
"required": true,
"position": 1
},
{
"id": "5a7c9e1f-3b5d-4f7a-8b9d-1e3a5c7f9b32",
"type": "text",
"label": "Company",
"required": false,
"position": 2
},
{
"id": "7c9e1a3b-5d7f-4a9c-9d1f-3a5c7e9b1d43",
"type": "dropdown",
"label": "Team size",
"required": false,
"position": 3,
"options": [
{
"value": "1-10",
"label": "1–10"
},
{
"value": "11-50",
"label": "11–50"
},
{
"value": "51+",
"label": "51 or more"
}
]
},
{
"id": "9e1a3c5d-7f9b-4c1e-8f3a-5c7e9a1d3f54",
"type": "textarea",
"label": "What do you want to improve?",
"required": false,
"position": 4
}
],
"is_active": true
}POST/api/forms/{form_id}/submit
Public. Requests from browsers on any origin are allowed.
Validates the answers, stores the submission, creates the record the form is set up to create, and runs its automations — the same as a submission of the hosted form.
Path parameters
The form’s ID.
Body parameters
Answers keyed by field
id, in the formats above.- request_iduuid
Makes retries safe: a repeat with the same ID and answers returns the first receipt with
replayed: true; different answers are409 submission_conflict. - source_urlstring
The page the form was on.
- captcha_tokenstring
The CAPTCHA token, when the form uses one.
- gclidstring
Ad click IDs for conversion tracking:
gclid,gbraid,wbraidandfbclidare accepted.
Returns
A receipt with the submission ID and the records created.
curl -X POST https://acme.nextora.co/api/forms/e3f5a7c9-1b3d-4f5a-8c7e-9b1d3f5a7c08/submit \
-H "Content-Type: application/json" \
-d '{
"data": {
"1c3e5a7b-9d1f-4b3d-8e5f-7a9c1e3b5d10": "Grace Whitfield",
"3e5a7c9d-1f3b-4d5f-9a7b-9c1e3a5d7f21": "[email protected]",
"5a7c9e1f-3b5d-4f7a-8b9d-1e3a5c7f9b32": "Harbor Logistics",
"7c9e1a3b-5d7f-4a9c-9d1f-3a5c7e9b1d43": "11-50",
"9e1a3c5d-7f9b-4c1e-8f3a-5c7e9a1d3f54": "One queue for customer email and WhatsApp."
},
"request_id": "2f4a6c8e-0b2d-4f6a-8c0e-2b4d6f8a0c13",
"source_url": "https://www.example.com/contact"
}'{
"success": true,
"submission_id": "8b0d2f4a-6c8e-4a0b-9d2f-4a6c8e0b2d35",
"created_entity_type": "lead",
"created_entity_id": "a7c9e1b3-5f2d-4a6c-8e9b-2d4f6a8c0e13",
"lead_id": "a7c9e1b3-5f2d-4a6c-8e9b-2d4f6a8c0e13",
"contact_id": null,
"task_id": null,
"request_id": "2f4a6c8e-0b2d-4f6a-8c0e-2b4d6f8a0c13"
}Form errors carry a code, often a readable error, and field_id when one answer is the problem:
| Status | code | Meaning |
|---|---|---|
400 | invalid_answer | An answer is missing or invalid; field_id says which. |
400 | captcha_required, captcha_failed | Send a valid CAPTCHA token. |
404 | — | The form does not exist or is not active. |
409 | submission_conflict | The request_id was used with different answers. |
409 | form_changed | The form changed during the submission; fetch it again. |
429 | rate_limited | Too many submissions; wait for Retry-After seconds. |
503 | submission_unavailable | Try again shortly. |