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-Nonceheader with awp_restnonce.
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, Git sync, preview links |
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 |
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.
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": [] } |
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.
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.
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.
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", ... } }.
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 |
The token is write-only: it's never returned.
Something unclear or missing? Tell us