Scope: the DAM REST API ("API Core") in depth, plus the adjacent Aprimo surfaces an integrator meets: the Upload Service, the OAuth 2.0 login service, the MCP Server, the Analytics API, and — briefly — the Productivity Management (PM) REST API and the PM Reporting API. Aprimo documents all of them on one portal and they share the same OAuth tokens S1 S3.
At a glance
https://{tenant}.dam.aprimo.com/api/core/ · Uploads: https://{tenant}.aprimo.com/uploads (no .dam., no /api/core) · OAuth: https://{tenant}.aprimo.com/login/connect/{authorize|token} · MCP: https://{tenant}.aprimo.com/mcp · Analytics: https://{tenant}.aprimo.com/analytics/?query=… · PM: https://{tenant}.aprimo.com/api/{resource} · PM Reporting: https://{tenant}.aprimo.com/WebApi/api/Reports/{id}.{json|xml|xsd}/ S6 S16 S20 S33 S34 S39API-VERSION: 1; GET/api/core/supportedversions lists only "1" S16 S41. Deprecated on 2026-06-01 (postponed from 2026-03-02): legacy /api/oauth/* token routes, registrations with flow type <None> or "Authorization Code (Obsolete)", DAM page-hook auth-code, PM LaunchExternalApp.aspx token injection, uploads via upload.aprimo.com, uploads continuing with an expired token S18. Policy: ≥ 6 months notice for documented APIs only S19expires_in: 3600); refresh tokens only for PKCE registrations with Enable Refresh Token, lifetime 60 minutes to 10 days, rotated on use; no refresh for client credentials or password flow; 5-minute clock skew; registration changes take up to 15 minutes to apply S3 S16api (REST incl. DAM downloads), offline_access, reporting-api, filestore-access (PM only), mcp S3 S20; discovery also lists openid, profile, email, tenant, user, legacy-api, brandportal-api, review-file-service, csp-api, cip-api, introspection, brandportals-management S40. Scopes are coarse: what a token can do is the represented user's DAM permissions and classification ACLs S3 S22/api/core/docs/openapi.json and linked publicly as the portal's "DAM API Reference" S16; a curated DAM "content consumption" OpenAPI 3.0.1 (40 operations) S14; PM OpenAPI 3.0.1 S15; Postman "Aprimo API Reference" (420 requests) S17. Archived copies on DAM Wiki: API spec downloadsAuthentication
Where credentials come from S3
- An admin with the Security or System Administration domain right opens Administration → Integration → Registrations and creates a registration: name, description, Client Secret (cannot be retrieved later), redirect URL (code flows), OAuth Flow Type, access-token lifetime, optional refresh token.
- For Client Credentials the registration names the user on whose behalf all calls run (the only user for that registration).
- Changes can take up to 15 minutes to propagate S3 S14.
Flows
| Flow | Token request (POSThttps://{tenant}.aprimo.com/login/connect/token, form-encoded) | Notes |
|---|---|---|
| Client Credentials | grant_type=client_credentials&scope=api&client_id=…&client_secret=… | Service integrations; recommended for learning the API; no refresh token — request a new token before expiry S3 S16 |
| Authorization Code + PKCE | Browser to /login/connect/authorize?response_type=code&client_id&redirect_uri&scope&state&code_challenge&code_challenge_method=S256; then grant_type=authorization_code&code&redirect_uri&code_verifier&client_id&client_secret | Redirect URI must match exactly; scope is not echoed back; the documented exchange also sends the client secret S3 |
| Refresh | grant_type=refresh_token&refresh_token=… with Authorization: Basic base64(clientId:clientSecret) | Returns new access + refresh token and invalidates the old refresh token S3 |
| Resource Owner Password | grant_type=password&username=…&password={UserToken}&scope=api&client_id&client_secret | User Token from My Profile → ⋮ → User Token; no refresh S3 |
| MCP | Registration with Client mcp_client, flow type "Model Context Protocol (MCP)", client-supplied redirect URL, refresh enabled; scope mcp | Per-user OAuth; see Integrations — AI & agent ecosystem S20 |
- The login service is an OpenID Connect provider: discovery at
https://{tenant}.aprimo.com/login/.well-known/openid-configurationadvertisesauthorization_code,client_credentials,refresh_token,password,implicit, device-code, CIBA and token-exchange grants, PKCEplain/S256, client authclient_secret_basic/client_secret_post/private_key_jwt, and no dynamic client registration endpoint S40. Only the flows in the table above are documented S3. - Service users and admin rights: in PM, users with
System Administration, Accesscannot read/edit records via the API; theIntegration API, Accessdomain right lets a service user bypass PM access lists (activities, programs, funding accounts, markets, plans, offers) S3. For the DAM, visibility is governed by the represented user's DAM permissions and classification permissions S16 S22. - Sending the token:
Authorization: Bearer <token>on every call; a 401 with an empty body usually means an expired token S3.X-Access-Tokenis not used by any current documented flow; the legacyexchange-auth-coderoute that used it is deprecated S18.
Required DAM headers S16
| Endpoint | API-VERSION | Accept | Authorization | User-Agent |
|---|---|---|---|---|
/ (root) | ignored | required | ignored | required |
/supportedversions | ignored | required | ignored | required |
/download | ignored | ignored | ignored | required |
/docs | ignored | ignored | ignored | ignored |
| all other endpoints | required | required | required | required |
Core resources
Paths relative to https://{tenant}.dam.aprimo.com/api/core. Inventory from the full OpenAPI spec (48 tags, 312 operations) S16; examples in Postman S17.
| Resource | Endpoints | Notes |
|---|---|---|
| Discovery | GET/ (home, links to collections), GET/supportedversions, GET/info (active DAM version), GET/csp | Root and supported versions answer without a token S41 |
| Records (assets) | GET/records, POST/records, GET|PUT|DELETE /record/{id}; sub-resources /fields, /field/{fieldId}, /classifications, /files, /masterfile, /masterfilelatestversion, /permissions, /locks, /image/{preview|thumbnail}[/download], /associatedcollections, /duplicateinfo, /downloadagreement | 47 operations under the Record tag; a record must carry ≥ 1 classification S16 S35 |
| Bulk / edit sessions | POST|PUT|PATCH|DELETE /record/bulkedits, POST/record/edits, POST/records/edits, /record/edits/{editToken} | Session-based bulk editing and locking S16 |
| Check-in / check-out | /record/operations/checkout, /record/operations/checkin, /record/{id}/{checkout|checkin|undocheckout}/prepare, POST|DELETE /file/{id}/checkouts | S16 |
| Audit trail | GET/record/{objectId}/trail?filter=change|download (skip/take only), GET/record/{objectId}/trail/entry/{entryId} | S16 |
| Search | POST/search/records (expression + facets), POST/search/classifications, POST/search/images (image-similarity job), POST/search/phrase-suggestions, POST/search/records/suggestions; filter/sort on any collection | See Search & querying S7 S16 |
| Metadata schema | GET|POST /fielddefinitions, POST/fielddefinitions/search, GET|PUT|DELETE /fielddefinition/{id}, /fielddefinition/{id}/listvalues; GET|POST /fieldgroups, /fieldgroup/{id}[/members]; GET|POST /contenttypes, /contenttype/{id}[/parent], /contenttypes/info | Field and content-type definitions are writable via API S16 |
| Taxonomy (classifications) | GET|POST /classifications, GET/classification?… (by path), GET|PUT|DELETE /classification/{id}; /ancestors, /children, /parent, /fields, /followerclassifications, /image | Hierarchical tree S16 |
| Classification permissions | GET|PUT /classification/{id}/recordpermissions, /classificationtreepermissions, /downloadpermissions | Group-level ACLs with inheritance S16 |
| Collections | GET|POST /collections, POST/collections/search, GET|PUT|DELETE /collection/{id}, /records, /permissions (+ autoReadAccess), /comments (+ status) | S16 |
| Files & versions | /file/{id} (/fileversions, /latestversion, /fields, /watermark, previews); /fileversion/{id} (/renditions, /additionalfiles, /publiclinks, /filepreviews, /duplicateinfo, /filetype, /linkedversions/{type}, /permissions, /fileprocessactionlog); /additionalfile/{id}; /rendition/{id}[/publiclinks]; /filepreview/{id} | S16 |
| Uploads | POSThttps://{tenant}.aprimo.com/uploads, /uploads/segments, /uploads/segments/{token}?index=n, /…/commit, DELETE/uploads/segments/{token} | Separate Upload Service S16 |
| Orders (downloads, CDN) | GET|POST /orders, GET|PUT /order/{id}, /order/{id}/targets[/{targetId}] | Async; types incl. download and publicCDN S16 S35 |
| Public links / sharing | POST/publiclinks (import own-CDN links), GET|PUT|DELETE /publiclink/{id}; /shareddownloadlinks (+ /downloads, /expiration, /revoke, /recipients/search, /requestverificationcode); /downloadlinks | S16 |
| Rights & governance | /downloadAgreements (+ search, classifications, contents, user groups, acceptance), /accesslists, /accesslist/{id}, /watermarks, /imageoverlays | S16 |
| Users & groups | GET/users, GET/user/{id} (+ /memberships, /fields, /image, GET|PUT /permissions); GET/usergroups, GET/usergroup/{id}, GET|PUT /usergroup/{id}/permissions, PUT/usergroups/permissions | No user/group create in the spec; no "members of group" route S16 Unverified see quirks |
| Permissions | GET/permissions, GET|PUT /permission/{name}, GET|POST /calculatedpermissions, GET/CalculatedPermission/{name} | Catalogue of functional rights and caller's effective rights S16 |
| Rules (automation) | GET|POST /rules, GET|PUT|DELETE /rule/{id}, /actions, /conditions | Rules readable/writable via API; used as the DAM event mechanism S16 S29 |
| Maintenance jobs | GET|POST /maintenancejobs, /maintenancejob/{id}[/targets] | e.g. CreateRenditions, crop/trim actions S12 S16 |
| AI & quality | GET/fieldpopulationlog/summary, /fieldpopulationlog/recent/{fieldId} (AI field prediction logs); POST/fileversion/{id}/compareInsights; Check Framework /checks, /checkcategories, /actiontypes, /fileversion/{id}/CheckResults[…/Findings] | S13 S16 |
| Configuration | /settings, /setting/{name}, /settingdefinitions, /settingcategories, /languages (+ synonyms), /translations, /filetypes, /fileprocessactions, /counters, /searchindex, /uniquekeyindex, /subscriptions | S16 |
| Analytics API | GEThttps://{tenant}.aprimo.com/analytics/?query={json} | Pre-aggregated facts: Downloads, Views, Impressions (public-link hits), ContentEngagement, Plays…; aggregate use only S33 |
| PM REST API (brief) | https://{tenant}.aprimo.com/api/… — tasks, review-tasks, activities, projects, attachments, budgets, content plans, invoices, commitments, users, groups, digital-assets… (288 paths / 377 operations) | Headers: Bearer + JSON, optional Language; offset/limit ≤ 250 S15 S39 |
| PM Reporting API | GEThttps://{tenant}.aprimo.com/WebApi/api/Reports/{reportId}.{JSON|XML|XSD}/?{params} | Reports must have Web Service Access enabled; scope reporting-api S3 S34 |
Data model
- Record = the central object (an asset, or content without a file). Fields:
id,status∈Draft,Released,Archived,Unpublished(out-of-box),contentType,title,tag,textContent,aIInfluenced,hasImageOverlay,createdOn,modifiedOn; related data are not returned unless selected S6 S16. - Identifiers are GUIDs; examples are shown both with and without hyphens (e.g.
250d22a231ed4f0ba9afa49900b0252e) S16. Whether hyphenated GUIDs are accepted on every route is Unknown Unverified. - Selecting (expansion):
select-{resource}headers embed relations, e.g.select-record: fields, classifications, masterfilelatestversion, preview, thumbnail, permissions, locks, accesslists, analyticsdata, createdby, modifiedby; nested selectors such asselect-field: definition,select-fileversion: renditions, publiclinks, additionalfiles, filepreviews,select-classification: parent, children;select-record-fields/select-record-fieldgroupsrestrict fields by ID or name;select-resolve-default-values: falseomits default values. A resource type may occur at most twice in an embedding chain; selecting a missing relation embedsnull, following its link returns 404 S8 S16. Valid select keys are listed asselect-keyin HAL_linksS6 S8. - Metadata:
FieldDefinitionwithdataType∈SingleLineText,MultiLineText,Numeric,DateTime,Date,Time,OptionList,Duration,UserList,UserGroupList,Html,Json,ClassificationList,RecordList,RecordLink,LanguageList,TextList,HyperlinkList(18 types) S16; properties includescope/scopeCategory(e.g.RecordContentGlobal, record vs classification vs user fields),languageMode(Single/Multiple),indexed,isRequired,defaultValue,validationS7 S16. Values are localized:fields.items[].localizedValues[{languageId, value | values[] | hyperlinks[]}]; option values are option IDs S16 S20 S36. - Field applicability: a field becomes usable on a record when registered on one of its classifications (scope "Record Content Class Dependent") and/or its content type; UI visibility also needs the DAM UI JSON layout S11.
- Taxonomy = classifications, a tree (
parent,children,ancestors,NamePath/LabelPath,Identifier,SortIndex) that also carries registered fields, record/tree/download permissions and download agreements S7 S16. - Files: record → files (master + others) → file versions (checksum CRC32, extension, file type) → renditions, additional files (crops, trims, renditions), previews, public links S7 S12 S16.
- Languages: fetch
/languagesand cache; request localized values with headerlanguages: {id}[,{id}]or*; default = the calling user's language S16. - Editing:
PUTis partial (send only what changes;nullusually resets); nested collections use{addOrUpdate:[…], remove:[…]}; the JSON returned by a read can generally be reused as the edit body S16 S36.
Search & querying
| Aspect | Behaviour |
|---|---|
| Two entry points | filter + sort (query string or header) on any collection GET; POST/search/records / POST/search/classifications with a searchExpression object (expression, parameters[] for ?, namedParameters{} for @name, defaultLogicalOperator, supportWildcards, languages) |
| Operators | =, >, >=, <, <=, <>, in, contains (full-text index); logical AND/+, OR, NOT/-; wildcards * (and ?) unless supportWildcards: false; Date/Time in only supports today |
| Record properties | Id, Title, ContentStatus, ContentType/DirectContentType, Classification/DirectClassification (.Id, .NamePath…), CreatedOn/ModifiedOn (sortable), CreatedBy/ModifiedBy (.Name, .Email…), FileCount, File.Version.* (FileName, FileSize, Extension, Checksum, HasPublicUri, Version…), LatestVersionOfMasterFile.* |
| Field values | FieldId("{id}") (recommended, stable), FieldName("{name}") or FieldLabel(…) (language-dependent) + type-specific property: .Value, .UtcValue, .Option.Id/Name/Label, .Classification.Id, .User.Name, .UserGroup.Id, .Url/.DisplayText, .Record.Id, .Child.Record.Id, .Language.Id |
| Sorting | Sortable properties, field values (FieldName('X').Value) and relevance Rank desc (records and classifications only); multiple criteria comma-separated |
| Facets | facets[] in the search body: option list, classification list, text, text list, numeric, numeric/date/datetime/time ranges, classification (root + children/descendants), content type, file type, created/modified by/on. Max 12 per request (extra ones listed in truncatedFacets); counts approximate; zero-count values omitted |
| Counts | totalCount is approximate: search first queries Elasticsearch for IDs, then the database; deletions in between desync the count |
| Page size | Records search/list clamp at 100; other collections 1000 (default 50); oversize requests are clamped without error |
| Deep pagination | Use the cursor — constant cost at any depth; the cursor is bound to filter, sort and tenant (changing them → 400); nextCursor: null = last page. Vendor sample tooling also uses keyset paging on CreatedOn S74 |
| Suggestions / similarity | Phrase and record suggestions endpoints; image-similarity search job (POST/search/images) |
| Index freshness | Writes can send set-immediateSearchIndexUpdate: true to index synchronously (slower request) |
| Delta sync | Filter on ModifiedOn (docs recommend filtering for changes and caching static data such as classifications) S5 |
Uploads & binaries
Upload flow (Upload Service, https://{tenant}.aprimo.com/uploads) S16 S35
- < 20 MB: POST
/uploadsmultipart/form-data, one file per request →200 {token, sasUrl}(or202). Requires the user to hold.RoleExecuteMaintenanceJobsand.RoleViewMaintenanceJobs. - > 20 MB: POST
/uploads/segments {filename}→{uri, token}; upload zero-based segments?index=n(parallel allowed) →202; POST…/commit {filename, segmentcount}→{token, sasUrl}; DELETE…cancels. Aprimo recommends 20 MB chunks S5. - Very large files: POST
/uploads {fileName}(JSON) returns a writable Azure blobsasUrlfor AzCopy; the token is usable once the copy has finished. - Attach: POST
/records(or PUT/record/{id}) withfiles.master = <uploadToken>and a version entry, plus at least one classification. Upload tokens are single-use and uploads are purged "after a few days". Unsupported filename characters:< > : " / \ | ? *. - Since 2026-06-01 every upload request (including each segment) needs a valid bearer token;
upload.aprimo.comis retired S18.
- Metadata can be ingested with a CSV token +
.dataExchangeSchemasXML schema in the record-create call S10.
Downloads & renditions S16 S35 S36
- Orders (POST
/orders,type: download, targets withrecordId,assetType∈LatestVersionOfMasterFile,AllVersionsOfMasterFile,LatestVersionOfAllFiles,AllVersionsOfAllFiles, optional transformation actions) are processed asynchronously; poll GET/order/{id}fordeliveredFiles. Reading orders requires the ViewMaintenanceJobs role. Synchronous orders exist for untransformed downloads S36. - Download URIs carry an expiring token: 30 h with disk storage, otherwise at least the value of
.minimumAvailableTimeForOrders/.minimumAvailableTimeForPreviews(Azure blob). The URI may redirect (301/302) to the CDN; headerLocation-Aliasselects CDN regionus1,eu2,au1,cn1. - Previews/thumbnails:
/record/{id}/image/{preview|thumbnail}(MCP docs describe ~150×150 thumbnails, ~800×600 previews, SAS URLs valid ~24 h) S20. - Public CDN links: created via an order of type
publicCDN(or rules); the URL pattern is set globally so a public URL is known before caching; supports URL transformations; recommended for CMS/e-commerce/email S16 S36 S46. - Renditions: presets in the
.renditionPresetsetting, generated by rules or POST/maintenancejobsactionCreateRenditions(e.g. AIremoveBackground); crops (CropImage) and video trims (TrimVideo) stored as additional files S12.
Events & webhooks
DAM — Rules S29
- If/then rules on records, files, classifications and other objects; triggered on save/delete or on a schedule; actions include field updates, classification linking, renditions/previews/public links, e-mail, AI actions and an HTTP Request action (POST to a configured URI).
- Actions run immediately (before save, under the triggering user's validation) or delayed (maintenance job, bypasses validation); rules are versioned.
- Retries: only some action types support a
retriesparameter (list Behind login in the in-app help); receivers must answer fast —2xx,400and500do not trigger a retry; retries can arrive out of order, so payloads should only announce what changed and the receiver should re-read the API. - Configuration: DAM UI or Admin Studio; the
/rulesAPI endpoints also expose them S16. Payload schema and signing for DAM HTTP actions are Not public in the developer docs; Aprimo's sample integrations authenticate by adding a customAuthorizationheader in the rule'sref:httpRequestdefinition S73. - Content subscriptions (
/subscriptions) exist in the spec; their delivery mechanism is not described there S16 Unverified. The rules docs cite e-mailing "subscribed users" about expiring assets as a use case S29.
PM — Webhooks S30
- Events: object created/updated/deleted (supported object list), task status action, project started/paused/resumed/closed/cancelled/role changed, commitment approved/rejected/cancelled, forecast changed, segmentation events, program proposal submitted, content-plan link changes, SSO user created/updated (
CalloutLocation500/501). - Payload: JSON POST with
CalloutLocation,ObjectTypeId,ObjectResourceName,ObjectId,CreatingUserId,RetryCount,Body(string),EventTime,EventId,ParentEventId. - Security:
X-SH1header = Base64(HMAC-SHA256(body, secret)). - Delivery: 30 s timeout; up to 4 retries (1, 2, 5, 7, 15 min schedule, exponential backoff with jitter); after 5 consecutive failures the subscription is invalidated and admins notified; manual retry from the Integration Log.
UI page hooks: DAM page hooks POST (or GET with {{field:Name}} URL tokens) to your endpoint with the triggering user's access-token, 15 s default / 30 s max timeout; response can show a message or open a URL S31. PM page hooks exist too S32.
Limits & quirks
| Topic | Detail | |
|---|---|---|
| Shared rate budget | The tenant limit is shared by every integration; one noisy client can starve others. No Retry-After / X-RateLimit-* header is documented | S1 S5 Unverified |
| HTML error bodies | 429 and 504 return HTML, not the JSON {exceptionType, exceptionMessage} object — check Content-Type before parsing | S6 S16 |
| Approximate totals | totalCount and facet counts are approximations | S16 |
| Silent clamping | pageSize/take above 100 (records) or 1000 (others) are clamped without error | S16 |
| Three hostnames | API on {tenant}.dam.aprimo.com, login/uploads/MCP/analytics on {tenant}.aprimo.com | S6 S20 |
User-Agent mandatory | Required on 312/312 operations (spec) | S16 |
| Status naming | Resource property status; search property ContentStatus | S7 S16 |
| Users read-only in the spec | Spec has no PUT/DELETE on /user/{id} or /usergroup/{id}, but the Postman collection shows "Edit User", "Delete User", "Edit User Group", "Delete User Group" requests | S16 S17 Unverified sources differ |
| Group membership | Membership is read per user (/user/{id}/memberships); there is no DAM route listing a group's members | S16 |
| Spec divergence | The curated content-consumption spec includes GET/publicuri/{id} and GET/fileversion/{id}/publicuris, which are absent from the full Core spec | S14 S16 Unverified |
| Orders need a job role | Retrieving orders requires ViewMaintenanceJobs; uploads require Execute/View maintenance-job roles | S16 |
| Rule/validation bypass | Write headers disable-rules, disable-validations, client-id, plus set-immediateSearchIndexUpdate, copyFromLatestVersion, recreateAutomaticPreviews, copyFilesInBackgroundProcess on record writes. Conditions under which bypass is honoured: Unknown from the spec text | S16 Unverified |
| Copilot Studio + PKCE | Copilot Studio's REST tool cannot do PKCE; Aprimo warns that disabling PKCE on a registration reduces security | S24 |
| Undocumented = unprotected | Undocumented endpoints/fields may change without notice (outside the deprecation policy) | S19 |
SDKs, tools & code samples
| Library / tool | Language | Maintainer | Status | |
|---|---|---|---|---|
| Official REST SDK | — | — | None published (no Aprimo-owned package on npm/PyPI/NuGet) | S70 |
| Content Selector | JavaScript (hosted page /dam/selectcontent + postMessage) | Aprimo | Supported; options select (single/multiple/singlefile/singlerendition), limitingSearchExpression, facets, dialogMode | S37 |
| Claude skills (4 ZIPs) | Markdown + bundled OpenAPI | Aprimo | DAM API, DAM Analytics, PM API, PM Reporting quick starts; examples in Python, JS/TS, C# | S28 |
aprimo-ci-cp-sdk | JavaScript | Aprimo (GitHub) | SDK for Content Intelligence & Personalization | S68 |
dam-metadata-extract-utility | C# | Aprimo (GitHub) | Bulk metadata export: rate pacing, cursor/keyset paging, delta, checkpoints | S68 S74 S38 |
| PKCE starter kits (Next.js, Angular) | TypeScript | Aprimo (GitHub) | Templates for custom pages inside Aprimo | S38 |
Other Aprimo-Connect repos | C#, TS, PowerShell, Apex | Aprimo (GitHub) | 26 repos: connectors (Optimizely, Contentful, Akeneo, inRiver, Salesforce), hot-folder upload, config mover, public-link crawler, Check Framework demo, M365 Copilot agent; "as-is", no support guarantee | S38 S68 |
aprimo-js | TypeScript | Community (Tim W.) | v2.4.0, 2026-09-24, MIT | S69 |
sanity-plugin-aprimo, Umbraco.Cms.Integrations.DAM.Aprimo, @uniformdev/canvas-aprimo | JS / .NET | Partners (Sanity, Umbraco HQ, Uniform) | Active 2024–2026 | S70 S75 |
| Postman collection | — | Aprimo | 420 requests with examples | S17 |
Changelog of the API
| Date | Change | |
|---|---|---|
| 2026-09-24 | Current full DAM Core spec (Last-Modified header of openapi.json) | S16 |
| 2026-06-01 | Enforcement of the 2025 deprecations: /api/oauth/* routes, <None>/"Authorization Code (Obsolete)" registrations, DAM page-hook auth-code, PM LaunchExternalApp.aspx tokens, upload.aprimo.com, uploads with expired tokens (date moved from 2026-03-02) | S18 |
| 2026-05-12 | MCP Server announced as part of the May 2026 release | S67 S52 |
| Unknown | Cursor pagination and the 100-record page-size clamp on records routes (documented in the current spec; introduction date not published) | S16 |
| Unknown | API deprecation policy (≥ 6 months notice) published | S19 |