In brief
From this page’s summary fields, verified 2026-10-29. Sources in each section.- Authentication (details in section Authentication)
- OAuth 2.0 (authorization code, PKCE, client credentials, password), API key
- Rate limit (details in section Limits & quirks)
- Phraseanet v1: none; Phrasea SaaS plans: 5-40 concurrent requests + request quotas
- Webhooks (details in section Events & webhooks)
- Phrasea: admin-managed entity events, unsigned; Phraseanet: per OAuth app, 17 events
- Pagination (details in section At a glance)
- Phrasea: page + limit (max 100); Phraseanet v3: offset/limit or page/per_page (max 100)
- API spec (details in section Stored API specs)
- OpenAPI 3.1.0 Databox (239 ops) + Expose (37 ops); Phraseanet v3 OpenAPI 3.0.3 (7 ops)
Scope: two API families from the same vendor.
- Phrasea (current): one REST API per service (Databox, Expose, Uploader), built with Symfony and API Platform. Authentication goes through Keycloak.
- Phraseanet 4.1 (legacy): one PHP application exposing API v1, v2 and v3 under
/api/, with its own OAuth2 server.
Every installation is a separate server; there is no shared multi-tenant API host. {domain} stands for the base domain of a Phrasea installation and {host} for a Phraseanet server. No authenticated call was made for this page. The OpenAPI documents of the vendor's public demo instance were read without credentials.
At a glance
https://api-databox.{domain}/, https://api-expose.{domain}/, https://api-uploader.{domain}/ (default {domain} is phrasea.local); Keycloak at https://keycloak.{domain}/realms/phrasea S34. Phraseanet: https://{host}/api/v1/, /api/v2/, /api/v3/; OAuth2 at /api/oauthv2/; report API at /api/report S52records/search has been deprecated since API 1.3 S48. Vendor-side, Phrasea replaces Phraseanet in 2026; no end-of-support date for the Phraseanet API is published S1 S3ApiKey scheme S30. A one-time-token endpoint (POST/ott) exists S39. Phraseanet: OAuth2 authorization_code and password grants S44<resource>:<action> (e.g. asset:read, collection:edit, basket:list, integration:owner), plus OIDC scopes. Keycloak roles admin / <service>-admin. Object-level ACLs on workspaces, collections and assets S28 S29 S22. Phraseanet: no OAuth scopes documented; calls run with the rights of the user who authorised the app S44/docs.json). Databox: 143 paths / 239 operations; Expose: 20 paths / 37 operations, read on the vendor demo S39 S40. Uploader: login required S66. Phraseanet: API v3 OpenAPI 3.0.3 (7 operations) on SwaggerHub and in the repository S49 S50; v1/v2 are documented as HTML pages only S42. Archived copies on DAM Wiki: API spec downloadsAuthentication
Phrasea (Keycloak) S28 S39 S67
- Each Phrasea installation runs a Keycloak realm (default name
phrasea) S34. OIDC discovery lives athttps://keycloak.{domain}/realms/phrasea/.well-known/openid-configurationS67. - Interactive apps use the authorization-code flow (
/protocol/openid-connect/auth→/protocol/openid-connect/token), which the Databox and Expose specs declare as theiroauthsecurity scheme S39 S40. - Machine-to-machine: Keycloak clients with service accounts (
service_accountscope) and the client-credentials grant S28 S67. Admins create clients and assign roles and scopes in the Keycloak admin console S28. - Send
Authorization: Bearer {access_token}toapi-databox.{domain}etc. S39. - Admin rights: Keycloak role
admin(all services) or<service>-admin(one service); Super Admin can do everything S29.
Phraseanet 4.1 (built-in OAuth2) S44 S51
- A user registers an application (name, callback URL) from the account settings, reached by clicking their login in the menu bar. Phraseanet returns a client ID and secret S44.
- Authorization: GET
https://{host}/api/oauthv2/authorizewith response typecode,tokenorcode_and_tokenS44. - Token: POST
https://{host}/api/oauthv2/tokenwithgrant_type=authorization_code. Thepasswordgrant is allowed for highly trusted clients S44. - Pass the token as the
oauth_tokenquery parameter or in theAuthorizationheader. HTTPS is required S44 S43. - Phraseanet can also delegate login to an OpenID Connect provider such as a Phrasea Keycloak (
openidandps-authproviders) S56 S57.
Core resources
Phrasea — Databox API (https://api-databox.{domain}), from the vendor demo OpenAPI S39 and the next branch source S79.
| Resource | Endpoints | Notes |
|---|---|---|
| Assets | GET/POST /assets, GET/PUT/PATCH/DELETE /assets/{id}, POST/assets/multiple, /assets/move, /assets/copy, /assets/add-to-collection, /assets/delete-multiple, /assets/restore-multiple, GET/assets/suggest, GET/assets/geo-clusters, POST/assets/{id}/add-as-version, PUT/assets/{id}/trigger-workflow, POST/assets/{id}/attributes, GET/assets/{id}/duplicates, GET/assets/{id}/metrics | 29 operations on the demo. Soft delete and restore. GET/assets/{id}/similar (kNN) is in the source but not on the demo S79 S30 |
| Metadata values | GET/POST /attributes, GET/PUT/PATCH/DELETE /attributes/{id}, POST/attributes/batch-update | One attribute = one value of a definition on an asset |
| Metadata schema | /attribute-definitions (CRUD, /sort, /{id}/duplicate), /field-types, /built-in-attributes, /locales, /attribute-policies, /attribute-filter-rules | Per-workspace definitions |
| Controlled vocabularies | /entity-lists (CRUD, /{id}/import, /{id}/export, /{id}/clear), /attribute-entities (CRUD, PUT/{id}/merge) | Pending / approved values (4.0+) S23 |
| Tags | /tags (CRUD) | Tags drive access rules S8 |
| Workspaces | GET/POST /workspaces, GET/PUT/DELETE /workspaces/{id}, /workspaces/{id}/flush, /logo, /terms, /terms/sign, GET/workspaces-by-slug/{slug} | Top-level container |
| Collections | /collections (CRUD), /collections/{id}/ascendants, PUT/collections/{id}/move/{dest}, /follow, /unfollow, /delete-multiple, /restore-multiple, /collection-assets | Nested hierarchy |
| Search | GET/assets?query=…&conditions[]=… (AQL), GET/assets/suggest, /saved-searches (CRUD) | See Search & querying |
| Uploads | GET/POST /uploads, GET/DELETE /uploads/{id}, POST/uploads/{id}/part | Multipart upload to S3 S38 |
| Files & versions | GET/files/{id}, /files/{id}/metadata, /files/{id}/duplicates, /asset-file-versions | Technical metadata per file |
| Renditions | /renditions (CRUD), /rendition-definitions (CRUD, /sort, /{id}/duplicate), /rendition-policies, GET/rendition-build-reference | Definitions per workspace |
| Attachments | /attachments (CRUD) | Files attached to an asset |
| Sharing | /shares (CRUD), GET/shares/{id}/public, GET/s/{id}/r/{rendition}, GET/s/{id}/a/{attachment} | Public, time-limited share links |
| Baskets | /baskets (CRUD), /baskets/{id}/assets, /baskets/default/assets, /archive, /unarchive, /remove | Selections, publishable to Expose |
| Rights | /asset-policies, /attribute-policies, /rendition-policies, /attribute-filter-rules | Users and groups come from Keycloak, not the Databox API S28 |
| Workflows | GET/workflows, GET/workflows/{id}, POST/workflows/{id}/cancel, POST/workflows/{id}/jobs/{jobId}/rerun | Workflow state per run |
| Integrations | /integrations (CRUD), /integration-types, /integration-datas, /integration-tokens | AI and third-party connectors per workspace S30 |
| Templates & exports | /asset-data-templates, /template-attributes, POST/asset-exports | Import templates, export jobs |
| Collaboration | /messages, GET/threads/{threadId}/messages | Discussions on assets |
| Other | /pages, /page-by-slug/{slug}, /profiles, /operation-tasks, POST/ott | Pages, display profiles, admin tasks, one-time tokens |
Phrasea — Expose API (https://api-expose.{domain}) S40: /publications (CRUD, /slug-availability/{slug}, /{id}/assets, /{id}/sort-assets), GET/publications/{publicationSlug}/assets/{assetSlug}, /assets (CRUD, /{id}/sub-definitions), /sub-definitions, /publication-profiles, /download-requests, /uploads.
Phrasea — Uploader API (https://api-uploader.{domain}): resources Asset, Commit, FormSchema, Target, TargetParams, MultipartUpload S66. Key routes: POST/commit, POST/commits/{id}/ack, POST/assets/{id}/ack, GET/targets/{id}/form-schema S79 S32.
Phraseanet 4.1 (paths relative to https://{host}/api/v1, /v2, /v3) S51 S46 S50
| Resource | Endpoints | Notes |
|---|---|---|
| User | v1 GET/me/, /me/collections/, /me/structures/, /me/subdefs/, POST/me/update-account/, /me/update-password/, /me/request-collections/ | |
| Databases & collections | v1 GET/databoxes/list/, /databoxes/{databox_id}/collections/, /status/, /metadatas/, /termsOfUse/, GET/collections/{base_id}/; v3 GET/databoxes/{databox_id}/subdefs/ | Metadata structure per database |
| Records (assets) | v1 GET/records/{databox_id}/{record_id}/ (+ /caption/, /metadatas/, /status/, /embed/, /related/), POST/records/add/, POST…/setmetadatas/, …/setstatus/, DELETE/records/{databox_id}/{record_id}/; v3 GET/PATCH /records/{databox_id}/{record_id}/, POST/records/{base_id}/ | v3 PATCH sets metadata and status bits |
| Stories | v1 GET/stories/{databox_id}/{record_id}/ (+ /embed/), POST/stories, /addrecords, /delrecords, /setcover; v3 GET/stories/{databox_id}/{record_id}/children/ | |
| Search | v1 /search/; v2 /search/; v3 POST/search/, POST/searchraw/ | records/search deprecated |
| Quarantine | v1 GET/quarantine/list/, /quarantine/item/{id}/; v2 POST/quarantine/item/{id}/add/, DELETE/quarantine/item/{id}/ | |
| Baskets | v1 /baskets/list/, /baskets/add/, /baskets/{basket}/content/, /setname/, /setdescription/, /delete/; v2 POST/DELETE /baskets/{basket}/records/, PUT…/records/reorder | |
| Orders | v2 GET/POST /orders/, GET/orders/{id}, POST/orders/{id}/accept, /deny, GET/orders/{id}/archive | |
| Feeds | v1 /feeds/list/, /feeds/{feed_id}/content/, /feeds/content/, /feeds/entry/{entry_id}/ | Publications |
| Renditions | v1 /records/…/embed/, POST/embed/substitute/, /me/subdefs/ | "Sub-definitions" |
| Accounts | v1 POST/accounts/access-demand/, /accounts/reset-password/{email}/, … | |
| Uploads | v1 POST/records/add/, POST/upload/enqueue/ | Enqueue used by the Phrasea Uploader S32 |
| Monitoring | v1 /monitor/phraseanet/, /monitor/scheduler/, /monitor/tasks/, POST/monitor/task/{task}/start/, /stop/; v3 /monitor/data/ | Admin |
Data model
- Workspace → Collections (nested; an asset can sit in several) → Assets. Assets can be stories that contain other assets.
- Asset: owner, privacy level, tags, attributes (values of attribute definitions, multilingual, possibly multi-valued, possibly entities from an entity list), renditions (built from rendition definitions), a source File with versions, attachments, annotations and discussion threads.
- Integrations and workflows are attached to a workspace. Webhooks are global to a service S36.
- Identifiers: string IDs in the API (UUID-style; the spec types them only as strings) S39. Users and groups are Keycloak identities S28.
- Databox (
sbas_id/databox_id: a metadata database with its own structure) → Collections (base_id) → Records (record_id, unique within a databox). - A record has a caption (metadata fields), status bits, sub-definitions (renditions such as thumbnail, preview and document) with permalinks, and can be a story.
- A record is identified by the pair
{databox_id}/{record_id}.
Search & querying
- GET
/assetswithquery(full text),conditions[](AQL),workspaces[],parents[],collection,story,ids[],include_deleted,page. - AQL examples:
title STARTS WITH "Report" AND (@tag HAS ALL OF ("a","b") OR description IS EMPTY);location WITHIN CIRCLE (48.85, 2.35, "1500m"); dates with prefix matching (@createdAt IS "2024-03").CONTAINS/STARTS WITH/ENDS WITHare case-insensitive unlessCASE SENSITIVEis added. They work on the raw value, which is indexed up to 256 characters S31. - Facets, sorting, suggestions (
/assets/suggest), geo clusters (/assets/geo-clusters) and kNN similarity on CLIP embeddings S22 S30. - Page size:
limit, max 100 S35. The maximum depth of deep pagination is not documented (Unknown).
Phraseanet S50
- v3 POST
/search/:query(full text with operators, e.g.dogs OR cats; empty = all),search_type(0 records, 1 stories),bases[](collection IDs), paging withoffset/limitorpage/per_page(1–100, default 10),story_children_limit,include[]to add facets or story children (left out by default). - v3 POST
/searchraw/returns raw search-engine results S50 S51.
Uploads & binaries
Phrasea
- Multipart upload S38 S39: POST
/uploadsstarts the upload, POST/uploads/{id}/partreturns the URL for the next part, the client PUTs the part to object storage, then the upload is completed and attached to an asset. DELETE/uploads/{id}cancels it. The source also has POST/uploads/{id}/parts(batch of part URLs) S38. - Signed URLs: request signatures expire after 3,600 s for Databox and Expose and 600 s for Uploader by default (
*_REQUEST_SIGNATURE_TTL). Optional CloudFront signed delivery (TTL 86,400 s) S34. - Uploader commits: users upload files, then commit the batch. The target (Databox, Phraseanet or another endpoint) is notified (push) or polls GET
/commits(pull). It downloads each asset with GET/assets/{id}/downloadand acknowledges with POST/commits/{id}/ackS32. - Assets can also be created from a URL S22.
Phraseanet
- POST
/api/v1/records/add/(multipart file +base_id;nosubdefsskips rendition generation). Files may land in quarantine S48 S46. - POST
/api/v3/records/{base_id}/creates a record S50. - Downloads: sub-definition permalinks (
/permalink/v1/{databox_id}/{record_id}/{subdef}/…?token=…) withurl,page_urlanddownload_urlS50 S48.
Events & webhooks
- Entity webhooks: admins manage them in the service's admin back office (EasyAdmin CRUD). Each webhook has a URL, a list of events, an active flag, "verify SSL", a timeout (default 30 s) and a secret field.
- Events (Databox):
{entity}:create,{entity}:update,{entity}:deleteforasset,attribute,attribute_definition,collection,rendition,rendition_definition,rendition_policy,tag,workspaceS37. - Delivery: HTTP POST with JSON body
{"event": …, "payload": …}; redirects are not followed. Failed deliveries are stored in a webhook log S36. - Signature: Unverified none found. The secret field exists but the delivery code reviewed on 2026-10-29 does not send it or sign the body. Retries: none found in the delivery handler (Unknown).
- Workflow webhook (
core.webhookintegration): calls a configurable URL (method, options, optional inputs and origin) as a workflow step S30. Saved-search automations can also fire webhooks S79. - Real time: WebSocket notifications to clients through Sockudo S22.
Phraseanet 4.1 S45 S53 S54 S55
- Configured per OAuth application: webhook URL, active flag, list of listened events (empty = all) S55 S54.
- Events in the code:
record.created,record.edited,record.deleted,record.media_substituted,record.collection_changed,record.status_changed,record.subdef.created,record.subdef.creation_failed,record.subdefs.created,order.created,order.delivered,order.denied,user.created,user.deleted,user.registration.granted,user.registration.rejected,new_feed_entryS53. Unverified The public docs still say onlynew_feed_entryexists S45. - Delivery: JSON POST with a
Phraseanet/{version}User-Agent and a default timeout of 30 s. Events are only sent when the app creator has rights on the affected collection or record. Failed deliveries go to a retry queue up to a configured maximum, then are logged S54. - Signature: the application model has an
hmac_keycolumn S55, but the webhook worker does not use it Unverified (inference from code); the docs say nothing about signing S45.
Limits & quirks
- Phrasea API doc on the demo vs the code: the demo instance's OpenAPI lacks some routes in the current source (
/assets/{id}/similar,/saved-search-automations) S39 S79. Unverified The demo probably runs an earlier release; its version is not exposed. - API Platform conventions: JSON-LD (
application/ld+json) or plain JSON. PATCH takesapplication/merge-patch+jsonS35. - Production readiness: Alchemy says its Docker Compose and Helm containers are "primarily designed for development and testing" and need hardening for production. It recommends managed PostgreSQL and S3 S27.
- Phraseanet v1 envelope: every response wraps
meta(api_version, http_code, error_type, error_message…) andresponse. With JSONP the HTTP status is 200 and the real code sits inmeta.http_codeS43. - Phraseanet v1 has no anonymous access; every call needs a token S43.
- Phraseanet v3 spec coverage: the spec documents 7 operations, while the v3 routes also include
/monitor/data/,/databoxes/subdefs/and a sub-definition service callback S50 S51. - Breaking change history (Phraseanet): API 1.2 renamed fields and changed collection shapes; later versions were backward-compatible S48.
- Legacy runtime: Phraseanet 4.1 requires PHP 7.0 S59, which has been end-of-life since 2019-01-10 S69.
SDKs, tools & code samples
| Library | Language | Repo / package | Status |
|---|---|---|---|
| Phraseanet PHP SDK | PHP | alchemy-fr/Phraseanet-PHP-SDK, Packagist phraseanet/php-sdk | Official; 7.0.1 on 2021-02-24; repository last pushed 2024-07-11 S62 S76 |
| Phraseanet PHP SDK Silex provider | PHP | alchemy-fr/Phraseanet-PHP-SDK-Silex-Provider | Last push 2013 S64 |
| Phraseanet-Clients | various | alchemy-fr/Phraseanet-Clients | Last push 2012 S64 |
Phrasea @alchemy/* TypeScript packages | TypeScript | monorepo lib/js | Internal packages of the Phrasea front ends (API client, auth, multipart upload) S22; publication on npm not verified (Unknown) |
| Media libraries | PHP | PHPExiftool, Zippy, BinaryDriver, PHP-Unoconv, PHP-FFMpeg fork… | Building blocks of Phraseanet; Zippy 476 stars S64 |
| Postman collection | — | — | None found (Unknown) |
Changelog of the API
| Date | Change |
|---|---|
| 2026-10-01 | Phrasea 4.5.0: workspace terms & conditions, multi-asset sharing, multipart upload for logos and terms PDFs S23 |
| 2026-06-30 | Phrasea 4.0.0: capability payloads change from canX booleans to an object (edit, delete, share, editPermissions, createAsset…); pending attribute entities; rendition rules and collection-level tag filter rules deprecated S23 |
| 2025-05-15 | Phraseanet API v3 spec: stories referenced in search results (include[]=results.records.stories) S50 |
| 2023-12-06 | Phrasea 3.0.0: authentication moves from the in-house Auth service to Keycloak (Symfony 6, API Platform 3) S23 |
| 2023-05-11 | Phrasea 2.0.0: workflows; Expose breaking changes S23 |
| 2020-06-30 | Phraseanet API v3 published on SwaggerHub S49 |
| Undated | Phraseanet API 2.0.0: search v2, orders, single-record deletion. API 1.5.0 (Phraseanet 3.8.8): embed/substitute, nosubdefs. 1.4.0 (3.8.4): me route. 1.3 (3.7.5): stories; records/search deprecated. 1.2: breaking renames (offset_start, updated_on…) S48 |