Skip to main content

Embedded Web SDK API

The endpoints that the @devotel-orbit/web browser SDK calls at runtime. Mounted at /sdk/* (no /api/v1 prefix) so client-side embeds don’t have to think about API versions. Base path: https://api.orbit.devotel.io/sdk Authentication: Tenant public key (dv_live_pk_*) sent in the X-API-Key header. CORS is open — these endpoints are designed to be called directly from your website’s JavaScript. Why a separate base path: server-to-server keys (dv_live_sk_* in the Authorization header) are secret. Browser-embedded public keys (dv_live_pk_* in X-API-Key) are safe to ship in client-side code. The split base prevents accidentally exposing a server key in a browser bundle. Response envelope: every endpoint returns the platform envelope — data plus a meta block with request_id and timestamp.

Identify

Resolve an anonymous browser visitor to a known contact (by email or phone). Events captured before the visitor identifies attach to the right contact once the server backfills. The response returns the resolved contact_id:
anonymous_id is required (it ties the call back to the browser session). Include at least one of email or phone — omitting both returns a 400/422 validation error. display_name and traits are optional. Identifying is idempotent: repeat calls with the same email or phone update the same contact_id.

Track

Capture one or more custom events (page view, button click, video watched, item added to cart). Events flow into the same store that powers segmentation, scoring, and contact timelines. A batch returns the count of accepted events:
Send up to 50 events per call. Each event needs a name; properties and an ISO-8601 timestamp are optional (properties are capped at 8 KiB per event — split or trim larger payloads). The required anonymous_id identifies the browser session, so events captured before a visitor identifies still attach to the right contact. You can also pass identity ({ "email": ... } or { "phone": ... }) to attribute the batch to an existing contact without an identify call.

Personalize

Resolve the right personalization slot variant for the current visitor at runtime. The response carries the slot’s content, CTA, matched variant, and the segment that matched (or null when the slot default applied):
Pass phone or email alongside anonymous_id to resolve the visitor’s segment. With no matching variant, content is empty and variant is null — render your site’s own default. Responses carry a Cache-Control: private, max-age=60 header, so repeat pulls from the same browser hit the local cache.

Server-to-server calls

The /sdk/identify and /sdk/track endpoints also accept calls from your backend — a CRM sync, an order pipeline, a nightly export job — not just from the browser. Same envelope and body shape, sent with the tenant public key (dv_live_pk_) in the X-API-Key header. The endpoints accept both transports, but use the right key class: server-to-server pipelines send the public key, never a secret key (dv_live_sk_). Browsers remain the preferred integration for behavioural events — the @devotel-orbit/web package batches them safely, handles CORS, and manages anonymous ids automatically. Only use the server-side path when the events genuinely originate in your backend. Node.js (a CRM-side event push):
Python (same two calls with requests):
Batching discipline is yours on the server. The browser SDK transparently batches up to 25 events every 2 seconds and flushes on page exit; a raw server-side caller must decide this trade-off explicitly. Group events into a single /sdk/track batch (up to 50 per call) instead of firing one HTTP request per event — both to stay under the per-key pacing and to keep CORS/browser semantics out of the loop. Grouping by callers like a CRM import also lets you pass a single shared identity in one batch call rather than one call per contact.

Use the SDK instead of raw fetch

For browser integrations, use the @devotel-orbit/web package — it handles the anonymous id for you (a stable id persisted in the visitor’s browser), batches events into groups of up to 25 every 2 seconds, and flushes on page exit. The raw-fetch flow above becomes:
Every page has a stable orbit.anonymousId you can reference in server-side flows; orbit.reset() clears a remembered identity for explicit logouts.

See also