Goal
Let CMS editors select approved media without exposing an account API key or making originals public.Prerequisites
- Published, rights-valid media in a selected Assets space and channel.
- A host backend that authenticates editors and holds a restricted Assets account credential.
- The built @stackshift-cloud/assets-picker package in your application.
Workflow
1
Create a host capability endpoint with fixed server-side scope restrictions.
2
Mount the picker and return {token} from getCapability.
3
Validate and save stable publication/version/rendition references on selection.
4
Resolve fresh delivery on the server when a permitted viewer opens the content.
Picker scope
The picker searches and selects published media. It is not the upload widget and does not expose originals. Its search results remain constrained by the issuer’s current access, channel, bucket/collection restrictions and publication rights. The browser receives a short-lived capability. Your account API key stays on the host backend. Each request rechecks current policy; removing access or withdrawing a publication cannot be bypassed with a cached picker result.Build and install
Build the repository package and install it in your application using the commands below.Host capability endpoint
Authenticate the editor, apply your host application’s CSRF protection when using cookies, and resolve the allowed space/channel from server-side CMS configuration. Create the SDK with assetSpaceId. Do not let the browser widen the origins, buckets, collections or actions. Return {token}, not the entire StackShift success envelope. Keep capability responses private/no-store. A registered HTTPS origin contains only scheme, host and optional port—no wildcard, trailing slash, path, query or fragment.Capability limits
- origins: 1–10 exact normalized HTTPS origins. apiOrigin for the picker is the trusted HTTPS API origin without /api/v1.
- buckets and collections: at most 20 each. Bucket identifiers are strings; collection identifiers are UUIDs. Nonempty bucket and collection restrictions intersect. Empty lists add no extra restriction; they do not grant access the issuer lacks.
- channel: a stable identifier matching [a-z][a-z0-9_]{0,63}. It must match the publication channel.
- actions: search and/or select; default includes both. No upload, edit, original download or arbitrary SDK operation is granted.
- result_limit: 1–100, default 1. It bounds result pages and a selection submission.
- expires_in_seconds: 60–3600, default 900. Expiry can be refreshed by the host callback; a revoked permission is not repaired by issuing broader credentials.
Browser callbacks: picker-callbacks.js
Save these callbacks in picker-callbacks.js for either embed below. The host endpoints are examples you implement, not built-in StackShift routes. Apply the host’s authentication/CSRF protection to both capability creation and saving; validate selected references on the server before persisting them.Plain JavaScript embed
React embed and styles
React accepts the same apiOrigin, getCapability, onSelect and optional onCancel callbacks. Remount with a new React key when switching the host context or Assets space. No global stylesheet is needed: the picker renders in a shadow root. A surrounding modal still needs the host application’s focus trap and focus restoration.- Set —ssp-background, —ssp-foreground, —ssp-muted, —ssp-border, —ssp-accent and —ssp-accent-text on the host to match your semantic theme.
- Keyboard activation, search, pagination, selection limits, loading/empty states and retry are handled by the picker.
Save references, then resolve delivery
onSelect receives publication_id, asset_id, version_id, name, channel and approved rendition reference objects. Store the stable references with the product/post. Treat browser submissions as untrusted: revalidate each selected publication and its allowed space/channel before saving. Do not trust a client-supplied preview_url or arbitrary rendition ID. At viewing time, authorize the viewer and resolve only the references saved for that content. Fetch current publication delivery through the backend. Do not persist preview or delivery URLs: their credentials expire and current policy can revoke them earlier.Wire endpoints and error handling
The SDK creates/revokes capabilities through /api/v1/assets/picker-capabilities. Browser traffic uses POST /assets/picker/search and /assets/picker/select at the API origin, without /api/v1. Both use Authorization: Bearer <capability> and the browser’s exact Origin. Search sends {query,cursor}; selection sends {publication_ids}. Search query length is limited to 240 bytes. The transport refreshes once on 401 and retries that operation. A 403 stays visible as a permission error. A selection that is no longer allowed must not be silently saved from cached results. Use assets.dam.revokePickerCapability(capabilityId) when ending a session early. Revocation also invalidates preview credentials issued by that capability. Clear selected state when changing tenant/space instead of reusing the old picker mount.Go, Python and PHP: issue the browser capability
Call these functions only after authorizing the CMS editor. The channel and allowed HTTPS origin come from trusted application configuration. Add fixed buckets and collections to narrow selection further. Return only the token field as {token} with Cache-Control: private, no-store; do not return your account key.HTTP operations for this workflow
Management requests use Authorization: Bearer with your server-side Assets credential and X-Asset-Space-ID for the selected space. API-key scopes and space/collection permissions both apply. Successful JSON responses use {success: true, data: …}; the SDK methods return the unwrapped data. Paths shown outside /api/v1 use their dedicated short-lived credential.
For If-Match, quote the revision number, for example If-Match: “7”. On 412 assets.revision_conflict, reload the relevant resource and reconcile the edit before retrying. Use the revision of the resource being changed: asset, collaborator, schema, publication or gallery. A bucket-policy save instead places its current revision in the JSON body.
Capability and selection response fields
Capability creation returns capability and token. The capability includes its ID, allowed origins, buckets/collections, actions, channel, result limit and expiry. Store capability.id in your CMS session if you need explicit revocation; return only {token} from the browser callback. Do not log the token or persist it with product content. POST /assets/picker/search sends {query, cursor}; query is at most 240 bytes and cursor is an optional UUID from the previous result. The response data contains items, next_cursor, result_limit and expires_at. POST /assets/picker/select sends {publication_ids: […]}; the response data is the ordered selection array. The requested selection must be nonempty and fit the capability’s result limit. Every search/select request carries the capability as Bearer and the matching browser Origin. A capability remains constrained by the issuing actor’s current access and the publication’s channel, rights and availability. Expired or revoked capabilities require a new authorized issuance; do not retry with a permanent API key in the browser. On CMS save, authorize the editor against the product record and validate the selected publication references on your backend. Persist the returned reference fields needed by the publication/gallery resolver. Preview URLs are disposable. If access changes between selection and save, show the failed item and let the editor select again.Expected result
Your CMS stores approved stable media references while browser selection and viewing use only short-lived, scoped credentials.
Common failures
Related guides
Publications, review and usage rights
Select immutable renditions, capture metadata and rights, submit editorial review, publish by channel, and withdraw delivery.
Create and embed media galleries
Arrange published images, video, spins and models with locale, alternate text, approved fallbacks and stable published revisions.
Use Assets in WordPress
Install the StackShift Assets plugin, select approved media in Gutenberg, publish stable gallery references, and maintain revocation-aware delivery.
Direct browser uploads
Upload browser files directly with short-lived sessions, per-part checksums, progress callbacks, retries, resume, and cancellation.
Assets SDKs: JavaScript, Go, Python and PHP
Configure space-scoped clients and use native video, governed DAM, model rendering, galleries and CMS capabilities in all four SDKs.