Which API for your app
This page is for app developers and technical leads who have to decide, screen by screen, which of the three HTTP interfaces of Exponential to call. It compares them on the things that matter for an app: what each one can do, how it authenticates, how its answers look and what the server team must set up.
Contents
The short answer
Read content with the REST API (/api/ezp/v1 or /api/ezp/v2). Use the remote services (expservices) for
what REST does not offer: search, image alias URLs, URL aliases, languages, updating content. Ask a PHP developer for
an ezjscore server function only when neither has what a screen needs.
By task
| Task | REST API | expservices | Read |
|---|---|---|---|
| Read one item with its fields | GET /content/node/<id>?ResponseGroups=Fields | expnode::get, expnode::dataMap | Reading a node |
| List a folder, paged | GET /content/node/<id>/list/offset/<n>/limit/<n> | expnode::children | Listing children and pagination |
| Count children | GET /content/node/<id>/childrenCount | expnode::childrenCount | same |
| Search | none | expsearch::search | Searching content |
| Image in a screen size | none (original path only) | expimage::url, expimage::urls | Image aliases for screen sizes |
| Item by URL path (deep link) | none | expnode::getByPath | Node ids, remote ids and deep links |
| Create and publish | POST /api/ezp/v2/content/node/create | expnode::create | Creating and removing content |
| Update | answers 501 after the permission check | expnode::update | Writing through expservices |
| Remove | DELETE /api/ezp/v2/content/node/delete/<id> | expnode::remove | Creating and removing content |
| Languages of the site | none | explanguage::prioritized, explanguage::languages | Multilingual content |
The expservices names come from the service declarations in extension/expservices/classes/; the full catalog is
in the expservices reference.
By property
| REST API | expservices | Own ezjscore function | |
|---|---|---|---|
| Ships with | ezprestapi (required by the 6.0.15 root composer.json) | expservices, part of the default distribution | your extension |
| URL | /api/ezp/<version>/... | /ezjscore/call/exp<domain>::<method>[::arg...] | /ezjscore/call/<name>::<function>[::arg...] |
| Credential | OAuth2 token or personal API key | expservices token, or a session cookie | whatever the function checks, usually the session |
| Anonymous calls | refused by default (RequireAuthentication=enabled) | allowed for services marked public | up to the function |
| Answer shape | plain JSON objects; errors with HTTP status | {"error_text":"","content":{"ok":...}}, errors inside with HTTP 200 | {"error_text":"","content":<value>} |
| Paging | offset, limit in the path; childrenCount in metadata | last two URL arguments; meta.total, meta.has_more | your own |
| Versioned | yes, v1 and v2 | no version in the URL | no |
The difference in error handling matters for your HTTP layer: REST says what went wrong with the status code, while
an expservices call that reaches the service answers HTTP 200 and puts the error in content.ok and
content.error.code (The expservices envelope).
Mixing interfaces
Mixing is normal and safe: both run as a user and both check the same roles and policies. Keep two things apart in the app's code:
- Two credentials. A REST OAuth token or
expk_key is not an expservices token, and anexpt_token is not accepted by REST. Store and refresh them separately (Choosing a credential). - Two error models. Wrap each interface in its own client class that turns its answers into one error type of your app.
When nothing fits
A screen that needs data no route or service gives (a combined dashboard, a custom calculation) gets its own server endpoint, written in PHP in an extension: an ezjscore server function or a REST provider of your own. That is application creator work: JSON endpoints with ezjscore, REST API for applications. Brief them with the screen, the fields you need and the user the call runs as.
Related pages
- What the APIs do not do
- Headless Exponential
- JSON endpoints with ezjscore: ezjscore, expservices or REST?
- Free documentation: this page is free to copy, translate and improve under the GNU FDL 1.3.
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.