Search by

ppcharlier / statamic-editor-api

ppcharlier

Write API for Statamic with drafts & revisions, built for mobile editors.

Package info

github.com/ppcharlier/statamic-editor-api

Type:statamic-addon

pkg:composer/ppcharlier/statamic-editor-api

Statistics

Installs: 58

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v2.7.0 2026-09-15 18:41 UTC

This package is auto-updated.

Last update: 2026-09-15 18:44:03 UTC


README

The write API that puts a pocket editor on your Statamic site.

Editor API adds a clean, complete REST write API to your Statamic 6 site — built as the backend of Editor for Drupal & Statamic, the iPhone and iPad app, and open to any client you want to build. No hosted service, no sync, no middleman: your site is the only backend. Free and open source.

The same contract exists as a module for Drupal 11: ppcharlier/drupal-editor-api.

tests Statamic 6 PHP 8.3+ License: MIT

Why

Statamic's Control Panel is excellent — on a laptop. Everything else (a phone, a tablet, a script, a custom editor) needs an API that can write, and that means more than POST and hope: drafts that don't go live, revisions you can restore, permissions that already match your team, and payloads that come back exactly as you sent them.

That's what this addon is.

Features

  • Control Panel parity, the safe way. Everything goes through Statamic's public facades — the same path the CP uses. No private controllers, no fragile workarounds.
  • Drafts by default, publishing on purpose. PATCH saves a working copy; publishing is an explicit action with its own endpoint and message.
  • Revisions & working copies. Full history and semantic restore, when revisions are enabled on the collection.
  • Your permissions, untouched. Tokens are tied to real Statamic users, and every request is authorized by Statamic's own policies — the same verdict the CP gives, site access and "other authors" rules included. One extra permission, access editor-api, decides who may use the API at all.
  • Clients know what they may do. Every payload carries a can block (edit, delete, publish, upload, …) and entries carry their author, so an app greys out an action instead of discovering a 403.
  • Stricter than the CP, if you want. Two optional per-collection permissions hide other authors' entries — or just their names — from an editor's listings. Off by default, on with one config key.
  • Byte-faithful Bard. ProseMirror documents round-trip verbatim — unknown node types, custom attributes and whitespace included. What your editor sends is exactly what your site stores.
  • Stored shapes are accepted back. GET serves field values exactly as Statamic stores them, and a write may echo them unchanged — including the fieldtypes whose Control Panel submits another shape: single-item assets and relationships, and date fields (stored Y-m-d H:i in the site's timezone, validated by Statamic 6 against a Zulu ISO string). The addon runs their own preProcess() on the way in, so nothing is rejected on a field you did not touch.
  • Conflict detection. X-Base-Modified guards every write — two editors can't silently overwrite each other (409 on a stale base).
  • The whole surface. Entries, assets (upload included), taxonomy terms, globals, navigations and form submissions — plus blueprints, so clients can render forms dynamically: choice options arrive as an ordered list, and GET /templates gives a template field the site's views.
  • Multi-site ready. Localized entries, linked localizations, per-site globals and terms.

Requirements

  • Statamic 6
  • PHP 8.3+

Works with and without Statamic Pro: without Pro the API degrades gracefully (direct saves instead of working copies, a single user). Revisions, multiple users and multi-site require Pro. Clients read GET /config and adapt their UI per collection.

Installation

composer require ppcharlier/statamic-editor-api

Optionally publish the config:

php artisan vendor:publish --tag=editor-api-config

That's it — the routes are live under /api/editor/v1.

Quick start

1. Sign in with a Statamic user's credentials to get a token. A non-super user needs the access editor-api permission on one of their roles (the "Editor API" group in the role editor):

curl -X POST https://example.com/api/editor/v1/auth/tokens \
  -H "Content-Type: application/json" \
  -d '{"email": "jane@example.com", "password": "secret", "device_name": "iPhone"}'
{ "data": { "token": "3|kqZ…", "expires_at": "2026-11-29T10:12:00+00:00" } }

2. Discover the site — one call gives a client everything it needs to build its UI (sites, collections, blueprints, containers, revision flags):

curl https://example.com/api/editor/v1/config \
  -H "Authorization: Bearer 3|kqZ…"

3. Save a draft, then publish it on purpose:

curl -X PATCH https://example.com/api/editor/v1/entries/abc-123 \
  -H "Authorization: Bearer 3|kqZ…" \
  -H "Content-Type: application/json" \
  -H "X-Base-Modified: 2026-09-01T08:15:00+00:00" \
  -d '{"data": {"title": "Low tide at the Aber Wrac’h", "body": [ … ]}}'

curl -X POST https://example.com/api/editor/v1/entries/abc-123/published \
  -H "Authorization: Bearer 3|kqZ…" \
  -d '{"message": "Fixed the tide times"}'

The X-Base-Modified header is the last_modified you read. If someone else changed the entry in between, you get a 409 instead of overwriting their work.

The API at a glance

All routes live under /api/editor/v1 (prefix configurable).

Area Endpoints
Auth POST /auth/tokens · DELETE /auth/tokens/current · GET /me
Discovery GET /config · GET /collections/{collection}/blueprints[/{blueprint}] · GET /templates
Entries GET·POST /collections/{collection}/entries · GET·PATCH·DELETE /entries/{id}
Publishing POST·DELETE /entries/{id}/published
Revisions GET /entries/{id}/revisions · POST /entries/{id}/revisions/{revision}/restore
Localizations POST /entries/{id}/localizations
Assets GET·POST /assets/{container} · GET·PATCH·DELETE /assets/{container}/{path}
Globals GET /globals · GET·PATCH /globals/{handle}
Taxonomies GET /taxonomies · GET·POST /taxonomies/{taxonomy}/terms · PATCH·DELETE /taxonomies/{taxonomy}/terms/{slug}
Navigations GET /navigations · GET·PATCH /navigations/{handle}/tree
Forms GET /forms · GET /forms/{form}/submissions · DELETE /forms/{form}/submissions/{id}

Every resource area can be disabled, or restricted to an allow-list of handles, in the config — a disabled resource answers 404, so a client can't even tell it exists.

📖 Full documentation — authentication and token drivers, every endpoint with its payloads, error codes, multi-site, permissions.

Permissions

Nothing to configure: the addon asks Statamic's policies the same questions the Control Panel asks. What a user may do in the CP, they may do through the API — no more, no less. Two things are specific to the addon:

  • access editor-api — the counterpart of access cp. A non-super user must hold it to get a token, and on every request afterwards: revoking it cuts off tokens already issued.
  • enforce_author_visibility (config, false by default) — the CP shows every entry, author included, to anyone who may view a collection. Turn this on and two per-collection permissions, editor-api list other authors {collection} entries and editor-api view other authors of {collection} entries, decide who sees other authors' entries and who may know their names. Super users and roles that may already edit other authors' entries are never restricted.

Security

Tokens are hashed at rest, revocable, expire after 90 days by default, and are rate-limited per token and per IP. Two storage drivers ship with the addon:

  • file (default) — tokens on disk, no database required.
  • sanctum — tokens in the personal_access_tokens table (requires laravel/sanctum and Eloquent users).

Found a vulnerability? Please report it privately rather than opening a public issue.

Testing

vendor/bin/pest

License

MIT — free, on as many sites as you like, nothing to buy on the Statamic Marketplace.

Versions v1.2.3 to v2.6.1 were published under a commercial licence and keep it; versions up to v1.2.2, and everything from the next release on, are MIT.