Skip to the content
Documentation
Help Start
Reading in:
  • German: 9,059 of 9,059 pages
About the help in other languages
All help pages

ezprestapi: a REST content provider for remote updates

This page is for developers who publish content into Exponential from scripts and other services. ezprestapi is a REST API provider (versions 1 and 2 of the ezp API) for updating content remotely: other systems list…

Download as PDF

Address: https://doc.exponential.earth/exphelp/viewer/features/6.0/extensions/ezprestapi.md

On this page

ezprestapi: a REST content provider for remote updates

This page is for developers who publish content into Exponential from scripts and other services. ezprestapi is a REST API provider (versions 1 and 2 of the ezp API) for updating content remotely: other systems list, read, create, update and delete nodes over HTTP with an OAuth token. It is a registered provider of the kernel's REST framework.

Since 1.2.6 it serves REST API v1 and v2 as one extension: one activation (ActiveExtensions[]=ezprestapi), one provider class for the prefixes ezp and ezpl, one route table, one OAuth2 setup. It replaces the deprecated ezprestapiprovider. The guide REST API v1 and v2: one extension has the routes, authentication, configuration and the migration.

How it is wired

The provider classes are named in rest.ini:

[ApiProvider]
ProviderClass[ezp]=ezp7xRestApiProvider
ProviderClass[ezpl]=ezp7xRestApiProvider

The routes are served below the REST prefix of the installation and carry a version. Reads answer at v1 and v2, writes at v2 only. With the prefixes ezp and ezpl they answer, for example, at /api/ezp/v1/content/node/<id>/list/offset/0/limit/20 and /api/ezpl/v2/content/node/create.

ProviderClass[ezp] of this extension replaces the one of ezprestapiprovider, which served v1. Before 1.2.5 that took v1 away (every /api/ezp/v1/... answered 404) although existing clients, a mobile app among them, read through it; since 1.2.5 this provider serves the v1 reads itself. That needs the kernel of Exponential 6.0.15, whose versioned routes take a list of versions; on an older kernel the routes are v2 only, as before. Since 1.2.6 ezprestapiprovider (6.0.4) sets the same provider class, so every combination of the two extensions routes every content URL to ezp7xRestContentController.

The template of OutputFormat=xhtml is set for this extension's controller (1.2.6):

[ezp7xRestContentController_viewContent_OutputSettings]
Template=rest_pagelayout.tpl

Since 1.2.9 the create, update and delete calls are written by the kernel's expContentWriter (kernel/classes/contentwriter/expcontentwriter.php, Exponential 6.0.15); the extension no longer requires nxc_powercontent. An update publishes a new version of the node's object with the values sent (Writing content). On a kernel older than 6.0.15 the write calls answer 501 not_implemented.

Authentication is the REST framework's OAuth2: obtain a token at POST /api/auth/v1/oauth/token (grants authorization_code and refresh_token) and send it in the Authorization: Bearer (or OAuth) header; the oauth_token parameter is read from a POST form body, and from the query string only with rest.ini [OAuthSettings] AllowTokenInQuery=enabled (OAuth token hardening). A user can also make a personal API key on the site and send it as Authorization: Bearer expk_...; the create, update and delete routes then need the key's publish, edit or remove scope as well (rest.ini [ApiKeySettings] RouteScopes[], RouteGuards[]).

Permissions

Since 1.2.5 the controller checks the current user's policies before every call, whatever the request was authenticated with, the way the content module checks them: content/read for reads (a list or count also of its parent node), content/create of the class below parentNodeID in languageLocale (with every limitation), content/edit for an update (in its language), content/remove of every location of the object and everything below them for a removal. A refusal answers 403 {"error":"access_denied","error_message":...} and writes nothing. Before 1.2.5 the writes asked nothing: an OAuth token could create and remove where its user had no right to. The check is the kernel's expRestContentPermission (Exponential 6.0.15); on an older kernel the extension refuses every write with 403 rather than run it unchecked. The details are in the guide: Permissions of the REST interface.

AnswerWhen
201 {"message":"Created","objectId","nodeId"}a create was published
200 {"message":"Updated","objectId","nodeId","version","languageLocale"}an update was published as a new version
202 {"message":"Waiting for a workflow",...}a workflow holds the publication of an update
200 {"message":"Removed","nodeId","objectId"}a removal is done
400 invalid_requestparentNodeID, classIdentifier or languageLocale is missing, or names a class or language that does not exist; an update without values; an unknown attribute, a value that is not text, or a file value that is not a public http(s) URL
403 access_deniedthe user may not do it
404 not_foundthe node does not exist
501 not_implementeda write on a kernel older than 6.0.15 (no expContentWriter)
401no or an invalid token or key (a POST or DELETE too; before 6.0.15 they answered 405)

Writing content

POST /content/node/<id> and PUT on the same URL (or POST with _method=PUT) publish a new version of the node's object; attributes left out keep their values. languageLocale is optional (default: the object's main language); a language the object does not have yet adds that translation. The new version goes through the content/publish operation, so workflows run. A personal API key needs the edit scope (RouteScopes[ezp7xRestContentController_UpdateContentNode]=edit).

Create and update accept the values as form fields or as a JSON object (Content-Type: application/json), by attribute identifier and as text: rich text (ezxmltext) as HTML, converted with the Online Editor's input parser (links and embeds become relations); files (ezimage, ezbinaryfile, ezmedia) as <http(s) URL> or <URL>|<alternative text or file name>, downloaded from a public address only (no server path, file://, other scheme, credentials in the URL, or address in a private, loopback, link-local or reserved network; no redirects; at most 50 MB); every other datatype in its text form (fromString()). Before 1.2.9 a create read a file value from a local server path or downloaded any URL through nxc_powercontent. The guide has the details and a curl example: Updating and the values of a write.

Routes

Registered by ezp7xRestApiProvider (classes/rest_provider.php); all but the Atom feed run in ezp7xRestContentController, so they all get its checks:

RouteVersionsPurpose
GET /content/node/:nodeIdv1, v2One node
GET /content/node/:nodeId/list... (a regular expression route)v1, v2List children (offset, limit, sort)
GET /content/node/:nodeId/fields, .../field/:fieldIdentifier, .../childrenCountv1, v2Fields and counts
GET /content/object/:objectId, .../fields, .../field/:fieldIdentifierv1, v2The same by object id
GET /content/node/:nodeId/listAtom (ezpRestAtomController)v1, v2Atom feed (answers 500: known issue)
POST /content/node/createv2Create and publish content
DELETE or POST /content/node/delete/:nodeIdv2Remove the node's object
POST or PUT /content/node/:nodeIdv2Update: publish a new version with the values sent
Before 1.2.5 and 6.0.15Since
/api/ezp/v1/...: 404 for every routethe reads answer at v1
POST /api/ezp/v2/content/node/create without or with a refused token: 405401 or 403
DELETE /api/ezp/v2/content/node/delete/<id>: 405runs (and POST)
a delete that worked answered 500 with "has been removed"200 with the ids
fields and object reads ran in ezpRestContentController of ezprestapiproviderin this extension's controller

Call it from the command line

bin/php/ezrestcall.php (1.2.0) is an example client built on Guzzle. Guzzle is not part of the distribution: run composer require guzzlehttp/guzzle in the installation that runs the script. It speaks HTTPS to a host:

# list the children of a node (the script appends /limit/<n> and the token)
php bin/php/ezrestcall.php --host=www.example.com --token=<oauth token> --action=list --uri=/api/ezpl/v2/content/node/2/list
OptionMeaning
--hostHost name without protocol
--tokenAn OAuth token
--actionlist (the default), login or create
--uriThe path to call

The login and create actions are examples to read and adapt. create posts a story to /api/ezpl/v2/content/node/create with parentNodeID, classIdentifier, languageLocale and the attribute values. The values in them belong to the author's own site, so copy the script and replace them before use. Do not keep real credentials or tokens in a script, or in shell history on shared machines.

What changed

VersionDateChange
1.2.029 October 2024Initial import of the solution's dependencies, funding information and the example client.
1.2.1 to 1.2.427 September to 2 October 2026Version, license and website; description; 7x and Exponential Foundation headers on the entry point files; commands and cronjob parts are classes the files call and start through the shared helpers.
1.2.56 October 2026Every read and write checks the current user's policies for every kind of authentication; reads answer at v1 again; delete takes DELETE; create and delete answer 201 and 200 with the ids. Needs Exponential 6.0.15 for the checks and v1.
1.2.615 October 2026OutputFormat=xhtml renders again ([ezp7xRestContentController_viewContent_OutputSettings] Template=rest_pagelayout.tpl; it answered an empty renderedOutput); name, description and README say the extension serves REST API v1 and v2 and replaces ezprestapiprovider; the model tests moved in from ezprestapiprovider.
1.2.912 November 2026REST v2 updates content (POST or PUT /content/node/<id> publishes a new version); create and update accept a JSON body; create, update and delete are written by the kernel's expContentWriter, so nxc_powercontent is no longer required; file values are downloaded from public http(s) addresses only. Needs Exponential 6.0.15 for the writes.

ezprestapiprovider is deprecated; its final release, 6.0.4, is a compatibility shim that extends this extension's provider and controller. See the migration.

Become an Exponential Partner

Partners share their information, provide funding, contribute back and develop the products with us, and that is how Exponential grows. A partner website and dashboard are planned for mid-2027: please become a partner today to speed up our growth rate and land new features faster.

Something wrong on this page? Report an error

Documentation license

This documentation is free documentation, licensed under the GNU Free Documentation License 1.3 or later.

Exponential Copyright © 1998-2026 Exponential Foundation and 7x