{"openapi":"3.1.0","info":{"title":"splitforms Form Submission API","version":"1.0.0","summary":"One HTTPS endpoint that receives HTML, fetch and server-side form submissions.","description":"POST any form to `/api/submit` with the form's `access_key`. splitforms validates the request, filters spam with rule-based checks, stores the submission and emails the form owner.\n\nPlans: Free is 500 submissions in total (one-time, no card). Pro is $5/month and Annual is $49/year. Paid plans add signed webhooks, integrations, exports and file uploads.\n\nRate limit: 6 submissions per minute and 20 per 15 minutes per IP, per form.\n\nFacts checked against the code on 2026-10-02.","termsOfService":"https://splitforms.com/terms","contact":{"name":"splitforms support","url":"https://splitforms.com/api-reference","email":"hello@splitforms.com"}},"externalDocs":{"description":"API reference with cURL, fetch, Python, PHP and Go examples","url":"https://splitforms.com/api-reference"},"servers":[{"url":"https://splitforms.com","description":"Production"}],"tags":[{"name":"Submissions","description":"Send form submissions to a splitforms form."}],"paths":{"/api/submit":{"post":{"operationId":"submitForm","summary":"Submit a form","description":"Send the form's `access_key` plus any fields. No Authorization header: the access key identifies the form and is public by design.\n\nThe response format follows the request. Requests with `Accept: application/json` or a JSON body, fetch requests, and clients that send no Accept header get JSON. A native HTML form post gets a hosted page, or a redirect when one is configured.\n\nFiles need multipart/form-data: up to 5 files of 5 MB each, stored on paid plans with Storage connected. On Free, text fields are saved, files are dropped and the JSON response carries a `note`.","tags":["Submissions"],"security":[],"requestBody":{"required":true,"description":"Accepted content types: application/x-www-form-urlencoded, multipart/form-data, application/json.","content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/SubmissionFields"}},"multipart/form-data":{"schema":{"$ref":"#/components/schemas/MultipartSubmission"}},"application/json":{"schema":{"$ref":"#/components/schemas/SubmissionFields"},"example":{"access_key":"YOUR_ACCESS_KEY","name":"Ada Lovelace","email":"ada@example.com","message":"Hello","botcheck":""}}}},"responses":{"200":{"description":"Submission accepted. JSON callers get `{ success: true, message }` plus `redirect`, `redirect_params`, `payment_url`, `note` or `files` when they apply.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"},"example":{"success":true,"message":"Submission received"}},"text/html":{"schema":{"type":"string","description":"Hosted thank-you page."}}}},"302":{"description":"Native HTML post on a form with a redirect URL set in the dashboard. Works on every plan.","headers":{"Location":{"description":"Where the browser is sent.","schema":{"type":"string"}}}},"303":{"description":"Native HTML post with a valid hidden `redirect` field, or a payment form sending the visitor to Stripe Checkout.","headers":{"Location":{"description":"Where the browser is sent.","schema":{"type":"string"}}}},"400":{"description":"The request could not be read. `invalid_body`: The body could not be parsed (empty or malformed JSON, or an unreadable form body). `missing_access_key`: No access_key field was sent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"message":"…","code":"invalid_body"}},"text/html":{"schema":{"type":"string","description":"Hosted error page, sent to native HTML form posts."}}}},"403":{"description":"The form refused the submission. `inactive_form`: The form owner turned the form off. `origin_not_allowed`: Strict origin protection is on and the request came from a domain that is not on the form's allowed list. `form_unavailable`: The form cannot accept submissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"message":"…","code":"inactive_form"}},"text/html":{"schema":{"type":"string","description":"Hosted error page, sent to native HTML form posts."}}}},"404":{"description":"Unknown form. `invalid_access_key`: No form has this access_key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"message":"…","code":"invalid_access_key"}},"text/html":{"schema":{"type":"string","description":"Hosted error page, sent to native HTML form posts."}}}},"413":{"description":"Request body too large. `payload_too_large`: The body is larger than 5 files of 5 MB plus form fields.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"message":"…","code":"payload_too_large"}},"text/html":{"schema":{"type":"string","description":"Hosted error page, sent to native HTML form posts."}}}},"415":{"description":"Unsupported Content-Type. `unsupported_content_type`: The Content-Type is missing or not URL-encoded, multipart or JSON.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"message":"…","code":"unsupported_content_type"}},"text/html":{"schema":{"type":"string","description":"Hosted error page, sent to native HTML form posts."}}}},"429":{"description":"Too many requests or no allowance left. There is no Retry-After header; wait about a minute before retrying a `rate_limited` response. `rate_limited`: More than 6 submissions a minute or 20 per 15 minutes from one IP to one form. `quota_reached`: The account's allowance is used: 500 submissions in total on Free, or the monthly cap on a paid plan.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"message":"…","code":"rate_limited"}},"text/html":{"schema":{"type":"string","description":"Hosted error page, sent to native HTML form posts."}}}},"500":{"description":"Server error. Some 500 responses carry no `code`. `profile_lookup_failed`: The form's account settings could not be read. Retry the request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"message":"…","code":"profile_lookup_failed"}},"text/html":{"schema":{"type":"string","description":"Hosted error page, sent to native HTML form posts."}}}}}},"options":{"operationId":"submitFormPreflight","summary":"CORS preflight","description":"Answers browser preflight requests so the endpoint can be called with fetch from any origin.","tags":["Submissions"],"security":[],"responses":{"204":{"description":"CORS headers, no body."}}}}},"components":{"schemas":{"SubmissionFields":{"type":"object","required":["access_key"],"properties":{"access_key":{"type":"string","description":"The form's public identifier, copied from the dashboard. Safe to embed in client-side HTML; it is not a secret."},"subject":{"type":"string","description":"Subject line of the owner notification email."},"replyto":{"type":"string","format":"email","description":"Reply-to address on the notification email."},"from_name":{"type":"string","description":"Sender name shown on the notification email."},"redirect":{"type":"string","format":"uri-reference","description":"Thank-you page. Native HTML posts get a 303 to it; JSON callers get it back as `redirect`."},"name":{"type":"string","description":"Name of the person submitting the form."},"email":{"type":"string","format":"email","description":"Email address of the person submitting the form."},"message":{"type":"string","description":"Message body of the form submission."},"botcheck":{"type":"string","description":"Honeypot field to trap bots; leave empty."},"files":{"type":"array","items":{"type":"string","format":"uri"},"description":"Array of URLs to uploaded files (paid plans only)."}}},"MultipartSubmission":{"type":"object","properties":{"access_key":{"type":"string"},"subject":{"type":"string"},"replyto":{"type":"string","format":"email"},"from_name":{"type":"string"},"redirect":{"type":"string","format":"uri-reference"},"name":{"type":"string"},"email":{"type":"string","format":"email"},"message":{"type":"string"},"botcheck":{"type":"string"},"files":{"type":"array","items":{"type":"string","format":"uri"}}}},"SuccessResponse":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"},"redirect":{"type":"string"},"redirect_params":{"type":"object"},"payment_url":{"type":"string"},"note":{"type":"string"},"files":{"type":"array","items":{"type":"string"}}}},"ErrorResponse":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"},"code":{"type":"string"}}}}}}