Get started
Select your first artwork.
Add a “Choose artwork” button to your CMS, open the hosted Picker, and put the selection into your content form. You’ll build two backend endpoints and connect them with the browser SDK.
Choose your environment
This quickstart and the integration guides use Test. The API reference labels its Production examples separately. When you launch, switch the backend API origin, SDK script, pickerOrigin and tenant token together. Register the production CMS origin in that environment too.
| Environment | Origin | REST API | Picker SDK |
|---|---|---|---|
| Production | https://collection.vieunite.com | https://collection.vieunite.com/v1 | https://collection.vieunite.com/sdk/v1/picker.js |
| Test | https://collection-test.vieunite.com | https://collection-test.vieunite.com/v1 | https://collection-test.vieunite.com/sdk/v1/picker.js |
Configure your CMS backend
Store the tenant token in your secret manager or server environment. Do not expose it through HTML, browser JavaScript, logs, URLs or client-side storage.
VIEUNITE_TENANT_TOKEN=<tenant-token>
CMS_PUBLIC_URL=https://cms.example.com
export VIEUNITE_TENANT_TOKEN="<tenant-token>"
export CMS_PUBLIC_URL="https://cms.example.com"
$env:VIEUNITE_TENANT_TOKEN = "<tenant-token>"
$env:CMS_PUBLIC_URL = "https://cms.example.com"
First, check that your server can reach the Test API:
curl "https://collection-test.vieunite.com/v1/capabilities"
Expect 200 OK with the API’s supported resources and filters. This endpoint is public, so success checks connectivity only. Creating a Picker session in the next step checks your token, scopes and registered origin.
Add two CMS bridge endpoints
These routes belong to your CMS. The first asks Vieunite to create a session; the second exchanges the editor’s completed selection for artwork references. The SDK calls both for you.
POST /api/vieunite/picker/sessionPOST /api/vieunite/picker/redeemUse your existing editor login and CSRF checks. Store who opened each session, including their organisation and content context, and check that ownership on redemption. Keep the tenant token on this backend.
The bridge response examples show the JSON the SDK expects. The backend examples show the Vieunite calls and identify the CMS helpers you need to supply. Finish those routes before connecting the button below.
Connect the button
Put this markup inside your existing content form. Have your server render the CSRF value using your framework’s template syntax. If your CMS uses another CSRF header name, change X-CSRF-Token to match.
<script src="https://collection-test.vieunite.com/sdk/v1/picker.js"></script>
<meta name="csrf-token" content="{{ csrf_token }}">
<button type="button" id="choose-artwork">Choose artwork</button>
<input type="hidden" name="vieunite_references" id="artwork-references" value="[]">
<p id="artwork-status" role="status">No artwork selected.</p>
<script>
const picker = VieunitePicker.create({
sessionEndpoint: "/api/vieunite/picker/session",
redeemEndpoint: "/api/vieunite/picker/redeem",
pickerOrigin: "https://collection-test.vieunite.com",
headers: {
"X-CSRF-Token": document.querySelector('meta[name="csrf-token"]').content,
},
});
const button = document.querySelector("#choose-artwork");
const field = document.querySelector("#artwork-references");
const statusMessage = document.querySelector("#artwork-status");
button.addEventListener("click", async () => {
button.disabled = true;
statusMessage.textContent = "Opening the artwork library…";
try {
const result = await picker.open({
allowedTypes: ["artwork"],
selectionMode: "multiple",
maxSelection: 0,
});
if (result.status === "cancelled") {
statusMessage.textContent = "Selection unchanged.";
return;
}
field.value = JSON.stringify(result.selection);
statusMessage.textContent = `${result.selection.length} artwork(s) selected. Save your form to keep them.`;
} catch (error) {
statusMessage.textContent = "The artwork library could not finish. Please try again.";
console.error("Picker failed", error.code || "unknown_error");
} finally {
button.disabled = false;
}
});
</script>
// Use the markup from the JavaScript tab and include picker.d.ts in your project.
const picker: VieunitePicker.PickerClient = VieunitePicker.create({
sessionEndpoint: "/api/vieunite/picker/session",
redeemEndpoint: "/api/vieunite/picker/redeem",
pickerOrigin: "https://collection-test.vieunite.com",
headers: {
"X-CSRF-Token": document.querySelector<HTMLMetaElement>('meta[name="csrf-token"]')!.content,
},
});
const button = document.querySelector<HTMLButtonElement>("#choose-artwork")!;
const field = document.querySelector<HTMLInputElement>("#artwork-references")!;
const statusMessage = document.querySelector<HTMLElement>("#artwork-status")!;
button.addEventListener("click", async () => {
button.disabled = true;
statusMessage.textContent = "Opening the artwork library…";
try {
const result = await picker.open({
allowedTypes: ["artwork"],
selectionMode: "multiple",
maxSelection: 0,
});
if (result.status === "cancelled") {
statusMessage.textContent = "Selection unchanged.";
return;
}
field.value = JSON.stringify(result.selection);
statusMessage.textContent = `${result.selection.length} artwork(s) selected. Save your form to keep them.`;
} catch (error) {
statusMessage.textContent = "The artwork library could not finish. Please try again.";
console.error("Picker failed", error instanceof VieunitePicker.PickerError ? error.code : "unknown_error");
} finally {
button.disabled = false;
}
});
Success means the modal closes and the form shows the selected count. Cancelling keeps the previous field value. If you use a client-side router, call picker.destroy() when this editor component is permanently removed.
Save the returned references
The button updates the form; it does not save to your database. In your normal form-save handler, parse vieunite_references, check the editor’s permission to update this entry, and validate the references on the backend. Store these four fields for each artwork:
{
"provider": "vieunite-art-collection",
"type": "artwork",
"id": "art_456",
"rendition": "crop"
}
art_456 and crop are examples. Save the ID and rendition returned by your own selection unchanged. A rendition is the chosen image version; don’t guess its key from its name or dimensions.
To display the artwork, resolve the saved reference from your backend, then request a signed URL for that rendition. Resolution returns current metadata and availability; the signed URL lets you fetch the image. If your CMS imports local media, follow the Nexus example.
Understand the Artwork attributes Resolve the reference Deliver the selected assetCheck your integration
Try a selection, then a cancellation.
Select two artworks, save the form and reload it. Confirm the same IDs and renditions were saved. Open the Picker again and cancel; your saved selection should stay intact. The demos below show the expected browser experience, using a separate demo backend.