Form Submission Endpoint
The form submission endpoint accepts data from your frontend forms.
Endpoint
POST /f/{form_id}Each form has a unique form_id (e.g., abc123xyz). Find it in your form settings.
Request Formats
JSON (recommended for JavaScript)
curl -X POST https://atlasforms.app/f/abc123xyz \
-H "Content-Type: application/json" \
-d '{"name": "John", "email": "john@example.com"}'Form URL-encoded (HTML forms)
curl -X POST https://atlasforms.app/f/abc123xyz \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "name=John&email=john@example.com"Multipart Form Data (with file uploads)
curl -X POST https://atlasforms.app/f/abc123xyz \
-F "name=John" \
-F "email=john@example.com" \
-F "attachment=@document.pdf"Response Formats
JSON Response (default for AJAX)
When Accept: application/json or Content-Type: application/json:
{
"success": true,
"submission_id": "550e8400-e29b-41d4-a716-446655440000",
"files": [
{
"id": "file-uuid",
"filename": "document.pdf",
"type": "application/pdf",
"size": 102400
}
]
}Redirect Response (HTML forms)
For standard HTML form submissions, users are redirected to:
Query parameters are appended:
https://yoursite.com/thank-you?submission_id=xxx&status=successSuccess Redirect
Configure a redirect URL in your form settings:
The redirect includes:
submission_id - The unique submission IDstatus - Always successfiles - Number of uploaded files (if any)webhook - delivered or pending (if webhook confirmation enabled)Spam Protection
Honeypot Fields
Add hidden honeypot fields to catch bots:
<form action="https://atlasforms.app/f/abc123xyz" method="POST">
<!-- Honeypot - hide with CSS -->
<input type="text" name="_gotcha" style="display:none" tabindex="-1" autocomplete="off">
<!-- Real fields -->
<input type="text" name="name" required>
<input type="email" name="email" required>
<button type="submit">Send</button>
</form>If _gotcha or _honeypot contains a value, the submission is silently rejected (bots fill all fields).
Turnstile CAPTCHA
Enable Cloudflare Turnstile in form settings for additional protection:
<form action="https://atlasforms.app/f/abc123xyz" method="POST">
<input type="text" name="name" required>
<input type="email" name="email" required>
<!-- Turnstile widget -->
<div class="cf-turnstile" data-sitekey="your-site-key"></div>
<button type="submit">Send</button>
</form>
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>Reserved Fields
These field names are reserved and automatically stripped:
| Field | Purpose |
|---|---|
_gotcha | Honeypot spam protection |
_honeypot | Honeypot spam protection |
_csrf | CSRF token |
cf-turnstile-response | Turnstile token |
_turnstileToken | Turnstile token (JS) |
CORS
The endpoint supports CORS for JavaScript submissions:
Access-Control-Allow-Origin: Your configured originsAccess-Control-Allow-Methods: POST, OPTIONSAccess-Control-Allow-Headers: Content-Type, X-Atlas-KeyConfigure allowed origins in Form Settings → Security → Allowed Origins.
Localhost Testing
Localhost submissions require:
See Security → Localhost Testing for details.
Optional: For JavaScript apps, you can add extra security with a Sandbox API Key:
await fetch('https://atlasforms.app/f/abc123', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Atlas-Key': process.env.ATLAS_FORM_KEY // From .env.local
},
body: JSON.stringify(data)
})Rate Limiting
Submissions are rate limited per IP address:
| Default | Limit |
|---|---|
| Standard | 60 requests/minute |
| Customizable | Via project settings |
Rate limit headers:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 55
X-RateLimit-Reset: 2024-01-15T10:31:00ZError Responses
400 Bad Request
Invalid data or content type.
{ "error": "Invalid content type" }403 Forbidden
{ "error": "Origin not allowed" }{ "error": "Localhost not allowed in live mode. Use sandbox mode for local development." }{ "error": "IP not registered for sandbox mode. Register your IP in form settings.", "your_ip": "73.45.123.100" }404 Not Found
Form doesn't exist.
{ "error": "Form not found" }429 Too Many Requests
Rate limit exceeded.
{ "error": "Rate limit exceeded. Please try again later.", "retry_after": 45 }402 Payment Required
Feature requires upgrade (e.g., file uploads on Starter plan).
{ "error": "File uploads require a paid plan", "upgrade_url": "..." }