Vieunite.Developers
Open quickstart

Keeping content current

React to catalogue changes.

Use cursor-based Sync as the reliable change feed for a local index. Use webhooks and delivery controls when your integration needs event-driven processing or delivery testing.

Choose the right mechanism

Incremental Sync

Pull changes in order

Best for scheduled jobs, recovery, local search indexes and deterministic progress through the complete change feed.

GET /v1/sync

Webhooks

Process an event delivery

Best for low-latency triggers and event-driven refresh. Consumers must verify signatures and deduplicate deliveries.

/v1/webhooks/*

Large integrations commonly use both: webhooks trigger fast refreshes and Sync closes any gap after downtime.

Incremental Sync

Start without a cursor. Persist next_cursor only after your CMS has committed the page successfully, then pass it unchanged on the next request.

pull artwork and collection changescURL
curl --get "https://collection.vieunite.com/v1/sync" \
  -H "Authorization: Bearer $VIEUNITE_TENANT_TOKEN" \
  --data-urlencode "types=artwork,collection" \
  --data-urlencode "limit=100" \
  --data-urlencode "cursor=$LAST_COMMITTED_CURSOR"
sync pageJSON
{
  "data": [
    {
      "event_id": "evt_123",
      "type": "artwork",
      "id": "art_456",
      "action": "update",
      "version": 7,
      "updated_at": "2026-07-15T16:30:43Z",
      "idempotency_key": "artwork:art_456:7",
      "links": { "resource": "/v1/artworks/art_456" }
    }
  ],
  "next_cursor": "eyJvZmZzZXQiOjEwMH0",
  "has_more": true
}

Apply change events

  • publish or updateResolve or fetch the current resource and replace the cached version transactionally.
  • deleteRemove it from discovery and mark stored references unavailable using the supplied reason.
  • Repeated eventDeduplicate with idempotency_key or compare the incoming resource version.
  • Processing failureDo not advance the committed cursor until the page can be replayed safely.

Register a webhook endpoint

Creation returns the signing secret once. Store it immediately in your secret manager.

create endpointcURL
curl --request POST "https://collection.vieunite.com/v1/webhooks/endpoints" \
  -H "Authorization: Bearer $VIEUNITE_TENANT_TOKEN" \
  -H "Content-Type: application/json" \
  --data '{
  "url": "https://cms.example.com/webhooks/vieunite",
  "event_types": [
    "artwork.updated",
    "artwork.unpublished",
    "artwork.rights_updated",
    "artwork.asset_updated",
    "collection.updated"
  ]
}'

Verify webhook signatures

Compute a base64 HMAC-SHA256 over <timestamp>.<raw-request-body>. Use the unparsed request bytes, reject stale timestamps, and compare in constant time.

signature verificationJavaScript
import crypto from "node:crypto";

const MAX_AGE_SECONDS = 300;

function verifyVieuniteWebhook({ rawBody, headers, secret }) {
  if (!Buffer.isBuffer(rawBody)) {
    throw new TypeError("rawBody must be the unparsed request Buffer");
  }

  const timestamp = headers["x-vieunite-timestamp"] || "";
  const supplied = headers["x-vieunite-signature"] || "";
  if (!/^\d+$/.test(timestamp)) return false;

  const timestampSeconds = Number(timestamp);
  const age = Math.abs(Math.floor(Date.now() / 1000) - timestampSeconds);
  if (!Number.isSafeInteger(timestampSeconds) || age > MAX_AGE_SECONDS) {
    return false;
  }

  const signedBytes = Buffer.concat([
    Buffer.from(timestamp, "ascii"),
    Buffer.from(".", "ascii"),
    rawBody,
  ]);
  const digest = crypto
    .createHmac("sha256", secret)
    .update(signedBytes)
    .digest("base64");
  const expected = Buffer.from(`v1=${digest}`, "ascii");
  const received = Buffer.from(supplied, "ascii");

  return expected.length === received.length &&
    crypto.timingSafeEqual(expected, received);
}
X-Vieunite-TimestampUnix timestamp included in the signed message. X-Vieunite-Signaturev1=<base64-signature>. Idempotency-KeyStable key for deduplicating the event.

Delivery controls

The API exposes event listing and explicit delivery preparation. A dry run returns the exact payload, signature headers and eligible target without sending an HTTP request.

prepare a deliverycURL
curl --request POST "https://collection.vieunite.com/v1/webhooks/events/evt_123/deliver" \
  -H "Authorization: Bearer $VIEUNITE_TENANT_TOKEN" \
  -H "Content-Type: application/json" \
  --data '{
  "endpoint_id": "wep_123",
  "dry_run": true,
  "timeout_seconds": 5
}'

Only set dry_run to false when intentionally requesting a real synchronous delivery. Treat this as an advanced testing or replay operation.

Search documentation

Start with “Picker”, “rendition”, or an endpoint path.