DAM Wiki

Canto API

Canto · Atlanta, GA, USA · Founded 1990 · PE-backed (JMI Equity)Verified 2026-09-30 · 110 sources
  • SaaS
  • Mid-market
  • REST API
  • OpenAPI spec
  • Webhooks (UI only)
  • SAML SSO
  • MCP: Product Hub MCP
Complete · 7 of 7 pages
110sources
13API specs
09-30verified 2026
Official website ↗Canto alternatives →

Scope: the REST API of the Canto SaaS DAM (the product formerly branded "Canto Flight") and, where relevant, the separate Product Hub (PIM) API. The legacy on-premise Cumulus product and its Canto Integration Platform (CIP) API are out of scope (Cumulus support ended January 2024 S86).

At a glance

API styles
REST/JSON over HTTPS only S14. One OData-style endpoint (POST/api/v2/users/$query) S9. No GraphQL found.
Base URL(s)
DAM JSON: https://{tenant}.{region}/api/v1/…; binaries: https://{tenant}.{region}/api_binary/v1/…; hashed public links: https://{tenant}.{region}/direct/…; OAuth: https://oauth.{region}/oauth/api/…; Product Hub: https://{tenant}.{region}/api/v1/pim/…. {region} ∈ canto.com, canto.global, canto.de, au.canto.com, ca.canto.com S2 S3 S12
Current version(s) & deprecations
v1 for everything except one v2 user endpoint; Canto commits to keep /api/v1 stable and add /api/v2 alongside S14. Deprecated: legacy token endpoint /oauth/api/oauth2/token (camelCase fields) S2. Portal spec versions: all families 1.0.0 (2026-08-03), Assets 1.0.2 (2026-08-24) S13
Auth methods
OAuth 2.0 with an App ID + App Secret ("API key"): authorization_code, client_credentials (acts as a named user), refresh_token S2. UI shortcut: a 1-month access token generated in the key settings S18. The docs portal itself uses a public-client PKCE flow (/oauth2/universal2/*) S3
Token lifetime / refresh
Access token 30 days (expires_in: "2592000"); refresh token 365 days, rotated on use (old one invalidated); no refresh token for client_credentials; authorization code valid 1 h S2 S14
Scopes / permission model
No fine-grained OAuth scopes: the token carries the rights of the Canto user it represents (role + group access). scope=admin|contributor|consumer in client-credentials mode only selects which user logs in S2
Official spec
11 OpenAPI 3.0.1 YAML files at api.canto.technology S1; Postman collection behind api.canto.com S14; Product Hub spec also on SwaggerHub S15. Archived copies on DAM Wiki: API spec downloads
Rate limits
Per endpoint, 5 levels per minute: L1 1000, L2 500, L3 300, L4 200, L5 50 (trial: 500/300/200/100/50); HTTP 429 when exceeded S14. Product Hub: 5 requests/second S12
Pagination
Offset start/limit + total found (search; limit default 100, max 1000) S3 S14; marker/nextMarker on reports S8; page/page-size on users S9; Product Hub page-based with RFC link header S12
Webhooks / events
DAM: 14 event types, configured in the admin UI only, JSON/Form/XML payload, optional "Secure Token", not persisted or retried S19 S20. Product Hub: webhooks managed by API (/webhooks) with a secret S12
Official SDKs
None. Canto ships a JavaScript sample (Universal Connector) as a Help Center download S62; community PHP clients exist S101
Sandbox / trial access
No public sandbox. Trial accounts get API keys from their sales rep and have lower rate limits S18 S14. The docs portal's "try it" console authenticates against your own tenant S3

Authentication

Where credentials come from S18 S20

  1. The first API key (App ID + App Secret) is handed over by the customer's Implementation Manager; after API activation, admins create more under User Menu → Settings → Configuration Options → API Keys → Create API Key (name, optional description, website, logo URL, redirect URL). If the menu is missing, the customer opens a support ticket; trial accounts ask their account representative. S14 S18
  2. Optional Support Client Credentials Mode on a key: Generate displays an access token valid one month that can be used directly (no OAuth round-trip); Revoke invalidates it. S18

OAuth host must match the tenant's domain — a .canto.global tenant must use oauth.canto.global, etc.; using the wrong host yields the error Wrong app_id value S14 S20. All five regional OAuth hosts (oauth.canto.com, oauth.canto.global, oauth.canto.de, oauth.au.canto.com, oauth.ca.canto.com) answer (405 on GET to the token URL) S16.

Token endpoint S2: POSThttps://oauth.{region}/oauth/api/oauth2/compatible/token (parameters in the query string in the docs).

ParameterUse
app_id, app_secretAlways required
grant_typeauthorization_code | client_credentials | refresh_token
code, redirect_uriAuthorization-code exchange (redirect_uri must equal the one on the key)
refresh_tokenRefresh; returns a new pair and invalidates the old refresh token
user_idClient credentials: e-mail of the Canto user to act as — recommended by Canto
scopeClient credentials: admin (default) | contributor | consumer — logs in the alphabetically first user with that role; cannot be combined with user_id

Response: {access_token, expires_in, token_type: "Bearer", refresh_token}; expires_in is a string S2.

Authorization-code flow S2 S14: browser to https://oauth.{region}/oauth/api/oauth2/authorize?response_type=code&app_id=…&redirect_uri=…&state=… → user enters account URL, credentials or SSO, clicks Allow → redirect with code → exchange. GEThttps://oauth.{region}/oauth/api/oauth/tenant/{refreshToken} returns the account (tenant) name bound to a refresh token, useful for multi-tenant apps S2.

Canto's guidance S14 S20: client credentials for unattended backend integrations; authorization code for web apps; do not use client credentials in browser JavaScript; use the least-privileged user/scope possible.

Sending the token: Authorization: Bearer <access_token> on /api/v1 and /api_binary/v1; 401 = missing/invalid token, 403 = the represented user lacks permission S14.

PKCE public client S3: the specs declare an authorization-code flow with PKCE and no client secret (https://oauth.canto.com/oauth/api/oauth2/universal2/authorize / /token), used by the docs portal's console. Whether third parties can register their own public clients is Unknown Unverified (not documented).

Core resources

Paths relative to https://{tenant}.{region}/api/v1 unless stated. Rate level (L1–L5) from the Postman documentation; ? = not stated S14. Endpoint inventory from the OpenAPI files S3–S12.

ResourceEndpointsNotes
Search / list assetsGET/search, GET/{scheme}, GET/folder/{id} (recursive), GET/album/{id} — L4Results already include full metadata; Canto asks integrators not to call detail per hit S14
Asset detailGET/{scheme}/{id} (L2); POST/batch/content (≤ 100 assets, L?)Flags noXMPMetadata, excludeTrashed, extendedRelationInfo S3
Metadata writePOST/batch/edit = read editable values (L2); PUT/batch/edit = apply (L4); PUT/{scheme}/{id}/rename (L2)Fields addressed by name, not id S3
Tags / keywords / smart tagsPUT/DELETE/{scheme}/{id}/tag/{tag}; POST/keyword; PUT/DELETE/{scheme}/{id}/keyword/{kw}; DELETE/{scheme}/{id}/smarttags/{tag} — L2Keywords must exist before being attached S3
Metadata schema (custom fields)GET/POST/PUT/custom/field, DELETE/custom/field/{id} — L28 types; no endpoint for built-in fields S10
Terms & conditions (rights texts)GET/POST/PUT/termAndCondition, DELETE/termAndCondition/{id} — L? S11
Folders / albumsGET/tree, GET/tree/{folderId} (L3); GET/info/folder/{id}, GET/info/album/{id} (L4); POST/folder/{parent}/{name}, POST/album/{parent}/{name} (L2); PUT/folder/{id}, PUT/album/{id}; DELETE/batch/folder[/permanent]Tree unpaginated, depth via layer S4
Album membership & relationsPOST/DELETE/batch/album (L4); POST/related, POST/{scheme}/{id}/unrelated, POST/unrelated (L4)Relations ≤ 1000 contents per call S3
CollectionsGET/mycollections, GET/mycollections/{id} — L1Per-user saved sets S4
UploadsGET/upload/setting (L1) → POST to S3 (L1) → GET/upload/status (L2); POST/uploadlink (L2); POST/uploadlink/import (L4)See Uploads & binaries S5
Metadata importPOST/import/metadata (multipart CSV), GET/import/metadata/progressAsync S5
Renditions / downloads/api_binary/v1/{scheme}/{id} (original), /preview[/{dim}], /HighJPG, /LowJPG, /PNG, /metadata (XML), /previewURI[/{dim}], /directuri[/{sec}], POST/api_binary/v1/batch/directuri — L1; /api_binary/v1/advance/image/{id}/download — L5; POST/api/v1/batch/download — L2 S6
Download & watermark presetsGET/tenant/download/presets, GET/tenant/watermark/presets — L2 S6
Metadata exportPOST/export/metadata (CSV by e-mail, L4); POST/album/{id}/export/metadata, POST/folder/{id}/export/metadata; POST/file/metadata (synchronous JSON, chosen columns) S7
SharingPUT/share/batch/ (L2), PUT/share/batch/containerShare links with expiry and download options S3
Video embedPOST/segment/video/{id} (L4)HLS/DASH embed S3
UsersGET/user (current, L1); GET/user/accounts, GET/users (L2); POST/PUT/user, DELETE/user/{userId} (L2); GET/users/fields (L1); POST/api/v2/users/$query (≤ 100 ids, L2) S9
Roles / groupsGET/roles (custom roles, L1); GET/groups (L?), GET/groups/{id} (members, L1); group CRUD and membership (L2)No endpoint exposes a role's privilege matrix S9
Reports & auditGET/usagehistory|shareactivity|downloadactivity/{scheme}/{id} (L2); GET/tenantreport/{uploadhistory|downloadhistory|sharehistory|share3rdpartyhistory|loginhistory}; GET/tenantreport/assetview; GET/top/{keyword|tag|smart_tag|commentedFiles}; GET/operationlogs (CSV, L4) S8
Self-descriptionGET/api/v1 — lists the tenant's endpoints as URI templates; no auth; L1 S8 S14
Workflows / approvalsNo dedicated endpoints; approval status and expiration are asset fields set through batch edit / CSV import S3 S37. Approval Hub (proofing) has no public API — Not public
Rightscopyright, termsAndConditions, expirationDate, approvalStatus asset fields + T&C CRUDPresent only when DRM is enabled on the tenant S3
Product Hub (PIM)/api/v1/pim/: products (+variants, asset link/unlink), product types, custom attributes, categories, dimensions, catalogs, channel templates (+export), bulk ops, share links, imports, webhooks — 75 operations5 req/s S12

Not exposed in the documented API (checked against all specs): DAM webhook management, portal/workspace/style-guide listing and settings, folder/album permission ACLs, approval-workflow configuration, a keyword-vocabulary list endpoint, a built-in-field schema endpoint, saved searches, trash listing, SSO/password-policy configuration S3–S11. Whether the tenant self-description (GET/api/v1) reveals more is Unknown.

Data model

  • Asset identity = content id + scheme, where scheme ∈ image, video, audio, document, presentation, other (case-sensitive; shown as "Smart Albums" in the UI). Every per-asset call needs both S14.
  • Structure: folders contain folders and albums; albums contain assets; an asset is never directly in a folder and can belong to several albums (relatedAlbums[] with idPath) S14 S31. Folder/album ids are short codes (e.g. 5 characters) and change when the folder/album is moved S14.
  • Metadata buckets on an asset S3 S14:
    • default{} — built-in fields keyed by display label (e.g. "Uploaded by", "Date modified", "Copyright", "Author", "Dimensions", "Resolution").
    • additional{} — custom fields keyed by field name (values: null, string or array).
    • metadata{} — embedded EXIF/XMP/IPTC, skippable with noXMPMetadata=true.
    • Top-level: description, tag[], keyword[], smartTags[], approvalStatus, expirationDate, copyright, termsAndConditions, owner/ownerName, created, time, lastUploaded, versionHistory[], relatedFile[], url{}.
    • Alt-text (images) is "accessible via the Canto API" S76; its JSON key is not shown in the specs — Unknown.
  • Custom field schema: GET/custom/field → [{id, name, type, values[]}]; ids follow meta_{type}_{n} (e.g. meta_text_2, meta_multichoice_0); types NUMBER, TEXT, DATE, SINGLECHOICE, MULTICHOICE, URL, LABEL (hex colour), RATING (1–5); create requires name (unique, ≤ 80 chars) and description (≤ 800) S10. Field type cannot be changed after creation; renaming an option leaves the old value on assets S22. Sections, display order, required-on-upload and translations exist in the UI S22 S23 but are not in the API schema S10.
  • Taxonomy: keywords = admin-managed controlled list (flat); tags = free text; smart tags = AI-generated S24 S25. No hierarchical taxonomy object S3.
  • Approval: approvalStatus ∈ Approved, Pending, Restricted (+ Expired set automatically, + up to 20 custom statuses) S26 S27.
  • Versions: versionHistory[] (no, versionId, ownerName, created, time, comment, currentVersion, per-version URIs) S3.
  • Storage class: standard or freeze (Cold Storage) S3.
  • Dates: JSON dates are strings yyyyMMddHHmmssSSS S14; search filters take Unix seconds except expirationDate (milliseconds) S3; batch-edit dates YYYY-MM-DD HH:mm (or YYYY-MM-DD for DATE fields) S3.
  • Numbers as strings: many numeric values (size, width, expires_in) are returned as strings S2 S3.

Search & querying

S3 unless noted.

AspectBehaviour
Full textkeyword (UI-like search); a|b = OR, a+b = AND; restrict with searchInField=filename|description|comment|keywords|author|tags; exactMatch; operator=and|or
Filtersscheme, tags, tagsLiteral (case-sensitive), keywords, approval (approved|pending|restricted; expired alone), owner, fileSize=min..max, width, height, dimension, resolution, orientation, colorModel, duration, pageNumber, storageClass, created, createdTime, uploadedTime, lastModified, expirationDate, latestReviewDate, and any custom-field id (e.g. meta_text_2=…)
Empty / non-emptyLiteral __null__ (no value) and __exists__ (any value) on filter fields
Negation$filter=tagsLiteral ne 'X' and keywords ne 'Y' (OData-style, tags and keywords only)
FacetsEvery search returns facets[]: distinct values (no counts) for categorical fields; min/max for numeric/date fields
Countsfound = total hits; tenant-wide frequency counts via GET/top/{keyword|tag|smart_tag|commentedFiles}, including Unkeyworded / Untagged buckets S8 S14
SortingsortBy=name|time|scheme|owner|size, sortDirection=ascending|descending (default time, descending)
Page sizelimit default 100, maximum 1000 S3; the docs state that over-large requests must be avoided S14
Deep paginationMaximum reachable offset is Not public Unverified — partition large crawls (e.g. by scheme and uploadedTime/lastModified ranges) rather than relying on deep offsets
Delta queriesCanto recommends delta requests by modification date over full re-reads S14; in search results time depends on a tenant display setting, so lastModified is the reliable delta filter S14

Uploads & binaries

Upload flow S5 S14

  1. GET/api/v1/upload/setting — returns an S3 POST policy (url, key, policy, signature fields); valid 5 hours, do not re-request per file. .de and .ca.canto.com tenants use an AWS SigV4 variant of the fields.
  2. POST multipart/form-data to the returned S3 URL without the Bearer token; one file per request, file field last; x-amz-meta-scheme + x-amz-meta-id of an existing asset creates a new version; x-amz-meta-album_id targets an album. Maximum 5 GB per API upload S14.
  3. GET/api/v1/upload/status?hours=… — poll no more often than every 30 s for backend applications (1 s single GUI upload, 10 s batch GUI) S14.

Other ingestion: Upload Links (POST/uploadlink, with duplicate-check mode MD5 or filename and default approval status) S5; CSV metadata import (key column File Name or Content ID + File Type; , or ; delimiter; multi-values separated by ;; UTF-8) S37. UI/desktop upload limits differ (browser 200 GB, current Canto Connect unlimited, Adobe connector 5 GB) S59.

Downloads & renditions S6 S14

  • Token-protected: original /api_binary/v1/{scheme}/{id}, previews /preview/{dim}, HighJPG, LowJPG, PNG, embedded-metadata XML, per-version binaries.
  • Signed CloudFront URLs: /directuri[/{expireSeconds}] (download) and /previewURI[/{dim}], plus a batch variant; the URL is version-specific and expires S14.
  • Hashed "direct URLs" (/direct/{scheme}/{id}/{hash}/original, preview sizes) need no token; returned in asset JSON S6. Preset preview widths are listed as 100, 240, 320, 500, 640, 800 and 2050 px S60.
  • Advanced download (resize/crop/colour mode) is L5 and must only be used for user-initiated single downloads, never batches S14.
  • Bulk ZIP: POST/api/v1/batch/download — async, e-mailed link, max 1000 files (413 above), one job at a time per tenant (429 otherwise) S6 S14.
  • Media Publisher / MDC (paid CDN add-on): CloudFront delivery URLs with on-the-fly operations (scale -S, bound -B, crop -C, format/quality -F, watermark -W, crop template -T); assets > 1 GB may fail to publish S61.

Events & webhooks

DAM webhooks S19 S20

  • Configured by an administrator in Settings → Configuration Options → API → Webhooks; no API to create or list them S3–S11.
  • 14 events: Add Album, Add Folder, Add New Version (also on "set as current"), Assign to Album, Delete Album, Delete Asset, Delete Folder, New Asset (also when moved from an Upload Link to the Main Library), Relate Files, Remove from Album, Unrelate Files, Update Album, Update Folder, Update Metadata. Fired for Main Library content.
  • Per webhook: target URL, optional "Secure Token" (literal null if unused), content type JSON / Form / XML, checkboxes selecting which asset parameters are sent; several webhooks per event allowed.
  • Canto does not persist webhooks (no retry/replay); it recommends a periodic (e.g. daily) consistency check on the receiving side S20.
  • Payload schema, header names and signing (HMAC) are Not public.

Product Hub webhooks S12: GET/POST/pim/webhooks, update/delete, GET/webhooks/{id}/events, DELETE/webhooks/{id}/events/purge; resources product, variant, import; events created, updated, deleted, started, completed, failed; optional secret.

Polling alternatives: lastModified search ranges; GET/operationlogs (CSV User,Operation,Location,Date,Content; both dates required in practice) S8; tenant upload/download history reports S8. The UI operation-log report covers the current and previous year S58 Unverified (retention for the API endpoint not stated).

Limits & quirks

TopicDetail
Rate-limit scopeWhether limits count per token, per app, per user or per tenant is Not public; no Retry-After / X-RateLimit-* headers are documented S14 Unverified
Rate levelsSearch/list L4 (200/min), detail L2, tree L3, binaries L1, advanced download L5; several endpoints (batch content, top, tenant reports, groups list, T&C, file/metadata) have no documented level S14
Volume reviewFor large integrations Canto asks for a sequence diagram and expected calls/min via its developer support S14 S20
Developer support scopeCanto provides API advice in a joint meeting but does not build custom integrations or review code S20
Error bodiesStandard HTTP codes (400/401/403/404/429/500/503); body {code, message}; OAuth errors {error, error_description}; batch calls report partial failures in the body (failed[]) S2 S3 S14
404 semanticsAlso returned for arbitrary/invalid ids S14
KeywordsAttaching a keyword that does not exist fails; create it first with POST/keyword S3
Name vs idSearch filters use custom-field ids; asset JSON and batch edit use field names S3 S10
Moving foldersFolder/album ids change on move — do not key long-lived state on them alone S14
MD5Available via POST/file/metadata columns; the Help Center warns the MD5 value tends to change even after metadata-only edits (tags, keywords, smart tags) S7 S28 Unverified
Accepted export columnsPOST/file/metadata column names are only exemplified ("Content ID", "File Name", "MD5", "Description"); the full list is Not public S7
Approval filterapproval= only works when the approval workflow is enabled on the tenant S3
Forward compatibilityCanto may add response keys and give meaning to currently-undocumented parameters — avoid strict response validation S14
Access-token wordingGeneral notes say every request "must contain an access_token parameter", while all examples use the Bearer header S14 Unverified (query-parameter form untested)

SDKs, tools & code samples

Library / toolLanguageMaintainerStatus
Official SDK——None published (no Canto package on npm/PyPI/NuGet; Canto states it does not provide developer resources for custom integrations) S108 S20
Universal ConnectorJavaScriptCantoSample asset picker (OAuth login incl. SSO, smart-album and folder/album filters, global search), zip download in the Help Center; basis of Canto's Salesforce connectors S62
Canto WordPress pluginPHPCanto (flightbycanto)v3.1.4, updated 2026-09-16 on WordPress.org; old GitHub mirror last pushed 2019 S99 S100
jleehr/canto-saas-apiPHPCommunity (continuation of an agency client)Active: last push 2026-09-22, Packagist 3.0.1 S101
TYPO3-Canto/canto-apiPHPCommunityLast push 2025-06-04 S102
flownative/neos-cantoPHPFlownativeNeos asset source; last push 2025-06-24 S103
lsst-epo/canto-dam-assetsPHPRubin Observatory EPOCraft CMS field/plugin; last push 2026-02-11 S104
firstspirit-canto-integration-dapJavae-Spirit user groupFirstSpirit CMS integration; last push 2026-09-04 S105
spicy-labs/canto-media-connectorTypeScriptCommunityCHILI GraFx media connector; last push 2025-02-27 S106
Postman collection—Canto137 items incl. saved example responses (public Documenter) S14

Changelog of the API

DateChange
2026-09-07Native Alt-Text field for images, readable via the API (key not documented) S76
2026-08-24Assets API spec 1.0.1 → 1.0.2 (documentation-only changes) S13
2026-08-03New docs portal api.canto.technology publishes 11 OpenAPI 3.0.1 specs (all v1.0.0) S13
2026-07Product Hub MCP server (/api/v1/pim/mcp) released S77
2025-09-09Product Hub (PIM) OpenAPI v1.0.1 published on SwaggerHub (Canto/Canto-PIM-Alt2) S15
2022-03-08Current Postman documentation (api.canto.com) first published S14
UnknownLegacy /oauth/api/oauth2/token endpoint deprecated in favour of /oauth2/compatible/token S2

Stored API specs

13 files · 2.0 MB · verbatim copies of public vendor filesSpecs README & provenance
FileFormatSizeDownload
canto_openapi_authorization.yamlOpenAPI14 KBDownload
canto_openapi_dam-assets.yamlOpenAPI52 KBDownload
canto_openapi_dam-download.yamlOpenAPI25 KBDownload
canto_openapi_dam-export.yamlOpenAPI7.6 KBDownload
canto_openapi_dam-fields.yamlOpenAPI5.5 KBDownload
canto_openapi_dam-librarytree.yamlOpenAPI27 KBDownload
canto_openapi_dam-reports.yamlOpenAPI22 KBDownload
canto_openapi_dam-terms.yamlOpenAPI5.0 KBDownload
canto_openapi_dam-upload.yamlOpenAPI22 KBDownload
canto_openapi_dam-user.yamlOpenAPI22 KBDownload
canto_openapi_pim-api.yamlOpenAPI174 KBDownload
canto_postman_collection.jsonPostman collection1.5 MBDownload
canto-producthub-pim-openapi-v1.0.1.jsonOpenAPI158 KBDownload
Search the wiki