Skip to content

Early-bird lifetime licence: $199 once, for the first 200 buyers only. See the offer

All docs

REST API

Snipfire's editor runs on a REST API that you can use too: from deploy scripts, CI, or your own tools.

Base URL: https://example.com/wp-json/snipfire/v1/

Snipfire's routes never run your snippets, so a broken snippet can't block the API.

Authentication

Use any authentication WordPress's REST API accepts:

  • Application passwords (built into WordPress: Users → Profile → Application Passwords) with HTTP Basic authentication. Best for scripts.

    curl -u 'jane:abcd efgh ijkl mnop qrst uvwx' https://example.com/wp-json/snipfire/v1/snippets
  • Cookies and a nonce, from JavaScript running in the WordPress admin: send the X-WP-Nonce header with a wp_rest nonce.

Permission levels

Each route needs one of three team access levels. Without Snipfire Pro, only administrators have access (all levels).

Level Routes
view Reading: snippets, history, schema, export, activity
design Changing snippets. Each change is also checked against the user's level, for the snippet as it is and as it would be (a designer can't create PHP, for example)
full Imports, folder renames, settings, exporting as a plugin, site status, system info, Git sync, preview links, running scheduled snippets

Two routes for the block editor use WordPress capabilities instead: see Generators and the block editor. A few Pro routes need more than a level: the secrets vault, the AI settings and the agency hub need full access and an administrator (super admin on multisite), and network snippets need a super admin. Team access can't give those.

GET /status and GET /system-info stay readable for administrators while DISALLOW_UNFILTERED_HTML makes Snipfire read-only, since they change nothing.

A refused change returns 403 with the reason in message.

Snippets

Method and route Level What it does
GET /snippets view All snippets, without code. ?with_code=1 includes the code. ?uid=<uid>,<uid> returns only the snippets with these permanent IDs (the way to find the same snippet on several sites)
POST /snippets design Create a snippet (body: snippet fields)
GET /snippets/{id} view One snippet, with code
PUT / PATCH / POST /snippets/{id} design Update; only the fields you send change
DELETE /snippets/{id} design Delete
POST /snippets/{id}/enable design Switch on (checks and test-loads)
POST /snippets/{id}/disable design Switch off
POST /snippets/{id}/run design Run a PHP or HTML snippet once; returns { "output": "…", "error": null }
POST /snippets/{id}/duplicate design Copy (switched off); returns the copy, 201
POST /snippets/{id}/editing design Check in while the snippet is open: returns others (who else has it open), modified, modified_by and by_name (who saved it last)
DELETE /snippets/{id}/editing design Check out when you close the snippet
POST /validate design Check a snippet without saving (body: snippet fields); returns { "errors": [], "warnings": [] }

Create, update, enable and disable return:

{
  "snippet": { "id": 12, "title": "…", "status": "active", "code": "…" },
  "errors": [],
  "warnings": [],
  "deactivated": false
}

Status 201 for a new snippet, 200 for an update, 400 when it couldn't be saved at all. A snippet that was saved but has problems is returned with errors (each { "message": "…", "line": 3 }) and switched off; deactivated is true when you asked for it to be on and it isn't.

The body can include a settings form (fields, values), smart_tags, and for Pro features schedule (with "run": "schedule") and selector (with "hook": "element:selector"): see Snippet fields.

On an update, values changes only the keys you send and keeps the others. Send "values_mode": "replace" to replace them all (fields you leave out go back to their defaults).

Example: create a CSS snippet and switch it on:

curl -u "$USER:$APP_PASSWORD" -X POST https://example.com/wp-json/snipfire/v1/snippets \
  -H 'Content-Type: application/json' \
  -d '{"title":"Hide store notice","type":"css","code":".woocommerce-store-notice{display:none}","status":"active"}'

Saving over someone else's changes

To avoid overwriting a change someone else made after you loaded a snippet, send the snippet's modified value (as you loaded it) as base_modified with an update:

{ "code": "…", "base_modified": 1790000000 }

If someone else has saved the snippet since, the update is refused with 409 and nothing changes:

{
  "snippet": null,
  "errors": [ { "message": "Maria saved this snippet at 14:32, after you opened it. Saving now would overwrite their changes.", "line": 0 } ],
  "warnings": [],
  "deactivated": false,
  "conflict": { "user": 7, "name": "Maria", "time": 1790000100 }
}

To save anyway, send the update again with "force": true. Updates without base_modified aren't checked. The editor does this for you: see When someone else has the snippet open.

History

Method and route Level What it does
GET /snippets/{id}/revisions view Earlier versions, newest first, with who saved each
GET /snippets/{id}/revisions/{rev} view One version, with code and settings
POST /snippets/{id}/revisions/{rev}/restore design Restore it (checked and test-loaded; the current version is kept)

Bulk actions and folders

POST /bulk (design):

{ "ids": [12, 15, 18], "action": "enable", "value": "" }

Actions: enable, disable, delete, move (value = folder, "" for none), tag and untag (value = tag). Returns done (IDs), errors (ID → message) and items (the updated list). Enabling several snippets runs one test load.

POST /folders/rename (full): { "from": "Old/Name", "to": "New/Name" }. Subfolders move too. Returns { "moved": 4 }.

Export and import

Method and route Level What it does
GET /export view Export file of all snippets, or ?ids=12,15
POST /import full Import an export file (the JSON as the body). Arrives switched off unless ?keep_status=1. Returns { "created": [ids], "errors": [] }
POST /export-plugin full Export snippets as a plugin. Body: ids (list, or "12,14") and/or folder, name, slug, version, include (IDs of snippets with issues to export anyway, or "all"), dry_run. Returns the report (snippets, each with export, blocked and issues; exported) and, unless it's a dry run, filename, size and zip (the zip file, base64-encoded)

Snippet library

Method and route Level What it does
GET /library view The snippet library: packs, and items with their code and this site's state (new, current, changed, update), snippet id, status, missing plugins and needs_edit
POST /library/install design Install. Body: slugs (list) and/or pack (pack ID), activate (true to switch them on after the checks and one test load). Returns installed (slug → ID), activated, skipped and errors (slug → reason)
POST /library/update design Update installed snippets to the library's version. Body: slugs, or "all": true. Returns updated, kept (slug → settings kept), replaced (slugs whose code edits were replaced), skipped, errors

Each snippet is checked against the user's access, so a designer's request skips PHP snippets.

Generators and the block editor

Method and route Level What it does
GET /generators view The generators: id, title, description, notes, group, type, hook, priority, conditions, smart_tags, consent, fields, code, requires (plugins), missing (plugins not active here), pro (needs Snipfire Pro) and locked (why it can't be used on this site, for example Needs Snipfire Pro., or ""). To make a snippet from one, send its settings to POST /snippets with your values, or use wp snipfire generate
GET /block-snippets edit_posts capability Shortcode snippets for the Snipfire block and the page-builder elements: id, title, shortcode, active, and atts (the attribute names the code reads, with defaults). People with Snipfire access get all of them; other writers only the switched-on ones
GET /page-snippets/{post} view, and may edit the post The snippets on a post's page, as in the Snipfire panel: runs, maybe, everywhere (PHP on early hooks, which runs on every request), lists (HTML with the excerpt or in lists of posts) and shortcodes, each a list of id, title, type, hook, and a note for everywhere and lists rows

Page code is stored with the post, in the _snipfire_page_scripts meta field (head, body, footer, skip_global). It's in WordPress's own REST API, for example /wp/v2/pages/{id}, and only people who may change page code can write it.

Importers (other plugins)

Method and route Level What it does
GET /import/sources full Plugins with snippets to import
GET /import/sources/{source} full Preview: each snippet, how it maps, notes, Check first
POST /import/sources/{source}/run full Import. Body: ids (the other plugin's IDs; all if left out), update (re-import changed ones)
POST /import/sources/{source}/switch full Switch snippets off in the other plugin. Body: ids. Returns the Snipfire IDs to switch on next

Switching over is two requests on purpose: call switch, then switch the returned IDs on with POST /bulk ("action": "enable") in a new request, so no function is declared twice. Sources: wpcode, code-snippets, fluent-snippets, hfcm, custom-css-js, post-snippets, woody, customizer-css, wpcodebox.

The editor

Method and route Level What it does
GET /design-tokens view The site's design tokens for CSS autocomplete: tokens (each name, value, label, kind and source: theme, elementor or bricks) and sources. Cached until a source changes; ?fresh=1 rebuilds it
POST /welcome view The Getting started screen for the current user: { "dismissed": true } stops it opening by itself, false brings it back

Site status and system info

Method and route Level What it does
GET /status full A short summary for tools that look after several sites (such as the agency hub, or your own monitoring)
GET /system-info full The system info: sections (each a title and rows of label and value) and text, ready to paste

GET /status returns:

{
  "format": 1,
  "time": 1790000000,
  "site": { "url": "https://example.com/", "name": "Example", "environment": "production", "multisite": false },
  "snipfire": { "version": "0.17.0", "update": "" },
  "wordpress": "7.1",
  "php": "8.3.12",
  "snippets": { "total": 42, "active": 37, "errors": 1, "by_type": { "php": 20, "html": 10, "css": 8, "js": 4 } },
  "errors": [ { "id": 12, "uid": "…", "title": "…", "type": "php", "status": "inactive", "message": "…", "line": 4, "time": 1789990000 } ],
  "safe_mode": false,
  "php_disabled": false,
  "read_only": false,
  "addons": { "pro": { "version": "0.17.0" } }
}

update is a newer Snipfire version WordPress already knows about, or "". errors lists up to 50 snippets with a recorded error. safe_mode is site-wide safe mode (SNIPFIRE_SAFE_MODE); php_disabled and read_only are SNIPFIRE_DISABLE_PHP and DISALLOW_UNFILTERED_HTML. Neither route includes code, secrets or email addresses, and neither contacts another server.

WordPress abilities

Snipfire also registers WordPress abilities (WordPress 6.9+), for AI assistants and tools that use the Abilities API. See AI assistants and WordPress abilities.

Schema

GET /schema (view) returns what the editor needs to build its forms: condition types with their operators and options, the picker groups, the locations per type with their stage, the snippet types and CSS languages. Useful to build a UI or validate input.

Scheduled snippets Pro

Method and route Level What it does
GET /snippets/{id}/runs view The run log (the last 50 runs, newest first) and the next run
POST /snippets/{id}/runs full Run the saved snippet now and record it (Run now)

To put a snippet on a schedule, save it with "run": "schedule" and a schedule: see Snippet fields.

Snippet performance Pro

Method and route Level What it does
GET /profile view The performance figures of each snippet (from the last week), and the settings
DELETE /profile full Delete all measurements

Secrets Pro

Full access and an administrator (super admin on multisite). Values go in, never out: no route returns a secret's value.

Method and route What it does
GET /secrets Names, masked hints (••••abcd), dates, the key state and where each secret is used
POST /secrets Add one: { "name": "stripe_key", "value": "…" }. 409 if the name exists
POST /secrets/{name} (or PUT) Replace its value: { "value": "…" }
DELETE /secrets/{name} Delete it
POST /secrets/rekey Re-encrypt every secret with the current key

AI assistant Pro

Method and route Level What it does
GET /ai full, administrator The AI assistant's settings (never the key) and this hour's usage
POST /ai/settings full, administrator Change settings: enabled, provider, model, base_url, timeout, max_tokens, access; key is stored in the vault as ai_api_key
POST /ai/test full, administrator A tiny request to check the settings
POST /ai/explain the level in the settings { code, type, hook, run, title, context } → { text }
POST /ai/fix the level in the settings { code, type, hook, run, title, errors, context } → { code, explanation }
POST /ai/write the level in the settings { prompt, type, context } → { snippet, notes } (not saved)

context: true adds the site context. Each request counts towards the user's hourly limit. Errors come back with a message fit to show: 409 when there's no key or it's switched off, 429 over the limit, 400 for bad input, 504 on a timeout and 502 for errors from the provider.

Activity log Pro

GET /activity (view): newest first, 50 per page.

Query: snippet (ID), user (ID), action (see log actions), search, page.

Returns { "items": [...], "more": true, "actions": { "created": "Created", ... } }.

Settings form values Pro

POST /snippets/{id}/values (design): save only the settings form values of a snippet, including one the user can't otherwise edit, such as a PHP snippet. Body: { "values": { "key": "…" } }; only the keys you send change. The values are checked and test-loaded like any save; the code, fields and other settings don't change. Returns the same as an update. 400 if the snippet has no settings form.

Live CSS preview Pro

POST /live-css (design): compile CSS, SCSS or LESS for the live preview without saving. Body: code, lang (css, scss, less), optional id (for the snippet's partials), fields and values. Returns { "css": "…", "error": null }, or the compile error with its line.

Testing mode Pro

POST /preview/new-key (full): make a new preview link; old links stop working. Returns { "url": "https://example.com/?snipfire-preview=…" }.

Git sync Agency

Method and route Level What it does
GET /git full Settings (without the token), last sync, conflicts
POST /git/settings full Change settings: provider, repo, branch, root, scope, token, api, schedule. Only the fields you send change
POST /git/check full Test the connection: { "ok": true, "message": "Connected to …" }
POST /git/sync full Sync now. Optional body { "resolve": { "<uid>": "site" \| "git" } } settles conflicts first. Returns report plus the status
POST /git/webhook none (signed) For GitHub and GitLab webhooks; see Webhooks. Each delivery is acted on once: one seen in the last hour (same delivery ID or body), or a GitHub push older than an hour, is answered 200 with Delivery already received; ignored. or Delivery is too old; ignored.

The token is write-only: it's never returned.

Agency hub Agency

Full access and an administrator (super admin on multisite), on a site with the Agency plan. See Agency hub.

Method and route What it does
GET /hub The sites and what the hub last saw (makes no requests)
POST /hub/sites Add a site: { url, user, password, name? }. The hub tests the connection first
POST /hub/sites/authorize Start WordPress's authorization flow for { url }; returns the address to send the browser to
POST /hub/sites/{id} Rename: { name }
DELETE /hub/sites/{id} Remove a site
POST /hub/sites/{id}/refresh Ask one site now
GET /hub/sites/{id}/snippets The snippets on the site that came from the hub (?refresh=1 asks the site)
POST /hub/refresh Ask every site now
POST /hub/push { ids, sites, activate, resolve: { "<site>": { "<uid>": "overwrite" \| "keep" } } }
GET /hub/snippets/{id} Where a snippet runs (?refresh=1 asks the sites)
POST /hub/rollback { snippet, site, action: "previous" \| "disable" \| "remove", rev? }

Application passwords are never returned. The hub talks to client sites through their ordinary routes (GET /status, GET /snippets?uid=…, POST /snippets, PUT /snippets/{id}…), with the header X-Snipfire-Hub.

Network snippets Agency

Multisite, Agency plan. See Network snippets.

On the network (super admins), the same routes as a site's snippets under network/: network/snippets (GET, POST), network/snippets/{id} (GET, PUT, DELETE; answers add required and off_sites), …/{id}/enable, disable, run, duplicate, editing, revisions, revisions/{rev}, revisions/{rev}/restore, plus:

Method and route What it does
POST /network/snippets/{id}/required { "required": true }: sites can't switch it off
POST /network/snippets/{id}/sites/{site} { "on": true } switches it back on for that site (false off)
POST /network/bulk, /network/folders/rename, /network/validate As on a site
GET /network/export, /network/activity Export file; the network's activity log
GET / POST /network/settings Network settings; { "safe_mode": true } switches network safe mode on

On each site:

Method and route Level What it does
GET /network-snippets view The network snippets, as the site's editor shows them (From the network)
POST /network-snippets/{id}/site full on that site { "on": false } switches one off for this site (not a required one); true back on

Something unclear or missing? Tell us