Saleo Public API

Last updated: October 21, 2026

Demo Personalization workflow

Discover Saleo Live demos, retrieve personalization tokens, and create or maintain personalized views of them programmatically.

Field

Value

API version

v1

Request URL

https://api.platform.saleo.io/

Protocol

RPC over JSON; POST-only

Authentication

Bearer token — a per-user Saleo API key

1. Overview

The Saleo Public API lets an authorized integration discover Saleo Live demo templates, inspect their text personalization tokens, create personalized views with token overrides, update those views later, share them with colleagues, and hand them over to the colleague they are for — all outside the Saleo Portal.

Support Operations

Endpoint

Description

POST /v1/get_live_demos

Search demos and personalized views visible to the key's user.

POST /v1/get_demo_tokens

List the text tokens of a template or personalized view.

POST /v1/create_personalized_view

Create a personalized view of a template.

POST /v1/update_personalized_view

Update token values, rename, share, and/or transfer ownership of a view.

POST /v1/get_user_id

Resolve a colleague’s email to the user id needed to share or transfer a view.

2. Authentication

All requests require a bearer token:

Authorization: Bearer <user_api_key>

Unlike team-wide tokens, this API uses user API keys. A user API key is bound to the Saleo user who created it: every call acts as that user, sees only the demos they can see, and creates views owned by them.

Creating and managing your key

  • Any user can create their own key in the Saleo Portal: profile menu → API Keys → Create My API Key. The key value is shown only once, at creation — copy it immediately; it cannot be retrieved later.

  • Each user can hold one active key at a time. To rotate, revoke the existing key and create a new one.

  • Revoking a key is permanent and takes effect on its next request. Keys can also be renamed to record what they're used for.

  • Admins can see and revoke every key on the team under Settings → Manage SCIM/API Access Tokens, including when each was last used. Non-admin users only see their own key.

  • A key stops working the moment its user is deactivated.

Partner teams:  user API keys are not available to Saleo partner (reseller) accounts — neither to create nor to use. This does not apply to standard customer tenants.

Security Recommendation

Call this API from your own backend or approved integration layer, not directly from an untrusted browser client. Store the API key the same way you'd store any credential — encrypted at rest, never embedded in front-end code — and rotate it if it may have been exposed.

3. Quick start: create a personalized demo view

Step 1 — Find a personalizable demo

curl --request POST \
  --url https://api.platform.saleo.io/v1/get_live_demos \
  --header "Authorization: Bearer $SALEO_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "search": "EA-4711",
    "personalizableOnly": true,
    "limit": 25
  }' {
  "data": [
    {
      "id": "d3f2a1b0-...",
      "name": "EA-4711 ACME Overview",
      "tags": ["Retail"],
      "owner": { "userId": "u-1", "name": "Sally Seller", "email": "rep@acme.com" },
      "personalizable": true,
      "personalizedView": false,
      "playUrl": "https://.../play/d3f2a1b0-...",
      "createdAt": "2026-07-07T12:00:00Z",
      "updatedAt": "2026-07-07T12:00:00Z"
    }
  ]
}

Step 2 — List the template's tokens

curl --request POST \
  --url https://api.platform.saleo.io/v1/get_demo_tokens \
  --header "Authorization: Bearer $SALEO_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{ "demoId": "d3f2a1b0-..." }' {
  "data": [
    { "id": "t-company", "name": "%%company%%", "description": "Customer name",
      "tags": ["Company Info"], "value": "ACME", "overridden": false }
  ]
}

Step 3 — Create a personalized view

curl --request POST \
  --url https://api.platform.saleo.io/v1/create_personalized_view \
  --header "Authorization: Bearer $SALEO_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "demoId": "d3f2a1b0-...",
    "name": "ACME for Globex",
    "tokenValues": [ { "tokenId": "t-company", "value": "Globex" } ]
  }' {
  "view": { "id": "v-0000-...", "name": "ACME for Globex",
    "personalizedView": true, "parentDemoId": "d3f2a1b0-...",
    "playUrl": "https://.../play/v-0000-..." },
  "appliedTokens": [
    { "id": "t-company", "name": "%%company%%", "value": "Globex", "overridden": true }
  ]
}

Every token value in the request must apply. An unknown token id or an over-length value (1000 char max) fails the whole call and creates nothing — there's no partial success to check for.

Step 4 — Update it later

Use the same view id to refresh token values, rename the view, share it with colleagues, or hand it over to the rep it was personalized for as the deal changes — see update_personalized_view below.

4. Endpoint reference

POST /v1/get_live_demos

Returns the demos the key’s user works with: personalizable templates they can view, plus personalized views they own or that are shared with them. Returned newest-created first.

Field

Type

Required

Description

search

string

No

Case-insensitive match over demo names and tag labels.

tags

array

No

Tag labels; a demo matches if it carries any of them.

ownerEmail

string

No

Demos owned by this user, matched case-insensitively.

sharedWithEmail

string

No

Demos shared directly with this user (view or edit), matched case-insensitively.

personalizableOnly

boolean

No

Governs templates only, default true. Personalized views are always returned — filter on personalizedView client-side.

limit

integer

No

Default 100, capped at 500.

continuationToken

string

No

Cursor from the previous response.

Filters combine: a demo has to match every filter you send. sharedWithEmail matches direct user shares only. Shares made in the portal to a user group, a role or the whole team do not match. Both email filters only narrow what the key’s user can already see. To list a rep’s views by email, the key’s user must still be able to reach them, for example as their owner or a user they are shared with.

owner in the response is the demo’s current owner. After a transfer, this is the new owner, not the user who created the view.

POST /v1/get_demo_tokens

Returns the text tokens of a template or a personalized view — tokens declared at any level of the demo's parent chain are included. Image tokens are not returned; this API personalizes text only.

Field

Type

Required

Description

demoId

string

Yes

A template id or a personalized view id.

POST /v1/create_personalized_view

Creates a personalized view of a template: a private copy owned by the key's user, carrying the requested token values. Only its owner can see the view until it is shared, through update_personalized_view or in the portal.

Field

Type

Required

Description

demoId

string

Yes

The template to personalize; must be personalizable.

name

string

Yes

Must be unique within the team.

tokenValues

array

No

Objects of { tokenId, value }. Values capped at 1000 characters.

POST /v1/update_personalized_view

Changes token values on an existing view. It can also rename the view, share it with colleagues and transfer its ownership. An integration can keep one view id and refresh it as the deal changes.

These users can update a view, matching the Saleo Portal:

  • the view’s owner

  • a team admin

  • a user the view is shared with as an editor

Field

Type

Required

Description

viewId

string

Yes

From create_personalized_view or get_live_demos.

tokenValues

array

No

Only the tokens named here change; the rest keep their values.

sharedWith

array

No

Objects of { userId, canEdit }. Omit to leave sharing untouched. Max 100 users per call. userId comes from get_user_id — emails are not accepted here.

newOwnerUserId

string

No

From get_user_id. Makes this user the view’s owner.

name

string

No

Rename the view; unique within the team. Re-sending the current name does nothing.

Sharing rules

  • Add-only. A user named in sharedWith is added to whoever the view is already shared with. An existing share can be raised from view to edit, but never lowered or removed — there's no un-share through this API. Remove a share in the portal.

  • canEdit in the portal depends on the recipient’s seat. In the Saleo Portal, canEdit only lets users edit if their seat allows editing at all. A sales-seat colleague keeps view access there, whatever you send. Through this API, a user the view is shared with directly as an editor can update it on any seat.

  • The owner is ignored. A share naming the view's own owner is dropped silently, since they already have access.

  • All or nothing. If any userId is not an active user of the key's team, the whole call fails and nobody is shared.

Sharing a view also makes its parent template visible to that user in the portal, so they can open the view without an extra step.

Transferring ownership

Send newOwnerUserId to hand the view to another user, for example the rep it was personalized for. The rep can then find it with ownerEmail, or open it in the portal as their own.

  • Anyone who can update the view can transfer it: its owner, a team admin or an editor.

  • The previous owner keeps edit access. They are added as an editor, so they can keep updating the view through this API on any seat.

  • The new owner’s existing share is removed, since owning the view already gives them access. A sharedWith entry in the same call naming the new owner is dropped the same way.

  • Naming the current owner does nothing.

  • The new owner has to be an active user of the key’s team. Otherwise the whole call fails and nothing changes.

A transfer can be combined with token, name and sharing changes in a single call.

After a transfer, sharedWith in the response includes the previous owner as an editor.

POST /v1/get_user_id

Resolves a colleague's email address to the user id that the sharedWith and newOwnerUserId fields take. Only active users of the key's own team resolve.

Field

Type

Required

Description

email

string

Yes

Matched case-insensitively; surrounding spaces ignored.

A user of another team, a deactivated user, and one who hasn't yet accepted their invitation all return the same 404 — the API never reveals who exists elsewhere in Saleo.

5. Error format

All error responses share this shape. The HTTP status carries the error class; the body's code field is the corresponding gRPC status number.

{
  "code": 5,
  "error": "Personalized view not found"
}

HTTP status

Meaning

400

A required field is missing, a token id is unknown, or a value exceeds 1000 characters — nothing changes. Also covers demo/view-type mismatches, e.g. “This demo does not allow personalized views.”

Also fails when a share entry carries no userId ("sharedWith entries require a userId" — resolve one via get_user_id), when a shared userId isn't an active user of the team, or when more than 100 users are named in one call ("Exceeded limit of 100 users to share with" — split across calls; sharing is add-only, so earlier shares are kept).

Also fails when newOwnerUserId is blank (“newOwnerUserId cannot be blank” — omit the field to keep the current owner) or isn’t an active user of the team (“<userId>: no such active user on this team” — nothing changes).

401

Missing API key, an invalid access token, a team-wide token used in place of a user API key, a deactivated user, or a deactivated company account.

403

The team is a partner team. On update: “You do not have edit access to this personalized view” — the key’s user isn’t the view’s owner, a team admin, or an editor of the view.

404

The demo or view does not exist, or belongs to another team.

404 — "User not found."

No active user of your team holds that email.

409

A demo with the requested name already exists.

6. Integration recommendations

  • Run Saleo API calls from your own backend service or approved integration layer, not directly from an untrusted browser client.

  • Map your own business identifiers (transaction, conversation, opportunity, or workflow id) to Saleo demoId and viewId values in a durable integration table.

  • Cache demo discovery results briefly, but re-read tokens before personalizing when template authors may have changed them.

  • Validate that a selected demo is personalizable before creating a view.

  • Treat playUrl as the base launch URL returned by Saleo — append your own ?startUrl= parameter before sharing it, rather than reconstructing the rest of the URL yourself.

  • Since create and update calls fail atomically, validate token ids and values client-side before sending to avoid unnecessary round trips.