Scope: the public REST API of the MediaValet SaaS DAM ("NextGen API"), its webhook service SkyHOOK and the Unify Integrations API, all published through an Azure API Management (APIM) gateway at api.mediavalet.com. Everything below comes from the public Postman documentation, the public developer-portal data and unauthenticated probes; no authenticated call was made.
At a glance
https://api.mediavalet.com (single global host; no tenant appears in the host or path of any documented request — how the library is selected is not documented, presumably from the user's token Unverified) S1 S3. SkyHOOK: https://api.mediavalet.com/skyhook; Unify: https://api.mediavalet.com/integrations S8 S12. Identity: https://login.mediavalet.com (issuer https://iam.mediavalet.com) S1 S14. Asset Picker: https://assetpicker.mediavalet.com S1. The APIM export names an http:// server too, but the gateway is used over HTTPS S12client_id:client_secret) S1 S23; plus an APIM subscription key on every call (Ocp-Apim-Subscription-Key header or subscription-key query) S12 S15. Client credentials: "coming soon" per docs Unverified (see Authentication)expires_in: 3600 (1 h) in all documented samples; authorization code valid 60 s; refresh tokens issued with scope offline_access, rotated (a new refresh_token is returned on refresh) S1. Refresh-token lifetime: Not publicopenid api; offline_access optional S1. No fine-grained API scopes: requests run with the MediaValet user's role/group permissions; docs and Help Center require an administrator account (or admin approval) to use the API S5 S21. Since v1.2, an authenticated user lacking permission gets 403 instead of 401 S1/skyhook/subscriptions), 8 event types, CloudEvents 1.0 envelopes, delivery to your HTTPS endpoint or to your own Azure Event Grid topic; endpoint validated by the CloudEvents abuse-protection handshake (HTTP OPTIONS) S1 S24 S26. "Enterprise level": webhooks are listed as an Enterprise Plan feature S6Authentication
Getting credentials S5 S21 S22
- Have a user (ideally admin) account in the MediaValet library to integrate with.
- Register at the developer portal (
developer.mediavalet.com, Azure APIM) and subscribe to a plan under Products — the Developer Plan is included in the MediaValet subscription; the Enterprise Plan goes through the account manager. - MediaValet Support e-mails you to collect the library URL, redirect URIs to whitelist and (if you are not an admin) an admin's approval; it then issues client_id / client_secret and activates the primary/secondary subscription keys visible in your portal profile.
- Postman callback URLs (
https://www.getpostman.com/oauth2/callback,https://oauth.pstmn.io/v1/callback,https://oauth.pstmn.io/v1/browser-callback) are whitelisted by default; other redirect URIs must be whitelisted by Support. Credentials may be shared by several users of the same library working on the same integration S22.
| Endpoint | URL |
|---|---|
| Authorize | GEThttps://login.mediavalet.com/connect/authorize |
| Token | POSThttps://login.mediavalet.com/connect/token (form-encoded; client_secret_basic or client_secret_post) |
| Discovery | https://login.mediavalet.com/.well-known/openid-configuration (also lists userinfo, revocation, introspection, device-authorization, CIBA and PAR endpoints) |
Authorization code flow S1: /connect/authorize?client_id=…&response_type=code&scope=openid api&redirect_uri=…&state=… → user signs in on MediaValet's login page → code returned to the redirect URI → server-side POST/connect/token with grant_type=authorization_code, code, redirect_uri, client_id, client_secret → response {id_token, access_token, expires_in: 3600, token_type: "Bearer"}. Use Authorization: Bearer <token> on API calls.
Resource owner password grant S1 S16: POST/connect/token with grant_type=password, username, password (the user's DAM login), scope=api (or openid api), and Authorization: Basic base64(client_id:client_secret). MediaValet discourages it for security reasons but calls it the preferred option for non-interactive integrations; the official GitHub sample uses only this flow.
Refresh S1: grant_type=refresh_token + client credentials; returns new access_token, id_token and a new refresh_token.
Every API request also needs the APIM subscription key: without it the gateway answers 401 with WWW-Authenticate: AzureApiManagementKey … name="Ocp-Apim-Subscription-Key" S15; the Unify API description states both the IAM JWT and the subscription key are mandatory S12.
Unverified Grant-type inconsistencies. The docs' parameter table lists only
authorization_codeandrefresh_tokenas grant types, the same page documents the password grant, the Help Center lists "Auth Code + Resource Owner Password" and says Client Credentials is "COMING SOON" S1 S23, while the public OIDC discovery document advertisesclient_credentials,implicit,device_code, CIBA and token-exchange grants and PKCE (S256,plain) S14. Discovery reflects the identity server's capabilities, not necessarily what is enabled for API clients — treat client credentials and PKCE as not officially supported until documented. Scopes advertised in discovery includeapi:service_principal,iam.adminandiam.provisioning(undocumented) S14.
Core resources
Paths are relative to https://api.mediavalet.com. Counts are APIM operations (NextGen API) per first path segment S9; examples from the Postman collection S2.
| Resource | Endpoints | Notes |
|---|---|---|
| Home / discovery | GET/ (JSON home document of endpoints available to the user), POST/bulk | Hypermedia entry point S2 |
| Assets (53 ops) | GET/assets, POST/assets/search, POST/assets/search/basic, POST/assets/search/duplicates, GET/PATCH/PUT/DELETE /assets/{assetId} (isHardDelete, includeSoftDeleted), /assets/{id}/attributes, /keywords, /categories, /comments, /rating, /history, /versions, /renditions[/{renditionKindId}], /relatedassets, /autotags, /faces, /checkOut, /clip, /videoIntelligence/*, /videoTranscript, /downloaded, /viewed; POST/assets/undeleteValidate | Soft delete by default; duplicates searched by MD5 and optionally semantic image similarity S9 |
| Check-in (versions) | POST/assets/{id}/checkOut → POST/assetCheckIn/{id}/validate → GET/assetCheckIn/{id} (upload URL) → PUT/assetCheckIn/{id} | New-version flow S2 |
| Uploads (11 ops) | POST/uploads, PUT/PATCH /uploads/{assetId}, POST/uploads/validate, `/uploads/{id}/keywords | attributes |
| Metadata schema | /attributes (10 ops: CRUD, data types, embedded-data types/mappings, cascading attributes), /attributeGroups (7, incl. reorder), /keywords (3), /keywordGroups (5), /metadataTemplates (6) | Attribute type Status requires API ≥ 1.1 S1 |
| Bulk metadata jobs | /export/asset-metadata (6), /import/asset-metadata (6, with validation step), /update/asset-metadata (3), GET/metadata-jobs/status | Present in APIM, not in the Postman collection; status endpoint requires CanEditMetadata or CanImportExportMetadata S9 |
| Search helpers | GET/search/facets, /mostViewed[/basic], /recentlyUploaded[/basic], /savedsearches (8 ops, incl. pinned and share) | Facets: file extension only S1 |
| Categories / folders | /categories (15 ops), /folders (6), sub-categories, category assets (/basic variant), permission sets, user-group links | "Folders" and "categories" are parallel routes over the same tree S2 |
| Lightboxes (collections) | /lightboxes (16 ops), approval lightboxes, policies | S2 |
| Users & groups | /users (15 ops incl. /users/current, /users/current/permissions[/{resourceType}], registration fields, approvers, POST/users/password-reset-url admin-only), /groups (7) | Public self-registration and password recovery under /public/… S9 |
| Authorization (policies) | GET/POST /authorization/policies, GET/authorization/resources/{resourceType}/ids; per-resource /policies on lightboxes and branded portals | Policy-based ACLs S2 |
| Renditions & crops | GET/config/renditionkinds, /assets/{id}/renditions, /crop (7 ops: templates, predefined templates), POST/cropWithTemplate/{assetId} | S2 |
| Direct (CDN) links | /directlinks (12 ops): create per asset, list (offset/count), export, CDN report by period, activate/deactivate/archive, validate | Image sizes XLarge…Thumbnail/Original/Custom; formats GIF, JPG, PDF, PNG, TIFF S2 |
| Downloads | /downloads (9 ops): download jobs, immediate download, asset URLs for download, validate | S2 |
| Sharing | POST/shareAssets, POST/shareLightboxes, GET/public/share/{shareCode}/… | Web galleries S2 |
| Branded Portals | /brandedportals (38 ops: CRUD, sections, sync, settings, publish, duplicate, upload sections) + /public/brandedportals/…, /public/{libraryId}/brandedportals/… | Live portal reads are anonymous public routes S2 |
| Experience portals | GET/portals/{portalId}/assets, GET/public/{libraryId}/portals/{portalId}/assets, POST/brandedportals/portals/{portalId}/non-searchable-section | Whole-portal search for "Story / Experience" portals; not in Postman S9 |
| External uploads | /externaluploads/links (7 ops) + /public/externaluploads/{linkId}/… (7) | Not in Postman S9 |
| AI | /assets/{id}/autotags, `/assets/{id}/videoIntelligence/{analyze | status |
| Reports | /reports (9 ops, by report type / users / groups / assets / events), /report/{reportType}, /v2/reports + /v2/reports/{id}/embed (embed token) | S2 |
| Library / org units | /organizationalunits (17 ops: current org unit, libraries, portals, skin colours, logo, welcome message, Print UI credential) | S2 |
| Notifications | /notification (10 ops: in-app notifications, follow asset, send) | S2 |
| Misc | /quicklinks (4), /features (2, per-user feature flags), /introductionAndHelp, /public/{domainName}/termsAndConditions | S9 |
| IAM clients | /iam-management/clients (5 ops: list, search, get, create, update) | Present in APIM, undocumented in Postman — purpose (OAuth client management) inferred from names Unverified S9 |
| Webhooks (SkyHOOK) | GET/skyhook/events, POST/skyhook/subscriptions, GET/skyhook/subscriptions/list, PUT/DELETE /skyhook/subscriptions/{id} | S10 |
| Unify Integrations | /integrations/apps (register/list/rename/delete ThirdParty apps), /integrations/allowed-origins (iframe CSP allow-list), /integrations/subscriptions…, /integrations/user-entitlement…, POST/integrations/users | 12 operations; envelope apiVersion/buildVersion/payload/recordCount/meta S11 S12 |
Rights/usage and workflow resources: no dedicated endpoints beyond asset status/approval fields, expiry dates (expiresAt), lightboxes for approval and download requests S2; proofing (PageProof) and templating (Marq) have no public API documented here (Unknown).
Data model
- Envelope on every response:
ApiVersion,Meta {MetaInformation, Warnings[], Errors[], CreatedOn},RecordCount {TotalRecordsFound, StartingRecord, RecordsReturned},PayloadS1. - Asset (GUID
id) withtitle, amediablock of pre-signed URLs per rendition (thumb,small,medium,large,original,download,stream/streamingManifest) carryingsasExpiry/sasRenewal, and afileblock (fileName,md5,fileType,sizeInBytes,uploadedAt,approvedAt,expiresAt, dimensions, video bitrate/frame rate,mimeType,colorMode…) S2. - Asset status codes used in filters: 0 approved, 2 pending, 5 rejected, 7 expired, 9 checked out S1; upload finalisation sets status 1 (ready for processing) S2.
- Taxonomy: categories (tree,
CategoryIds/CategoryAncestorIds), lightboxes, keywords (inside keyword groups, with approval status) and attributes (custom fields, grouped; data types incl. Status) S1 S2. - Libraries belong to an organizational unit;
libraryIdappears in public routes and in webhook payloads S2 S1. - Since v1.2 the asset DTO returns permissions as an array like other resources S1.
Search & querying
- Full text: GET
/assets?search=…(or body of POST/assets/search) across categories, keywords, file names, comments, descriptions; implicit AND, explicitAND/OR/NOT,"exact phrase",*wildcards S1. - Field-scoped search: field prefixes or
searchFields=amongcategoryIds,category(ies),cognitiveBackgroundColor,cognitiveForegroundColor,cognitiveDominantColors,cognitiveTextInImage,comments,description,fileName,keywords,title; the POST body also acceptscognitiveContentInDocument,cognitiveTags,videoIntelligenceS1 S2. - Filters:
filters=withEQ NE LT GT LE GE CT SW EW,AND/OR, parentheses; case-insensitive names and values; filterable: AssetType, attribute values, AverageRating, CognitiveColor (12 colours), CreatedBy, DateApproved/CheckedOut/PendingApproval/Rejected/Uploaded, file extension, Status, CognitiveTextInImage. Filters apply before search S1. - Container filters:
containerFilter=(CategoryIds/ANY(c: c EQ '<id>')), addCategoryAncestorIds/ANY(…)for sub-categories,LightboxIds/ANY(…)for lightboxes (OData-like lambda syntax) S1. - Semantic / visual: POST
/assets/searchacceptsuseSemanticSearch,semanticSearchSimilarity,useRrf(rank fusion) andfileId/fileUrl/fileSearchExactMatch(search by image) S2 — undocumented beyond the request schema Unverified. - Sorting: e.g.
sort=record.createdAt DS2. Facets: GET/search/facetsreturns counts by file extension only (other facets "planned") S1. include,exclude,max-lengthquery parameters are described but marked "not implemented yet" S1.- Deep pagination limits / maximum
count: Not public.
Uploads & binaries
Documented four/five-step flow S1 S2:
- POST
/uploads{ "filename": "…" }→ holding asset record (status "Uploading") +uploadUrl, an Azure Blob SAS URL with temporary write access. - PUT
{uploadUrl}with the bytes (x-ms-blob-typeheader) directly to Azure Blob Storage. - PUT
/uploads/{assetId}withfilename,title,description,fileSizeInBytes(required to be the original size). - POST
/uploads/{assetId}/categories(assign at least one category; keywords, attributes, lightboxes have sibling endpoints). - PATCH
/uploads/{assetId}JSON Patch[{"op":"replace","path":"/status","value":1}]→ pre-flight validation, rename handling, processing (thumbnails, AI).
- Single PUTs are limited to roughly 64 MB; larger files must be sent in blocks with the Azure Storage SDKs (C# sample provided) S1 S16.
- New versions: check-out / check-in flow (see Core resources) with
priority=highon the final PUT in the guide S2. - Downloads: rendition URLs in the asset
mediablock are SAS-signed and expire (sasExpiry) S2; download jobs via/downloads; persistent public URLs via direct links (POST/directlinks/{assetId}withRenditionSettingssize/format andLinkSettingsincl.IsUniqueLink,IsEmbedCode) S2. UI-side CDN transformations (AVIF/WebP auto-format, resize ≤ 2,000 px) are documented for the UI S65; their URL syntax is Not public.
Events & webhooks
- Service: SkyHOOK,
https://api.mediavalet.com/skyhook, separate APIM API with its own subscription requirement S8 S10. - Events (8):
Asset.StatusUpdated,Asset.MediaFileAdded,Category.AssetsAssigned,Category.AssetUnassigned,Asset.KeywordsAdded,Asset.AttributesAdded,Asset.VideoRenditionsAdded,Asset.KeywordRemovedS1 S25.Asset.StatusUpdatedfires on statuses such as Activated, PendingApproval(WithAnnotations), Approved, Rejected, Expired, Deleted, SoftDeleted, CheckedOut S28. No user, portal, CDN-link or deletion-specific events. - Configuration: by API only — POST
/skyhook/subscriptionswithEvents[],Type=webhook(Data.webhookURL) oreventgrid(Data.eventGridTopicEndpointUrl+eventGridKey);PUTto change events; one subscription per webhook URL (a second one with the same URL fails with 400 "subscription found with similar data") S1 S27. - Validation: CloudEvents 1.0 webhook abuse-protection handshake — an HTTP
OPTIONSrequest; answer synchronously withWebHook-Allowed-Origin(andWebHook-Allowed-Rate) headers or asynchronously by callingWebHook-Request-Callback; failure leaves the subscription in status Failed S1 S26. - Payload: CloudEvents JSON (
id,source,type,time,specversion: "1.0",subjectlike/library/{libraryId}/assets/{assetId}/Asset.StatusUpdated,datawithLibraryId,AssetIdand event specifics;Asset.MediaFileAddedcarries aMediaFileBlobUrl) S1. - Signature / retries: no payload signature or retry policy documented (Unknown).
Limits & quirks
- Two credentials on every call (bearer token + APIM subscription key) — the most common onboarding pitfall; the subscription key is tied to the developer-portal plan, OAuth clients are issued manually by Support S1 S21 S15.
- Manual onboarding: no self-service client creation; redirect URIs are whitelisted by Support S22.
- Admin-centric: the developer portal says an administrator account is needed to use the API S5.
- Documentation drift: 64 APIM operations (metadata import/export/update jobs, metadata templates, external uploads, quick links, IAM clients, experience-portal search, duplicate search…) are absent from the Postman collection S2 S9; the docs changelog stops at v1.2 (2025-06-13) S1; the developer-portal "API changelog" page is not readable without JavaScript.
- Changelog dates use US
MM/DD/YYYYformat in the docs (e.g. "03/06/2024" = 2024-03-06) Unverified interpretation based on ordering. - 401 vs 403: from v1.2, missing permission → 403; on v1.0/1.1 it remains 401 S1.
- Facets limited to file extensions;
include/exclude/max-lengthnot implemented S1. - Gateway:
api.mediavalet.comis fronted by Cloudflare and Azure APIM S15; the APIM backend reported for the NextGen API is a regional host (api-usca.mediavalet.net) S12 — whether other regions use other backends is Not public. - Upload size: ~64 MB per single blob PUT; Azure block upload beyond S1.
- Duplicate detection at upload (UI) does not apply to API uploads S30.
- Rate-limit headers / 429 behaviour: Not public.
SDKs, tools & code samples
| Tool | Language / form | Maintainer | Status |
|---|---|---|---|
| MediaValet/how-to-samples — large-file upload | C# (.NET 8) | MediaValet | Last push 2025-02-03; uses password grant S16 |
| MediaValet/Mediavalet.AzureMediaMigration | C# | MediaValet (fork of a Microsoft sample) | Azure Media Services migration tool, last push 2024-06-13 S17 |
| Postman collection + "Guide Variables" environment | Postman | MediaValet | Run-in-Postman from docs.mediavalet.com S1 S3 |
| Asset Picker (Unify PBC) | iframe + postMessage (insertedAssets event; params allowedAssetTypes, allowedFeatures, redirectType) | MediaValet | Enabled per domain by Support or self-serve whitelisting; local dev on http://localhost:5174 S1 S78 |
| PowerShell | — | MediaValet | Mentioned on the developer portal home page; no public module found Unverified S4 |
No official SDK packages on npm, NuGet, PyPI or Packagist S18. Community libraries: none found.
Changelog of the API
| Date | Change |
|---|---|
| 2025-06-13 | v1.2: asset DTO permissions consolidated into an array; 401 → 403 for authenticated-but-unauthorized calls S1 |
| 2024-05-22 | v1.1: stream / streamLoDef deprecated (Azure Media Services retirement); streamingManifest, fullStreamAvailable added S1 |
| 2024-03-06 | v1.1: attribute type Status in /attributes endpoints and PATCH/assets/{id}; sending Status attributes on older versions → 400 S1 |
| 2023-08-30 | Postman documentation (re)published at docs.mediavalet.com S3 |
| Unknown | v1.0 initial release S1 |
| File | Format | Size | Download |
|---|---|---|---|
mediavalet_apim_nextgen-api_openapi-export.yaml | OpenAPI | 411 B | Download |
mediavalet_apim_nextgen-api_operations_p1.json | JSON | 22 KB | Download |
mediavalet_apim_nextgen-api_operations_p2.json | JSON | 22 KB | Download |
mediavalet_apim_nextgen-api_operations_p3.json | JSON | 23 KB | Download |
mediavalet_apim_nextgen-api_operations_p4.json | JSON | 14 KB | Download |
mediavalet_apim_skyhook-api_openapi-export.yaml | OpenAPI | 405 B | Download |
mediavalet_apim_skyhook-api_operations_p1.json | JSON | 675 B | Download |
mediavalet_apim_unify-integrations_openapi-export.yaml | OpenAPI | 1.2 KB | Download |
mediavalet_apim_unify-integrations_operations_p1.json | JSON | 4.3 KB | Download |
mediavalet_postman_collection.json | Postman collection | 2.5 MB | Download |
mediavalet_postman_documenter_metadata.json | Postman collection | 9.4 KB | Download |