Darstellung
REST API
Namespace: ad-form/v1
Base: /wp-json/ad-form/v1
Authentication: WordPress cookie + X-WP-Nonce: wp_rest for admin routes. Application passwords work for the same capability checks.
Discovery
GET /status
Public. Plugin identity only.
GET /system
Capability: manage_ad_form_settings
Forms
GET /forms/schema
Capability: edit_ad_form_forms
Returns JSON Schema for the definition document and the REST resource.
GET /forms/picker
Capability: edit_posts or edit_pages or edit_ad_form_forms or manage_ad_form_forms.
Published forms only (per_page 100, orderby=title ASC). Optional search.
Items are { id, title, slug, shortcode } — no definition, UUID or counts. Used by the Gutenberg block picker.
GET /forms
Capability: edit_ad_form_forms or manage_ad_form_forms
Query: page, per_page (max 100), status, search, orderby (id|title|slug|status|created_at|updated_at|submission_count), order (ASC|DESC)
json
{
"items": [
{
"id": 1,
"uuid": "...",
"title": "Contact",
"slug": "contact",
"status": "draft",
"version": 1,
"created_at": "2026-08-20 09:00:00",
"updated_at": "2026-08-20 09:00:00",
"submission_count": 0,
"shortcode": "[ad_form id=\"1\"]"
}
],
"total": 1,
"page": 1,
"per_page": 20,
"pages": 1
}POST /forms
Capability: create_ad_form_forms
Body: title (required), slug, status, definition, starts_at, ends_at
Returns 201 and the full resource. Location header points to the new form.
GET /forms/{id}
Full resource including parsed definition.
PUT / PATCH /forms/{id}
Capability: edit_ad_form_forms
Partial updates. Send version for optimistic locking (409 version_conflict on mismatch). Sending definition replaces the whole definition document.
DELETE /forms/{id}
Capability: delete_ad_form_forms
force=false (default): 409 form_has_entries when submission_count > 0.
force=true: deletes the form and form meta. Submissions are kept.
POST /forms/{id}/duplicate
Capability: create_ad_form_forms
Copies title, definition and creates a draft with a new UUID and slug.
Fields
GET /fields
Capability: edit_ad_form_forms or manage_ad_form_forms
Returns the builder palette: field types, inspector schema, default settings and categories.
json
{
"items": [
{
"type": "text",
"label": "Text",
"category": "basic",
"icon": "editor-textcolor",
"supports_required": true,
"default_settings": {},
"inspector": []
}
],
"categories": [
{ "id": "basic", "label": "Basic" }
]
}Actions
GET /actions
Capability: edit_ad_form_forms or manage_ad_form_forms
Returns the submit-action catalogue and documented merge tags.
json
{
"items": [
{
"type": "email",
"label": "Email notification",
"default_settings": {
"to": "{admin:email}",
"subject": "New submission: {form:title}",
"message": "{all_fields}"
},
"inspector": []
}
],
"merge_tags": [
{ "tag": "{field:key}", "description": "Submitted value for the field with this key." }
]
}Conditions
GET /conditions
Capability: edit_ad_form_forms
Returns operator, effect and logic catalogues for the builder.
json
{
"operators": [
{ "id": "is", "label": "Is", "needs_value": true }
],
"effects": [
{ "id": "show", "label": "Show this field if" }
],
"logic": [
{ "id": "all", "label": "All rules match" }
]
}Calculations
GET /calculations
Capability: edit_ad_form_forms
Returns formula functions and documented syntax.
json
{
"functions": [
{ "id": "min", "label": "min", "hint": "min(a, b)" }
],
"syntax": {
"operators": ["+", "-", "*", "/"],
"variables": ["{key}", "{field:key}", "key"]
}
}Submit
POST /forms/{id}/submit
Public. Body:
json
{
"nonce": "...",
"honeypot": "",
"source": "shortcode",
"values": {
"name": "Ada",
"email": "ada@example.com"
}
}The nonce is created with ad_form_submit_{id} (not wp_rest). Filled honeypot fields return a success confirmation without storing an entry and without running submit actions.
Logged-in visitors must also send X-WP-Nonce (wp_rest) because WordPress cookie authentication requires it. The form markup exposes that value as data-wp-rest-nonce. The per-form nonce remains the handler’s authorization.
Success 201:
json
{
"success": true,
"confirmation": {
"type": "message",
"message": "Thank you. Your message has been sent.",
"redirect_url": ""
},
"submission": {
"uuid": "..."
}
}Validation errors: 400 validation_failed with errors keyed by field key. Unavailable form: 404. Login required: 401. Invalid nonce: 403.
Submissions
Capability: view_ad_form_submissions for reads. Status/star changes need edit_ad_form_submissions. Permanent delete needs delete_ad_form_submissions. manage_ad_form_forms satisfies all three.
GET /submissions
Query: paged or page, per_page (max 100), form_id, view (inbox|unread|read|spam|trash|starred|any; status is an alias), search, orderby (id|created_at|updated_at|status), order.
Inbox (default) is unread + read. Search uses submission_meta, not the JSON payload. List items include a preview string, not the full payload.
json
{
"items": [
{
"id": 1,
"uuid": "...",
"form_id": 1,
"status": "unread",
"is_starred": false,
"preview": "ada@example.com",
"created_at": "2026-08-20 10:00:00"
}
],
"total": 1,
"page": 1,
"per_page": 20,
"pages": 1,
"counts": {
"inbox": 1,
"unread": 1,
"read": 0,
"spam": 0,
"trash": 0,
"starred": 0
}
}GET /submissions/{id}
Full resource including payload. Opening an unread entry marks it as read. ip_hash is never returned; ip_stored and ip_hash_prefix are.
PATCH /submissions/{id}
Body: status (unread|read|spam|trash), is_starred.
DELETE /submissions/{id}
force=false (default) moves the entry to trash. force=true deletes the row and meta and decrements submission_count.
POST /submissions/bulk
json
{
"ids": [1, 2],
"action": "spam"
}Actions: read, unread, spam, unspam, trash, restore, star, unstar, delete.
Planned
| Method | Route | Phase |
|---|---|---|
| GET | /templates | 12 |
Error shape
json
{
"code": "invalid_definition",
"message": "The form definition is invalid.",
"data": {
"status": 400,
"data": {
"success": false,
"code": "invalid_definition",
"message": "The form definition is invalid.",
"errors": {
"fields.1.key": "Field keys must be unique."
}
}
}
}