Scope: the Media Management REST API (/otmmapi/v6) of OpenText Digital Asset Management / OTMM, as documented on the OpenText developer portal under "Media Management CE" S1 S2. The separate SaaS product Core DAM has its own API, summarised in Core DAM API. No authenticated call was made. Specs were downloaded from the developer portal's public content API (see API spec downloads).
At a glance
https://{tenant}/otmmapi/v6/…, where {tenant} is the customer's own OTMM host. Every installation, on-prem or hosted, has its own host, and the spec declares no servers S1. Vendor sample code uses http://localhost:11090/otmmapi S1. Media Widget scripts are served from {otmm-base-url}/otmm/ux-html/… S7. Core DAM: https://digitalassets.{us|ca|au|eu}.api.opentext.com/v1 S8/v6/sessions with username/password (form-encoded). (2) Remote user header or (3) SSO resolver: GET/v6/sessions, after server-side configuration. (4) OAuth 2.0 via OTDS: POST/v6/sessions/oauth2/token with grant_type client_credentials, password or refresh_token S1grant_type=refresh_token on the same endpoint S1info.version: v6, title "OpenText Media Management API": 190 paths, 247 operations, 45 tags, 464 schemas (CE 23.2) S1. Archived copy on DAM Wiki: API spec downloads. Older CE specs (21.2–22.4) are on the portal S5. No Postman collectionAuthentication
Required anti-CSRF header S1. Every request must carry one of the following headers, otherwise it is rejected with HTTP 400:
X-Requested-By: <session id>otmmauthtoken: <message digest>Authorization: <access token>
Session login (Basic) S1
- POST
/otmmapi/v6/sessionswith form fieldsusernameandpassword. - The response sets a
JSESSIONIDcookie and returns a session object whosemessage_digestis the user token. - Send either the cookie or the header
otmmauthtoken: <digest>on later calls. - Log out with DELETE
/v6/sessions.GET/DELETE/v6/users/me/sessionslists or kills all of the user's sessions.
Remote user header / SSO resolver S1
- Configure on the server ("Configuring Remote User Header" and "Configuring Single Sign-On Resolver" in the OTMM Integration Guide, Behind login), then call GET
/v6/sessionsto get a session. - POST
/v6/sessions/otdssessions(target_resource) returns an OTDS ticket for another resource. - The Media Widget authenticates with an OTDS ticket in a configurable SSO header, or with an OTDS OAuth token S7.
OAuth 2.0 (OTDS) S1
- Register an OAuth client in OpenText Directory Services (OTDS) to get a client ID and secret. The procedure is in the OTDS documentation and in "Using OAuth2.0 to Access OTMM REST APIs" (Integration Guide), both Behind login.
- POST
/otmmapi/v6/sessions/oauth2/token(form-encoded):client_id,client_secret,grant_type=client_credentials|password(+username,password) |refresh_token(+refresh_token). The spec describes it as "intended for server-to-server authentication" and equivalent to logging in. - POST
/v6/sessions/oauth2/tokens/validatevalidates a token (since CE 23.2) S1 S5. - Unverified Header scheme contradiction. The spec says to send
Authorization: Basic [access_token], and its sample token is an OTDS-issued JWT obtained withclient_credentialsS1. OpenText's ownpyxecmclient sendsAuthorization: Bearer <token>after apasswordgrant S14. Which schemes a given server accepts is Unknown without testing.
| Mechanism | Endpoint | Credentials | Carried as |
|---|---|---|---|
| Session (Basic) | POST/v6/sessions | username + password | JSESSIONID cookie or otmmauthtoken header |
| Remote user header | GET/v6/sessions | upstream proxy header (server-configured) | session |
| SSO resolver / OTDS ticket | GET/v6/sessions; POST/v6/sessions/otdssessions | OTDS SSO | session / OTDS ticket |
| OAuth 2.0 | POST/v6/sessions/oauth2/token | OTDS client ID + secret (± user) | Authorization header |
Core resources
Paths are relative to https://{tenant}/otmmapi. Inventory parsed from the CE 23.2 spec S1.
| Resource | Endpoints | Notes |
|---|---|---|
| Sessions & auth | POST/GET/DELETE/v6/sessions; POST/v6/sessions/oauth2/token; POST/v6/sessions/oauth2/tokens/validate; POST/v6/sessions/otdssessions | See Authentication |
| Assets (read) | GET/v6/assets (by selection context), GET/v6/assets/{id}, /versions, /latestversion (by original_asset_id), /parents, /collections, /relatedassets, GET/v6/assets/recent, GET/v6/assets/nofolders (orphans) | load_type = full | system | metadata | inherited_metadata | custom; level_of_detail=slim drops field definitions |
| Assets (write) | POST/v6/assets (multipart, returns a job handle); PATCH/v6/assets/{id} (lock_strategy), bulk PATCH/v6/assets; PUT/v6/assets/{id}/state and PUT/v6/assets/state (lock, unlock, check-out, cancel check-out, delete, undelete); POST/v6/assets/{id}/duplicate, POST/v6/assets/duplicate; links POST/DELETE/v6/assets/links | Writes are typically asynchronous jobs |
| Content & renditions | GET/v6/assets/{id}/contents (rendition_type = thumbnail, preview, pdf_preview, mac_resource, default_thumbnail, default_preview, video_rollover, 3d_preview; disposition=attachment); GET/v6/assets/{id}/contents/spin360; POST/v6/assets/{id}/contents (add/replace renditions); GET/v6/renditions/{id}; GET/v6/renditions/{id}/contentsignedurls; POST/v6/renditions | Signed URLs fetch content straight from the storage provider (since CE 22.x) S5 |
| Metadata schema | GET/v6/metadatamodels[/{id}] (by object_type), /v6/metadatafields[/{id}], /v6/metadatafieldgroups[/{id}], /v6/lookupdomains[/{id}], /v6/cascadinggroups/{id}[/lookupvalues], /v6/metadatalocales | Read-only: no field or model creation in the API |
| Folders | GET/v6/folders/rootfolders, GET/v6/folders/{id}, /children, /assets, /folders, /parents, /templates; POST/v6/folders/{id} (create a child); PATCH/DELETE/v6/folders/{id}; PUT/v6/folders/{id}/children (add/move/remove); PUT…/state; GET/v6/foldertypes[/{id}] | Folders can have several parents |
| Collections | GET/POST/v6/collections; GET/PUT/PATCH/DELETE/v6/collections/{id}; GET/v6/collections/{id}/assets; PUT/v6/collections/assets (add); POST…/{id}/publish, DELETE…/{id}/unpublish; promotions, rating, thumbnail, microsite templates | Published collections feed Digital Hub microsites |
| Search | GET/POST/v6/search/text; GET/POST/v6/search/database; GET/POST/v6/search/saved/{id}; GET/v6/search/text/suggestions; GET/v6/search/collections/text, GET/v6/search/tags/text (23.2) | See Search & querying |
| Saved & recent searches | /v6/savedsearches (text, database, copy; CRUD, thumbnail); /v6/recentsearches (23.2) | |
| Search configuration | /v6/searchconfigurations, /v6/facetconfigurations, /v6/searchoperators, /v6/searchscopes, /v6/colorfilters | Read-only |
| Jobs (async & workflow) | GET/POST/PATCH/v6/jobs; GET/PATCH/v6/jobs/{id}; PUT/v6/jobs/{id}/state; POST/v6/jobs/imports, /exports, /publish; PUT/v6/jobs/imports/{import_job_id}, /checkins/{id}, /attachcontents/{id}; GET/v6/jobs/definitions, /{name}/forms, /{id}/assets, /{id}/tasks, /{id}/users, /{id}/exports/contents | Import, export, publish and workflow jobs share this resource |
| Tasks (review/approval) | GET/v6/tasks, GET/PATCH/v6/tasks/{id}, PATCH…/assets, PATCH…/assignees, PUT/v6/tasks/{id}/assets/{asset_id}/state (approval), comments GET/PUT/DELETE | |
| Exports | POST/v6/exports/schedules; GET/v6/transformers (export/import/delivery transformers) | Scheduled media delivery |
| Transfer | GET/v6/transferschemes, POST/v6/transferschemes/{scheme}/sessions | Accelerated or alternative transfer schemes |
| Video | GET/v6/videos/{id}/insights, /keyframes, /subclips, /speech/search, /speech/srtfile; PATCH/DELETE…/speech; POST…/subclips; PATCH/v6/videos/proxies; PATCH…/insight/persondetails | AI video insights |
| Usage tracking | POST/v6/assets/{id}/usage, GET/v6/assets/{id}/usages; GET/POST/v6/usageapplications, /v6/usagecategories | Added in CE 22.x S5 |
| Products | GET/POST/PUT/DELETE/v6/products, GET/v6/products/{id}; GET/v6/assets/{id}/productassignments, POST/v6/assets/productassignments, PUT/DELETE/v6/assets/{id}/products | Added in CE 23.2 S5 |
| Security / rights | GET/v6/securitypolicies[/{id}[/permissions]]; GET/v6/featurepermissions[/me]; GET/v6/intervalprofiles | Read-only; assigning policies is done through asset updates |
| Users & groups | GET/v6/users (filters by name, login, department, role), GET/v6/users/me, GET/v6/users/{id}, PATCH/v6/users/{userid}/updaterole; GET/v6/usergroups/me, GET/v6/usergroups/{id}/children; GET/v6/usertypes | No user creation (OTDS owns identities) |
| Subscriptions | POST/DELETE on /v6/assets[/{id}]/subscriptions, /v6/folders/{id}/subscriptions, /v6/collections[/{id}]/subscriptions | Notification channel Unknown |
| Integration Service | GET/POST/PUT/v6/integrationservices, DELETE/v6/integrationservices/{id}, PATCH…/{id}/state | Registers publication connectors S6 |
| Hightail | POST/v6/hightail/spaces, GET/v6/hightail/contacts, token endpoints | Creative collaboration |
| Audit | GET/v6/auditactivity/{assetId}/activityhistory, GET/v6/auditactivity/{sequenceId}/details, filter and sort options | |
| System | /v6/systemsettings, /v6/systemdetails (+ helpURL), /v6/systemannouncements/me, /v6/preferences, /v6/brandings, /v6/importtemplates, /v6/linktypes |
Not exposed in the documented API (checked against the CE 23.2 spec S1): creating metadata models or fields, user/group provisioning, security-policy authoring, workflow (job definition) authoring, SSO configuration, and an analytics or reporting API.
Data model
S1 unless noted.
- Asset.
- Identified by
asset_id, a 40-character hex string in examples S14. Versions share anoriginal_asset_id. - Key properties:
name,mime_type,content_type/content_sub_type,metadata_model_id,metadata,security_policy_list,path_list(all folder paths),master_content_info,rendition_content,asset_state,content_state,locked,checked_out,deleted,expired,latest_version,delivery_service_url,streaming_url,progressive_download_url,deep_zoom_info,asset_color_infos,product_associations,review_info_collection.
- Identified by
- Metadata. Each asset follows a metadata model, a list of fields and field groups. A metadata field has an
id(system id such asARTESIA.FIELD.…),data_type,edit_type,domain_id(lookup domain),cascading_group_id, andrequired,multilingual,searchable,facetableandsortableflags. Values can be scalar, tabular or multilingual. - Content.
ContentInfodescribes the master file and each rendition:id,mime_type,content_size,width/height,url(for example/otmmapi/v6/renditions/{rendition_id}),content_signed_url,content_checksumS1 S14. - Containers. Folders (with folder types) and collections hold assets. Selection contexts (asset IDs, folder, search, collection) target bulk operations and can filter by permission (
ASSETVIEW_PERM,EXPORT_PERM,METAEDIT_PERM…). - Naming. JSON uses snake_case, and resources are wrapped (for example
asset_resource.asset). Java client classes map camelCase to snake_case through EclipseLink MOXy providers shipped with the server. - Heritage. Class names in the spec still read
com.artesia.search.*, the SDK JAR isTEAMS-sdk.jarand the default search plugin isARTESIA.PLUGIN.SEARCH.SOLR.V1. These names trace back to the Artesia TEAMS platform S1 S18. - Errors. Failed calls return
{"exception_body": {"http_response_code", "message" (localised), "debug_message", "failed_ids", "error_code"}}.
Search & querying
| Aspect | Behaviour S1 |
|---|---|
| Engines | Text search (/v6/search/text, Solr plugin by default; search_plugin_id can be overridden) and database search (/v6/search/database) |
| Keyword query | keyword_query with keyword_scope_id: 1 = metadata, 2 = file content, 3 = both (default). default_operator is and/or; the server default comes from setting [SEARCH\SERVER] DEFAULT_OPERATOR |
| Structured conditions | search_condition_list: a JSON list of typed conditions (com.artesia.search.SearchScalarCondition, …TabularCondition, …FulltextCondition, …MetadataCondition, …CustomCondition) with metadata_field_id, relational_operator_id, value, parentheses and AND/OR. A search_config_id can be used instead, pointing to an admin-defined search configuration |
| Filters | keyword_filter, folder_filter (+ folder_filter_type = all | direct), collection_filter, color_filter, facet_restriction_list |
| Facets | generate_facets=true with a facet_config_id; generate_type_counts; group_by = content_type | metadata_model |
| Return shape | return_type = count | ids | objects | all; load_type and metadata_to_return decide which fields come back |
| Sorting | sort is a comma-separated list of field IDs with optional asc_ / desc_ prefixes |
| Suggestions | GET/v6/search/text/suggestions?input=…&max_suggestions=… |
| Paging | after / before + limit. pyxecm pages with after += hits and limit 200 S14. Maximum page size and deep-paging limits: Unknown |
| Multilingual | multilingual_language_code searches a given language variant of multilingual fields |
Uploads & binaries
Create assets with content S1
- POST
/v6/assetsasmultipart/form-data(UTF-8 file names):asset_representation(JSON) and/orimport_template_id,parent_folder_id, the file part(s), optionalno_content=truefor metadata-only assets, and optional review job/task IDs. - The call creates a job and returns a
job_handle.job_id. Poll GET/v6/jobs/{id}until it completes, or pass acallbackurl. - Security: if only an asset representation is given, the user needs "Apply/Remove Security Policy" permission for every policy it assigns. Policies inherited from an import template do not require it.
Staged import S1
- POST
/v6/jobs/importscreates an import job. - POST
/v6/renditionsuploads the content against that job. - PUT
/v6/jobs/imports/{import_job_id}registers the assets.
Related calls: PUT/v6/jobs/checkins/{import_job_id} adds a new version to existing assets; PUT/v6/jobs/attachcontents/{import_job_id} attaches content to metadata-only assets.
Large files. Transfer schemes (/v6/transferschemes) negotiate alternative transfer sessions S1. The OpenText Accelerated File Transfer add-on handles very large uploads and downloads S16. Size limits: Unknown.
Downloads S1
- GET
/v6/assets/{id}/contentsreturns the original, or a rendition whenrendition_typeis set. - GET
/v6/renditions/{id}returns a rendition by ID. GET/v6/renditions/{id}/contentsignedurlsreturns a signed URL served directly by the storage provider. - Export jobs (POST
/v6/jobs/exports, then GET/v6/jobs/{id}/exports/contents) package assets, with transformers, for delivery. - For channel delivery, Adaptive Media Delivery serves rendition URLs by profile, and the Media Widget returns AMD link URLs S16 S7.
Events & webhooks
- Job callbacks are the only push mechanism documented S1:
- Add
callbackurl=<url-encoded URL>to import/export (and other job) requests, withcallbackmethod=GET(sends job ID and status as parameters) orcallbackmethod=POST(adds asset IDs and error details). - Query parameters prefixed
header_are sent back as HTTP headers. This is the only built-in way to pass a shared secret. - Custom callback authentication: implement the Java interface
com.opentext.job.notification.JobCallbackNotifier, register it as a system setting under[JOB\CONFIG], and addcallbackauthscheme=CUSTOM&callbackclientId=<setting>to the callback URL. - Signing, retries and ordering: Not public.
- Add
- Subscriptions (assets, folders, collections) let users follow changes S1. How notifications are delivered (email or in-app) is Behind login.
- Integration Service (outbound publishing) S6:
- A standalone microservice built on Apache Camel. Custom Java integrations implement
com.opentext.is.service.interfaces.IntegrationService.publishContent(PublishJobRequest). - The service calls back OTMM with
COMPLETED,FAILEDorCOMPLETED_WITH_ERRORSplus the object and audit URLs. - Integrations are packaged as JARs and registered through
/v6/integrationservices. On managed deployments, the Service Delivery Manager must be involved.
- A standalone microservice built on Apache Camel. Custom Java integrations implement
- Media Widget audit events. IDs 8060 "Asset Placed" and 8061 "Asset Placement Removed" go to the OTMM audit trail. They must be added to the
ASSET_EVENT_IDS_FOR_AUDITsetting S7.
Limits & quirks
- No published spec after CE 23.2. The developer portal's newest OTMM spec dates from 2023-07-31, while the product is at CE 26.2 S2 S17. Endpoints added after 23.2: Unknown.
- Mandatory CSRF header. Calls without
X-Requested-By,otmmauthtokenorAuthorizationfail with HTTP 400, even when a validJSESSIONIDcookie is present S1. - Basic vs Bearer in the OAuth header (see Authentication) Unverified S1 S14.
- Version-path drift in the docs. The CSRF sample targets
/otmmapi/v2while every resource is/v6S1. Only v6 and the previous version are supported. - Parameters as JSON strings. Search conditions, data-load requests and selection contexts are JSON objects serialized into query or form parameters, not request bodies, so URLs can get very long S1.
- Asynchronous writes. Asset creation, import, export, check-in and publish return job handles, so clients must poll jobs or use callbacks S1.
- Javadocs as contract. Fields, methods and classes missing from the Javadocs are internal and may change without notice S1.
- CORS. Browser calls (for example, an embedded Media Widget) need the origin in the
CORS_ORIGIN_LISTsystem setting. OpenText advises against*S7. - Licensing and access. In the G-Cloud offer, the API "is not designed for End Users" and is reached through a Professional Services engagement S33. Rate limits and quotas are Not public.
- Sample secrets in the spec. The published spec embeds a sample OTDS JWT, with an internal IP address as
iss, in its prose S1. It is vendor sample data, kept verbatim in the archived copy on DAM Wiki (API spec downloads).
SDKs, tools & code samples
| Library | Language | Maintainer | Status |
|---|---|---|---|
otmm-rest-representations.jar (+ TEAMS-sdk.jar, TEAMS-common.jar, ot-transfer-scheme.jar, Apache Commons, EclipseLink MOXy 2.7.6) | Java (Jersey client examples) | OpenText, shipped inside each OTMM installation | Not on Maven Central. Javadocs in the Programmer's Guide (Behind login) S1 |
pyxecm, module otmm | Python | OpenText (GitHub opentext, Apache-2.0) | v3.7.0 on PyPI (2026-09-29). Read-oriented: OAuth password grant, lookup domains, assets, text search, renditions, download. Built to migrate OTMM assets into Extended ECM S13 S14 |
Media Widget (all-in-one-embed.js) | JavaScript embed | OpenText, served by the OTMM server | Documented on the portal up to 22.4. A sample app is on My Support (Behind login) S7 |
| qibb OTMM node | Low-code media workflow | qibb (third party) | Session, header, SSO and OAuth auth S36 |
Community repos (for example joaquinOnSoft/OTMMAssetUploader, access-otmm-api-from-node-js) | Java, Node.js | Individuals | Small, mostly 2020–2023 S39 |
No official JavaScript/TypeScript, .NET or PHP SDK was found S1 S39.
Core DAM API
A separate product with a separate, much smaller API S8 S9 S10.
| Spec | OpenAPI 3.0.1 "Core DAM API" v1.0.0 (YAML): 9 paths, 12 operations; published on the portal 2025-08-19. Archived copy on DAM Wiki: API spec downloads S8 |
|---|---|
| Hosts | https://digitalassets.us.api.opentext.com, .au., .ca., .eu. (+ /v1/…) S8 |
| Auth | OpenText Cloud OAuth 2.0. An extension app is created in the developer Admin Center, then POSThttps://{region}.api.opentext.com/tenants/{tenant_id}/oauth2/token with JSON {client_id, client_secret, grant_type: "client_credentials"} returns a JWT used as a Bearer token S9. A Core DAM subscription is two subscriptions: Core DAM, for distribution through the Digital Assets API, and the embedded Core Content, for creating and managing content. Each needs its own extension app and token S9 |
| Endpoints | GET/v1/assets (filter=name:…,path:…, load_type = SLIM | FULL | NORENDITIONS, delivery-service URLs per profile), GET/v1/assets/{asset_id}, GET/v1/profiles (asset profiles), GET/v1/folders/{folder_id}/children, GET/POST/v1/collections, GET/POST/DELETE/v1/collections/{collection_id}/assets, POST/v1/assets/{asset_id}/usage, POST/v1/assets/usage, GET/v1/assets/usage/form S8 |
| Pagination | offset + count (default 25). offset must be a multiple of count S8 |
| Uploads | Not in the Digital Assets API. Upload through Core Content: POSThttps://css.{api_host}/v3/files/fromStream?tenant={tenant_id} (multipart) returns a blob ID. Then POSThttps://{api_host}/cms/instances/file/ccm1_dam_brand_assets with the blob ID and the "Digital asset library" folder as parent. Edit metadata (traits ccm1_dam_*) with PATCH…/instances/file/ccm1_dam_brand_assets/{id}. Responses are HAL+JSON S10 |
| Webhooks, rate limits | Not public |
Changelog of the API
| Date | Change | Source |
|---|---|---|
| 2025-08-19 | Core DAM API spec v1.0.0 published on the developer portal | S8 |
| 2023-07-31 | CE 23.2 spec (247 operations). Added products and product assignments, recent searches, collection and tag text search, OAuth token validation | S2 S1 S5 |
| 2023-01-12 | CE 22.4 spec (231 operations). Compared with 21.2: asset usage tracking, usage applications and categories, Integration Service endpoints, publish jobs, signed rendition URLs, latest-version lookup, video person edits | S5 |
| 2021-08-09 | CE 21.2 spec (213 operations), the first OTMM spec on the developer portal | S5 S4 |
| Unknown | v6 became the current resource version. Earlier versions are unsupported beyond "the previous version" | S1 |