Appearance
REST API
Formatrica registers its endpoints under the WordPress REST API namespace formatrica/v1. Every route below is reachable at:
https://your-site.com/wp-json/formatrica/v1/...Looking for PHP hooks?
This page covers the HTTP REST API. For do_action / apply_filters extension points, see the Hooks & Filters reference.
Authentication
Admin routes require the caller to be an authenticated administrator (manage_options). From the WordPress admin (cookie session), send the REST nonce in the X-WP-Nonce header. For external admin calls, use an Application Password with HTTP Basic auth.
Public routes — the form submission, draft save/resume, country/state lookups, and the payment webhook/status endpoints — are callable without authentication. They are protected by their own mechanisms (per-form nonce, resume token, provider signature, HMAC status token) rather than user login.
The tables below mark each route's auth model.
Submitting a form
POST /forms/{id}/submissions
The public endpoint a form posts to. Auth: public (protected by the per-form nonce and anti-spam checks).
The body is a flat map of field name → value, plus a small set of reserved keys the form's markup includes automatically:
| Key | Purpose |
|---|---|
_fmt_nonce | Per-form submit nonce (action formatrica_submit_{id}). |
| (honeypot field) | Must be empty. The field name is derived per-form. |
| (timing token) | Rejects submissions faster than the minimum fill time (default 2s). |
_fmt_captcha_token | CAPTCHA response, when a CAPTCHA provider is enabled. |
_fmt_return_to | Post-payment return URL (payment forms only; must be same-origin). |
Success — 200
json
{
"success": true,
"message": "Thanks! Your submission was received.",
"data": { "submission_id": 42, "fields": { "email": "a@b.com" } },
"email": { "sent": true }
}A payment-enabled form instead returns a redirect instruction:
json
{
"success": true,
"payment_required": true,
"payment_redirect": "https://checkout.stripe.com/...",
"order_uuid": "…",
"status_token": "…"
}Validation error — 422
json
{
"success": false,
"message": "Please check the highlighted fields.",
"errors": {
"fields": { "email": "Please enter a valid email address." },
"data": { "email": "not-an-email" }
}
}Other statuses: 403 (nonce failed), 400 (honeypot tripped or submitted too quickly), 429 (rate limited), 401 (headless auth failed — see below), 500 (unexpected error; internal details are never leaked).
Headless (server-to-server) submissions
Pro feature
The headless submission API is part of Formatrica Pro.
You can submit a form from a server, script, or another application — no browser, nonce, or CAPTCHA required. It uses the same POST /forms/{id}/submissions endpoint; what switches it into headless mode is an API-key header.
Setup
- Open the form → Settings → Advanced and enable Headless / API submissions.
- Generate and save an API key (stored encrypted; shown once).
- Optionally restrict calls to an allowlist of IPs / CIDR ranges (IPv4 and IPv6). An empty allowlist means no IP restriction.
Making the call
Send the key in the X-Formatrica-Api-Key header:
bash
curl -X POST 'https://your-site.com/wp-json/formatrica/v1/forms/123/submissions' \
-H 'Content-Type: application/json' \
-H 'X-Formatrica-Api-Key: YOUR_API_KEY' \
-d '{"your_field_name":"value","email":"a@b.com"}'With a valid key, the nonce, honeypot, timing, and CAPTCHA checks are all skipped. Field validation and rate limiting still apply. A success returns the same 200 body as a browser submission.
Rejections
Every authentication failure — unknown or missing key, disabled toggle, IP not on the allowlist, or too many failed attempts — returns an identical response, by design, so keys and settings can't be probed:
json
{ "success": false, "message": "This form does not accept API submissions.", "errors": [] }- Status: 401.
- Repeated failures from one IP are throttled (10 failures/hour per form + IP).
- If your Pro licence lapses past its grace period, the API stops accepting calls even while the toggle is still on.
IP allowlist and proxies
The client IP is read from forwarding headers when present. If you rely on the IP allowlist, make sure your site sits behind a trusted proxy that sets those headers reliably — otherwise treat the API key as the primary control.
Forms (admin)
All admin. Send X-WP-Nonce (or use Application Passwords).
| Route | Method | Purpose |
|---|---|---|
/forms | GET | List all forms — { "forms": [ … ] }. |
/forms | POST | Create a form. Body: title, config. Returns the saved form (201). |
/forms/{id} | GET | Fetch one form. 404 if not found. |
/forms/{id} | PUT / PATCH | Update a form. Body: title, config. |
/forms/{id} | DELETE | Delete a form. 204 on success. |
Secrets in a form's config (integration API keys, webhook secrets, the headless key) are never returned by GET — the response carries a *_set boolean instead, and re-saving the blanked value preserves the stored secret.
Utilities
| Route | Method | Auth | Purpose |
|---|---|---|---|
/utility/countries | GET | Public | Country list. Query mode = all/shipping/selling/both. |
/utility/states/{country} | GET | Public | States/provinces for a 2-letter country code. |
/wp/post-types | GET | Admin | Registered post types (for the WordPress Post integration). |
/woocommerce/catalog | GET | Admin | Products or categories. Query type, limit, search. |
/emails/test | POST | Admin | Send a test email. Body: recipient, options, formId. |
/integrations/mailchimp/lists | POST | Admin | Fetch Mailchimp audiences. Body: apiKey, formId. |
/integrations/brevo/lists | POST | Admin | Fetch Brevo lists. Body: apiKey, formId. |
Settings (admin)
| Route | Method | Purpose |
|---|---|---|
/settings/email | GET / POST | Global email sender + delivery provider settings. Secrets are write-only (returned as *_set flags). |
/settings/email/test | POST | Send a test email using the global settings. |
/settings/email/diagnostics | GET | Last wp_mail error/success details. |
/settings/pdf | GET / POST | PDF branding. Pro only — the route is absent in the Free package. |
Pro endpoints
These routes exist only when Formatrica Pro is installed.
Payments
| Route | Method | Auth | Purpose |
|---|---|---|---|
/payments/webhook/{provider}/{mode} | POST | Provider signature | Stripe/PayPal webhook receiver. provider = stripe/paypal, mode = test/live. |
/payments/status | GET | HMAC token | Order status for the return page. Query order_uuid, status_token. Returns status only, no personal data. |
/payments/settings | GET / POST | Admin | Gateway credentials (site-level, write-only) and the copy-paste webhook URLs. |
Save & Resume (drafts)
| Route | Method | Auth | Purpose |
|---|---|---|---|
/forms/{id}/drafts | POST | Form nonce | Save a draft. Body: values (incl. _fmt_nonce), page_url. |
/forms/{id}/drafts/resume | GET | Resume token | Exchange a resume token for the saved values. Every failure returns an identical 404 { "resumable": false }. |
AI form generation
All admin. See AI form generation.
| Route | Method | Purpose |
|---|---|---|
/ai/generate | POST | Generate a form proposal from an instruction. |
/ai/review | POST | Review an existing form and return findings. |
/ai/notification-template | POST | Draft notification subject / success message. |
/ai/models | POST | List the account's available models. |
/ai/settings | GET / POST | AI settings (API key is write-only). |
License
All admin. See License & updates.
| Route | Method | Purpose |
|---|---|---|
/license | GET | License status summary + masked key. |
/license/activate | POST | Activate. Body: license_key. |
/license/refresh | POST | Re-validate the stored key. |
/license/deactivate | POST | Free the activation slot. |
Submission preview
| Route | Method | Purpose |
|---|---|---|
/submissions/{id} | GET | Full detail of one stored submission (admin + SUBMISSIONS_PREVIEW capability). |