Scope: the public REST API of Acquia DAM (the Widen Collective platform, still labelled "Acquia DAM (Widen)" in the docs), versions 2.0 and 1.0, plus the MCP server and webhooks. The older Acquia DAM Classic product and its API are out of scope.
At a glance
Access-Control-Allow-Origin: * S1. No GraphQL found. A read-only MCP server exists on each tenant (see AI & agent ecosystem) S14https://api.widencollective.com/v2/… (one shared host for all tenants) S1 S15; v1: https://{tenant}.widencollective.com/api/rest/… S3 S15; OAuth consent page: https://{tenant}.widencollective.com/allowaccess S1; MCP: https://{tenant}.acquiadam.com/mcp (the tenant's DAM URL + /mcp) S14; CDN embed links on embed.widencdn.net / s-embed.widencdn.net S1size_in_kbytes (use size_in_bytes), "templated" embed URLs, v1 GET/api/rest/assetgroups S1 S3. Opt-in new behaviours via X-Widen-Api-Toggle headers (list at GET/v2/toggles) S1x-oauth-basic as password). Tokens come from a personal access token generated in the Admin app, or from OAuth 2.0 authorization_code (+ refresh_token) with a client ID/secret issued by Acquia support S1. v1 additionally documents the password grant, which was removed from v2 S3 S7X-Ratelimit-Limit: 50/second header observed S17. Separate monthly call allowance (billing, not throttling) — see Limits & quirksAuthentication
- Generated in the DAM application under Admin → Global Settings → API Setup; it inherits the permissions of the user who generated it.
- Sent as
Authorization: Bearer <token>(preferred) orAuthorization: Basic base64(<token>:x-oauth-basic).
OAuth 2.0 (third-party apps) S1 S7
- Client ID (format
…app.widen.com) and secret are obtained out of band from Acquia (Widen) support; there is no self-service app registration. - Redirect the user to
https://{tenant}.widencollective.com/allowaccess?client_id=…&redirect_uri=…&state=…(stateoptional). The user signs in if needed and approves the client on an "Allow Access" page. - Acquia DAM redirects to
redirect_uriwithcode(prefixwac_) andstate. - POST
https://api.widencollective.com/v2/oauth/access-tokenwith JSON{client_id, client_secret, grant_type: "authorization_code", authorization_code}— no other auth needed. Response:access_token,token_type: "Bearer", plusrefresh_tokenandexpires_in(seconds) when the client uses refresh tokens. - Refresh: same endpoint with
grant_type: "refresh_token"andrefresh_token(prefixwrt_); a new refresh token is returned and the old one is consumed.
| Grant | v2 | v1 |
|---|---|---|
authorization_code | Yes | Yes (client credentials in a Basic header) |
refresh_token | Yes, only for clients configured by support | No (v1 tokens do not expire) |
password | Removed for security reasons S7 | Documented, "only if authorization_code is not possible" S3 |
client_credentials | Not documented | Not documented |
Revocation S1 S6: DELETE/v2/oauth/access-token invalidates the calling token (v1: POST/api/rest/oauth/logout); deleting the user or disabling the integration also disables its tokens.
Token prefixes seen in vendor examples: wat_ access token, wac_ authorization code, wrt_ refresh token S1.
Core resources
v2 paths are relative to https://api.widencollective.com; v1 paths to https://{tenant}.widencollective.com. Inventory parsed from the specs S1 S3.
| Resource | Endpoints | Notes |
|---|---|---|
| Asset search | GET/v2/assets/search, GET/v2/assets/search/scroll | Quick-search syntax, facets, expands; see Search & querying |
| Asset detail & versions | GET/v2/assets/{id}, GET/v2/assets/{id}/versions, GET/v2/assets/{id}/versions/{version_id} | expand= adds metadata, embeds, thumbnails, security, status, tags, ai_tags… |
| Asset lifecycle | DELETE/v2/assets/{id} (to trash), DELETE/v2/assets/{id}/permanent, PUT/v2/assets/{id}/filename | |
| Metadata values | GET/PUT/v2/assets/{id}/metadata | Only sent fields change; patch= restricts the update to listed fields |
| Tags | PUT/v2/assets/{id}/tags/add, POST/v2/assets/{id}/tags/remove | Human tags; AI tags are read-only (ai_tags expand) |
| Metadata schema | GET/v2/metadata/fields/viewable (filter by field_types, display_name_starts_with, display_name_after, limit ≤ 100); v1 GET/api/rest/metadata/types, PUT/api/rest/asset/changemetadatatype/asset/{assetuuid}/type/{typeuuid} | Only fields the user may view |
| Controlled vocabularies | GET/POST/v2/metadata/{displayKey}/vocabulary; GET/PUT/DELETE/v2/metadata/{displayKey}/vocabulary/{existingValue}; v1 POST/api/rest/metadata/field/uuid/{uuid}/values | Full CRUD on list values |
| Security / rights | GET/PUT/v2/assets/{id}/security; GET/v2/assets/assetgroups | Asset groups + release/expiration dates; at least one value required |
| Categories (folders) | GET/v2/categories/{path} (read); v1 POST/api/rest/category, PUT/api/rest/category/uuid/{uuid}, POST/api/rest/category/assets, GET/api/rest/category/categoryTree | Category creation and asset assignment are v1-only |
| Collections | GET/v2/collections (type global | private | shared); v1 POST/api/rest/collection, POST/api/rest/collection/assets, list/detail endpoints | Creation and membership are v1-only |
| Uploads | POST/v2/uploads; POST/v2/uploads/chunks/start|upload|complete|status; GET/v2/uploads/profiles; POST/DELETE/v2/assets/{id}/alternatepreview | Upload profile required; see Uploads & binaries |
| Renditions / delivery | embeds and thumbnails expands; v1 GET/api/rest/asset/uuid/{uuid}/embed/code, /embed/link, /preconversions; v1 orders (POST/api/rest/order, …/zip, POST/api/rest/conversion/order/profile/uuid/{uuid}) | Orders = packaged downloads with conversions |
| Users | GET/v2/user (current), GET/v2/user/{id}; v1 GET/api/rest/user/address | No user/group provisioning endpoints |
| Analytics | POST/v2/analytics/assets/downloads|shares|views; POST/v2/analytics/events/query (event types: download, asset_view, embed_view, share, collection_share, asset_upload, login, portal_view, asset_search) | Date range within 3 years; up to 10,000 results per page |
| Usage | GET/v2/usage/api | Month-to-date API request count; calls to it are not counted S8 |
| Webhooks | GET/POST/v2/webhooks/configurations; GET/PUT/DELETE/v2/webhooks/configurations/{id}; GET…/{id}/ping | See Events & webhooks |
| Workflow (proofing) | POST/v2/workflow/projects; GET/DELETE/v2/workflow/projects/{project_id}; deliverables CRUD, PUT…/deliverables/{id}/close, POST…/deliverables/{id}/proofs; GET…/support-files; GET/POST/DELETE/v2/workflow/webhooks | Workflow add-on |
| Products (Entries PIM) | POST/v2/products, POST/v2/products/search, GET/DELETE/v2/products/{id}, PUT…/attributes|featured-image|parent-product|product-category|product-type|rename; GET/v2/products/channels/{channel_id}; GET/v2/attributes, GET/v2/attributes/{id}/vocabulary; GET/v2/product-categories, GET/v2/product-types; GET/v2/channels[/{channelId}] | Entries add-on |
| Embedded search UI | GET/v2/integrations/url | Signed URL to the Search Connector iframe, valid 24 h |
| Integration links | v1 GET/POST/api/rest/integrationlink, DELETE/api/rest/integrationlink/{uuid} | Register where an asset is used externally |
| Misc. | GET/v2/toggles; v1 GET/api/rest/fileformats, GET/api/rest/uploadprofile |
Not exposed in the documented API (checked against both specs S1 S3): user/role/group administration, SSO configuration, portal management, metadata field creation (only vocabulary values), saved searches, Templates. Whether more exists behind feature toggles is Unknown.
Data model
S1 unless noted.
- Asset — identified by a UUID
id; alsoexternal_id,version_id,current_version,filename,created_date,last_update_date,file_upload_date,deleted_date,released_and_not_expired,_links. Dates are ISO-8601; list indices 0-based. - Metadata —
metadata.fieldsis a map of field display key → array of strings (e.g.{"keywords": ["…"], "description": ["…"]}). Display keys never change, unlike display names, so integrations should use them S11. Themetadata_infoexpand returns the asset's metadata type (field_set) and its fields withfield_type,controlled_vocabulary,editable,requiredS1. Each asset has exactly one metadata type, assigned at upload S27. - Field types in the API:
selection_list,selection_list_multi,text,text_multi_line,date,numeric, checkboxes… S1; UI families: date, numeric, limited text (255 chars), text (1,280 chars), text area/long text, checkbox, dropdown (UI shows up to 249 values), autocompleter, palette S27. - Security —
asset_groups[](every asset needs at least one),release_date,expiration_dateS1 S18. - Taxonomy — hierarchical categories addressed by path (slashes in names escaped as
%5C%2F), collections (global/private/shared), human tags and machine ai_tags (both added to API responses in June 2026 S31). - Files —
file_properties(format,format_type,size_in_bytes, image/video properties);thumbnails(signed URLs withvalid_until, URL syntax not guaranteed);embeds(named CDN renditions such asoriginal,640px-landscape);status.upload_progress∈pending,verifying,complete. - Products (Entries) — products with typed attributes (
text,rich_text,asset,single_controlled_vocab,multi_controlled_vocab), attribute groups, product types, categories, parent/variant links, channels.
Search & querying
| Aspect | Behaviour |
|---|---|
| Query language | query= uses the same quick search syntax as the UI S1: implicit AND, OR, * wildcards, quoted phrases, -(term) exclusion, field:value, {term} exact field match, field:(isempty) / field:-(isempty), date expressions such as du:[after MM/DD/YYYY] S28 |
| Field addressing | Use the field display key (assetinfo:photo), not UI shortcuts or display names, which can change S11 |
| Options | search_document_text (search inside documents), include_natural_language_results (AI natural-language search), include_archived, include_deleted S1 |
| Facets | facet=file_types,categories,metadata; up to 25 values per facet with counts and a ready-made search_query for refinement; facets only on the first page of a scroll S10 |
| Sorting | sort= field name, - prefix for descending; default -created_date S1 |
| Diagnostics | Response includes query_explained, query_syntax_ok, sort_explained, total_count S1 |
| Page size | limit default 10 (100 with scroll), max 100 S1 |
| Deep pagination | offset cannot exceed 10,000; for more, use scroll: start with scroll=true, then call /v2/assets/search/scroll?scroll_id=… within scroll_timeout (ms) until an empty page. Scroll is sequential, meant for batch sync, and returns each asset once; ties on the sort field can cause duplicates/skips with offset paging S1 S9 |
Uploads & binaries
Single request S1 — POST/v2/uploads (multipart/form-data): profile (upload profile name, required: profiles set initial metadata and security), one of file | url (public URL to fetch) | file_id (from a chunked upload), optional filename and metadata (JSON in the Update Metadata format).
- POST
/v2/uploads/chunks/start→session_id, valid 7 days. - POST
/v2/uploads/chunks/uploadper part:session_id,chunk_number(1–10,000),file(5 MB minimum except the last chunk, 100 MB maximum) → returns atag. Up to 40 concurrent chunk operations S6. - POST
/v2/uploads/chunks/completewith all tags →file_id; POST/v2/uploads/chunks/statusto check progress. - POST
/v2/uploadswithfile_idto create the asset. Some accounts do not have chunked upload enabled (error message tells you to contact support) S1.
v1 upload — POST/api/rest/asset (uploadProfileUUID, file, filename) is limited to 5 GB; larger files and chunking require v2 S3.
After upload, poll GET/v2/assets/{id}?expand=status until upload_progress is complete before relying on embeds and previews S1. A new version of an existing asset cannot be uploaded through any documented v2 or v1 endpoint; version history is read-only and requires the AssetVersioning feature on the site S1 S3 Unverified (absence inferred from the specs).
embedsexpand: CDN URLs (embed.widencdn.net) for the original and configured sizes; these links are served by the CDN and are not counted against the rate limit S1.- Custom renditions follow a URL convention documented in the help center (size, crop, format parameters); "templated" embed URLs are deprecated S1.
thumbnailsexpand: short-lived signed URLs (125–2048 px) S1.- v1 orders package assets (with conversions) into a ZIP: POST
/api/rest/order→ POST/api/rest/order/uuid/{uuid}/zip→ poll GET…/zipfor the link S3.
Events & webhooks
- Prerequisites: an admin enables the webhook feature (Admin → Global Settings → Features, "Integrate" section) and grants the role permission "Administrate Webhooks" S13.
- Managed only through the API: POST
/v2/webhooks/configurationswithdelivery_url,event_type, optionalsecret_key(≤ 256 chars) and, for metadata-value events, optionalmonitored_metadata_fields(display keys; 403 if the user cannot see a field) S1. - Event types (9):
asset_created,asset_deleted,asset_version_added,asset_categories_updated,asset_tags_updated,asset_asset_groups_updated,asset_release_date_updated,asset_expiration_date_updated,asset_metadata_value_updatedS1. The metadata-value event was added in June 2026 S31. - Payload (e.g.
asset_created):webhook_configuration_id,webhook_delivery_id, event context (acting user),asset_id,event_type,date_createdS12; update events add achangeobject, deletions adate_deletedS1 (spec examples). TypeScript event types ship in the SDK S15. - Signing: if a secret key is set, every delivery carries an HMAC hex-digest signature (
signing_enabled: trueon the configuration) S1 S12. The header name and hash algorithm are not stated in the public docs — Unknown. - Testing: GET
/v2/webhooks/configurations/{id}/ping; configurations exposedelivery_enabled,last_delivered_date,last_pinged_dateS1. - Retries, ordering and delivery guarantees: Not public.
Workflow webhooks S1 — POST/v2/workflow/webhooks with event ∈ PROJECT_CREATED, DELIVERABLE_STATUS_CHANGED and a target URL; list and delete endpoints; no signing documented.
Native automations — Acquia also uses webhooks internally for event-driven "task automation" integrations (August 2026) S32.
Limits & quirks
- Monthly API call allowance (billing). For Workgroup plans, calls not authorized through an Acquia OAuth client are capped at 500,000/month (1,000,000 with Entries); overages are billed, Acquia-managed and authorized third-party integrations are excluded S18. The pricing page lists 500k (Workgroup), 1M (Mid-Market) and "Standard API access" (Enterprise) S19. The FAQ says the allowance applies to customers who joined from 2022-04-01 and Entries adds 500,000 calls S6 S8. There is no service interruption when exceeded S8. Unverified The v2 spec still says the 50 calls/s rate is "the only limitation" S1 — true for throttling, but not for billing.
- Rate limit history: raised from 10 to 50 calls/s in February 2022 S36.
- Swapped parameter descriptions: in the v2 spec,
include_archivedis described as returning deleted assets andinclude_deletedas returning archived ones S1 Unverified (documentation bug; actual behaviour not tested). - Inconsistent token examples: the security-scheme examples use an authorization-code prefix (
wac_…) as a bearer token, while the intro useswat_…S1. - Split surface: category/collection creation and membership, orders, embed-code generation, integration links and metadata-type changes remain v1-only S1 S3; the official SDK therefore calls both versions and needs the tenant key for v1 S15.
- Offset ceilings: search offset ≤ 10,000 S9; collections and products list
offset≤ 9,999 in the schema S1. - Security update caveat: PUT
/v2/assets/{id}/securitywithpatch=allnulls any property not sent; an asset left without security values becomes unavailable S1. - Metadata search by display name breaks when admins rename a field — use display keys S11.
- Chunked upload limits: 5–100 MB per chunk, 10,000 chunks, session 7 days S1. UI uploads are limited to 500 GB per file S26.
- API access is licensed: "REST API" is an add-on in the product guide and the MCP server requires the REST API feature S18 S14.
SDKs, tools & code samples
| Library | Language | Maintainer | Status |
|---|---|---|---|
acquia-dam-sdk | TypeScript / JavaScript (ESM + CJS, fetch-based) | Acquia (Widen GitHub org) | v1.0.3, last push 2026-07-20; components analytics, assets, attributes, categories, collections, metadata, orders, products, searchConnector, usage, users, webhooks, workflow; no built-in retry or OAuth token exchange S15 S16 |
acquia_dam | PHP (Drupal module) | Acquia + community | 1.1.18 (2026-09-09); Drupal 9.5/10/11; Media Library, webhook-based sync S53 S54 |
widen-sso-examples | Samples | Widen GitHub org | Last push 2024-03-28 S79 |
| Zapier "Acquia DAM" app | No-code | Unknown | One action: Upload Asset S56 |
No official Python, PHP (outside Drupal), Java or .NET SDK was found S15 S79.
Changelog of the API
| Date | Change | Source |
|---|---|---|
| 2026-07 (notes published 2026-08-06) | MCP Server for Acquia DAM (read-only: search, asset details, metadata fields) | S30 S14 |
| 2026-07-20 | SDK 1.0.3: natural-language search parameter, tags/ai_tags expands, metadata-update webhook | S15 |
| 2026-06 (notes published 2026-07-07) | tags and ai_tags in asset search/detail responses; asset_metadata_value_updated webhooks | S31 |
| 2025-05-28 | acquia-dam-sdk first published on npm (repo created 2024-11-07) | S16 S15 |
| 2024-03 (notes published 2024-04-01) | DAM webhooks available through the API | S35 |
| 2022-11 | Faceted asset search (facet parameter) in v2 | S36 S10 |
| 2022-07 | Full OAuth flow and refresh tokens in v2; password grant not carried over | S36 S7 |
| 2022-04-01 | Monthly API call allowance applies to customers joining from this date | S6 |
| 2022-02 | Rate limit raised from 10 to 50 calls/second | S36 |
| Unknown | GET/v2/usage/api released (announcement undated) | S8 |