v1.0

Guidez Developer Platform

The complete reference for the Guidez REST API, JavaScript SDK, CLI, and MCP server. Build programmatic onboarding flows, identify users, track analytics, and automate everything.

The Guidez API is organized around REST. All requests must be made over HTTPS. Responses are returned as JSON. We also offer a native JavaScript SDK, a CLI for terminal workflows, and an MCP server so Claude, Cursor, and Windsurf can call Guidez tools natively.

Base URL: https://api.guidez.io/v1  —  All REST endpoints are prefixed with this URL.

What can you build?

  • Identify and segment users at sign-up, then trigger contextual tours automatically
  • Sync your CRM's company data so Guidez knows account context
  • Pull session completion data into your data warehouse for activation analysis
  • Receive real-time webhook events when users complete onboarding milestones
  • Use the CLI in CI/CD to manage content across environments
  • Let your AI assistant (Claude, GPT, etc.) query Guidez data via the MCP server

Content types

Guidez content (tours, checklists, banners, NPS surveys) is unified under the /v1/content resource. Filter by type to work with specific content types.

Quick links

# REST API base
https://api.guidez.io/v1

# JavaScript SDK
npm install @guidez/sdk

# CLI
npm install -g @guidez/cli

# MCP Server
npm install @guidez/mcp

Available SDKs

// JavaScript / TypeScript
import Guidez from '@guidez/sdk';

# Python (pip)
pip install guidez-sdk

# Ruby (gem)
gem install guidez

# Go
go get github.com/guidez/guidez-go

5-Minute Quickstart

Get from zero to your first user identified and tour triggered in five steps.

  1. 1

    Get your API key

    Go to Dashboard → Settings → Environments → API Keys. Create a secret key. It looks like env_live_xxxxxxxx. Store it securely — never expose it in client-side code.

  2. 2

    Get your Environment ID

    Also on the Environments page, copy your Environment ID. It looks like cm9cs634h00001mp50l45n7kz. Pass it as the x-environment-id header with every request.

  3. 3

    Identify your first user

    Call POST /v1/users with the user's external ID from your database. You can include attributes like name and email for targeting.

  4. 4

    Install the JavaScript SDK

    Add @guidez/sdk to your frontend. Call Guidez.identify() on sign-in. Guidez will automatically evaluate targeting rules and show the right content.

  5. 5

    Watch sessions flow in

    Query GET /v1/content-sessions or open the Dashboard → Analytics to see real-time completion data.

Full quickstart example

# 1. Identify a user
curl -X POST https://api.guidez.io/v1/users \
  -H "Authorization: Bearer env_live_xxxx" \
  -H "x-environment-id: cm9cs634h..." \
  -H "Content-Type: application/json" \
  -d '{
    "id": "user_123",
    "attributes": {
      "name": "Jane Smith",
      "email": "jane@acme.com",
      "plan": "pro"
    }
  }'

# 2. List content to find tour ID
curl https://api.guidez.io/v1/content \
  -H "Authorization: Bearer env_live_xxxx" \
  -H "x-environment-id: cm9cs634h..."
const headers = {
  'Authorization': 'Bearer env_live_xxxx',
  'x-environment-id': 'cm9cs634h...',
  'Content-Type': 'application/json',
};

// 1. Identify a user
await fetch('https://api.guidez.io/v1/users', {
  method: 'POST',
  headers,
  body: JSON.stringify({
    id: 'user_123',
    attributes: { name: 'Jane Smith', email: 'jane@acme.com' }
  })
});

// 2. List content
const content = await fetch(
  'https://api.guidez.io/v1/content',
  { headers }
).then(r => r.json());
import requests

headers = {
    "Authorization": "Bearer env_live_xxxx",
    "x-environment-id": "cm9cs634h...",
}

# 1. Identify a user
requests.post(
    "https://api.guidez.io/v1/users",
    headers=headers,
    json={
        "id": "user_123",
        "attributes": {"name": "Jane Smith"}
    }
)

# 2. List content
resp = requests.get(
    "https://api.guidez.io/v1/content",
    headers=headers
)
content = resp.json()

Authentication

Guidez uses Bearer token authentication. Pass your API key in the Authorization header with every request.

Authorization: Bearer env_live_sk_xxxxxxxxxxxxxxxxxxxxxxxx

Key types

TypePrefixUse case
Secret keyenv_live_Server-side API calls only. Full read/write access. Never expose in browsers or mobile apps.
Test keyenv_test_Development & staging. Same permissions but operates against your test environment.

Environment header

Every request must also include the environment ID header. This scopes all data to a specific environment (production, staging, development).

x-environment-id: cm9cs634h00001mp50l45n7kz

Key rotation

Rotate keys any time from Dashboard → Settings → Environments → API Keys. Old keys are invalidated immediately. Keep your keys in environment variables or a secrets manager — never hardcode them.

Never expose secret keys client-side. Use the JavaScript SDK with a publishable key for browser-based identification.

Authenticated request

curl https://api.guidez.io/v1/users \
  -H "Authorization: Bearer env_live_sk_xxx" \
  -H "x-environment-id: cm9cs634h..."
const BASE = 'https://api.guidez.io/v1';
const headers = {
  'Authorization': `Bearer ${process.env.GUIDEZ_API_KEY}`,
  'x-environment-id': process.env.GUIDEZ_ENV_ID,
};

const res = await fetch(`${BASE}/users`, { headers });
const data = await res.json();
import os, requests

headers = {
    "Authorization": f"Bearer {os.environ['GUIDEZ_API_KEY']}",
    "x-environment-id": os.environ["GUIDEZ_ENV_ID"],
}
resp = requests.get(
    "https://api.guidez.io/v1/users",
    headers=headers
)

401 Unauthorized

{
  "statusCode": 401,
  "message": "Unauthorized",
  "error": "Invalid or missing API key"
}

Environments

Environments are isolated namespaces within a project. Most teams have at least Production and Development environments. Users, companies, content, and sessions are completely separate between environments.

Finding your environment ID

Your environment ID is visible in the Dashboard under Settings → Environments. It's a unique string like cm9cs634h00001mp50l45n7kz.

Multiple environments

You can have up to 3 environments on the Growth plan, and unlimited on Business. Use separate environments for dev, staging, and production to avoid polluting real user data with test sessions.

Environment-scoped API keys

API keys are scoped to a single environment. A production API key will only return production data, even if you pass a staging environment ID in the header.

Tip: Set GUIDEZ_API_KEY and GUIDEZ_ENV_ID in your environment variables and never hardcode them. The CLI and MCP server both read these automatically.

Environment-scoped request

# Production
curl https://api.guidez.io/v1/content \
  -H "Authorization: Bearer env_live_sk_prod_xxx" \
  -H "x-environment-id: prod_env_id_here"

# Development (separate data)
curl https://api.guidez.io/v1/content \
  -H "Authorization: Bearer env_test_sk_dev_xxx" \
  -H "x-environment-id: dev_env_id_here"

Env vars convention

# .env (never commit this)
GUIDEZ_API_KEY=env_live_sk_xxxxxxxxxxxxxxxx
GUIDEZ_ENV_ID=cm9cs634h00001mp50l45n7kz
GUIDEZ_BASE_URL=https://api.guidez.io

Core Concepts

Understanding the Guidez data model makes working with the API intuitive.

User

A person using your product, identified by their external ID from your database. Users have attributes (name, plan, etc.) used for targeting.

Company

A group or account that users belong to (B2B use case). Companies have their own attributes and memberships linking users.

Content

A tour, checklist, banner, or NPS survey. Content has versions — a published version served to users and an edited draft. Filtered by type.

Content Session

One user's interaction with one piece of content. Created automatically when a user starts a tour. Records step completions, answers, and timestamps.

Attribute Definition

The schema for a custom attribute on users or companies. Defines the name, type (string/number/boolean/date), and which object it belongs to.

Event Definition

A named event that can be tracked on users (e.g., file_uploaded, invite_sent). Used for targeting rules in tours.

Upsert semantics

Users and companies are created or updated in a single POST call using their external id. If the record doesn't exist it's created; if it does, the provided attributes are merged (not replaced). This makes it safe to call on every sign-in.

Data model overview

// User with company membership
{
  "id": "user_123",
  "externalId": "user_123",
  "attributes": {
    "name": "Jane Smith",
    "email": "jane@acme.com",
    "plan": "pro"
  },
  "memberships": [{
    "company": {
      "id": "acme",
      "attributes": { "name": "Acme Inc." }
    }
  }],
  "createdAt": "2026-01-15T09:30:00Z"
}

// Content session
{
  "id": "cs_abc123",
  "contentId": "cnt_xyz789",
  "userId": "user_123",
  "state": "completed",
  "completedAt": "2026-01-15T09:35:00Z"
}

Errors & Status Codes

Guidez uses conventional HTTP response codes. Codes in the 2xx range indicate success. 4xx codes indicate a client error. 5xx codes indicate a server error (rare).

CodeMeaning
200 OKRequest succeeded. Response body contains the resource.
201 CreatedResource was created successfully.
204 No ContentRequest succeeded with no response body (DELETE).
400 Bad RequestMissing or invalid parameters. Check the message field for details.
401 UnauthorizedMissing or invalid API key. Check your Authorization header.
403 ForbiddenValid key but insufficient permissions for this operation.
404 Not FoundThe requested resource does not exist in this environment.
409 ConflictThe request conflicts with an existing resource.
422 UnprocessableValidation failed. The errors array lists field-level issues.
429 Too Many RequestsRate limit exceeded. See the Retry-After header.
500 Server ErrorSomething went wrong on our end. Retry with exponential backoff.

Error response shape

All errors return a JSON body with at least statusCode and message. Validation errors include an errors array.

Error response

// 400 Bad Request
{
  "statusCode": 400,
  "message": "Validation failed",
  "errors": [
    {
      "field": "id",
      "message": "id must be a string"
    }
  ]
}

// 404 Not Found
{
  "statusCode": 404,
  "message": "User not found",
  "error": "Not Found"
}

// 429 Rate Limited
{
  "statusCode": 429,
  "message": "Too Many Requests",
  "retryAfter": 60
}

Retry strategy

async function withRetry(fn, retries = 3) {
  for (let i = 0; i < retries; i++) {
    try {
      return await fn();
    } catch (err) {
      if (err.status === 429 || err.status >= 500) {
        await sleep(2 ** i * 1000);
        continue;
      }
      throw err;
    }
  }
}

Pagination

List endpoints use cursor-based pagination. This is more efficient than offset pagination and handles concurrent inserts correctly.

Query parameters

ParameterTypeDefaultDescription
limitoptinteger20Number of items per page. Max: 100.
cursoroptstringOpaque cursor from the previous response's next field.
orderByoptstringcreatedAtSort field. Prefix with - for descending (e.g., -createdAt).

Response shape

All list responses include results, next, and previous. Pass the next cursor to get the next page. A null value means you're on the last page.

Paginated response

{
  "results": [ ... ],
  "next": "cm9cs634h00001mp50l45n7kz",
  "previous": null
}

Iterate all pages

async function* paginate(url, headers) {
  let cursor = null;
  do {
    const params = cursor
      ? `?cursor=${cursor}&limit=100`
      : '?limit=100';
    const { results, next } = await
      fetch(url + params, { headers })
        .then(r => r.json());
    yield* results;
    cursor = next;
  } while (cursor);
}

for await (const user of
  paginate('/v1/users', headers)) {
  console.log(user.id);
}

Rate Limits

The API enforces rate limits per API key. Exceeding the limit returns a 429 Too Many Requests response with a Retry-After header indicating when you can retry.

PlanRequests / minuteBurst
Hobby60100
Starter300500
Growth1,0002,000
Business5,00010,000

Rate limit headers

Every response includes rate limit information in the headers.

HeaderDescription
X-RateLimit-LimitMax requests allowed per minute
X-RateLimit-RemainingRequests remaining in current window
X-RateLimit-ResetUnix timestamp when the window resets
Retry-AfterSeconds to wait before retrying (429 only)

Rate limit response headers

HTTP/1.1 200 OK
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 842
X-RateLimit-Reset: 1747500060

# When exceeded:
HTTP/1.1 429 Too Many Requests
Retry-After: 37
X-RateLimit-Reset: 1747500060
GET/v1/users

List Users

Returns a paginated list of users in the environment. Supports cursor-based pagination and sorting.

Query parameters

ParameterTypeDescription
limitoptintegerItems per page. Default: 20. Max: 100.
cursoroptstringCursor from previous response for pagination.
orderByoptstringcreatedAt or -createdAt (desc). Default: createdAt.
expandoptstring[]Relations to expand: companies, memberships, memberships.company.
curl "https://api.guidez.io/v1/users?limit=20&expand=memberships.company" \
  -H "Authorization: Bearer env_live_sk_xxx" \
  -H "x-environment-id: cm9cs634h..."
const res = await fetch(
  'https://api.guidez.io/v1/users?limit=20&expand=memberships.company',
  { headers }
);
const { results, next } = await res.json();
resp = requests.get(
    "https://api.guidez.io/v1/users",
    params={"limit": 20, "expand": "memberships.company"},
    headers=headers
)

Response

200 Success
{
  "results": [
    {
      "id": "usr_abc123",
      "externalId": "user_123",
      "attributes": {
        "name": "Jane Smith",
        "email": "jane@acme.com",
        "plan": "pro"
      },
      "createdAt": "2026-01-15T09:30:00Z"
    }
  ],
  "next": "cm9cs634h00001mp50l45n7kz",
  "previous": null
}
GET/v1/users/:id

Get User

Retrieve a single user by their external ID (the id you passed when identifying them).

Path parameters

ParameterTypeDescription
idreqstringThe user's external ID.

Query parameters

ParameterTypeDescription
expandoptstring[]Relations to expand: companies, memberships, memberships.company.
curl "https://api.guidez.io/v1/users/user_123?expand=memberships.company" \
  -H "Authorization: Bearer env_live_sk_xxx" \
  -H "x-environment-id: cm9cs634h..."
const user = await fetch(
  'https://api.guidez.io/v1/users/user_123?expand=memberships.company',
  { headers }
).then(r => r.json());
user = requests.get(
    "https://api.guidez.io/v1/users/user_123",
    params={"expand": "memberships.company"},
    headers=headers
).json()

Response

200 Success
{
  "id": "usr_abc123",
  "externalId": "user_123",
  "attributes": {
    "name": "Jane Smith",
    "email": "jane@acme.com",
    "plan": "pro",
    "signedUpAt": "2026-01-10"
  },
  "memberships": [{
    "company": {
      "id": "acme",
      "attributes": { "name": "Acme Inc." }
    }
  }],
  "createdAt": "2026-01-15T09:30:00Z"
}
POST/v1/users

Identify / Upsert User

Create or update a user. If the user doesn't exist it's created. If it exists, provided attributes are merged — existing attributes not in the payload are preserved. Safe to call on every sign-in.

Request body

FieldTypeDescription
idreqstringYour external user ID. This is the stable identifier from your database.
attributesoptobjectKey-value map of custom attributes. Values can be strings, numbers, booleans, or ISO 8601 dates.
companiesoptarrayArray of { id, attributes } objects. Adds the user to these companies (upserts them too).
membershipsoptarrayArray of { company: { id, attributes }, attributes } with membership-level attributes.
Call this on every sign-in. Guidez merges attributes incrementally, so it's always safe to pass all known user data.
curl -X POST https://api.guidez.io/v1/users \
  -H "Authorization: Bearer env_live_sk_xxx" \
  -H "x-environment-id: cm9cs634h..." \
  -H "Content-Type: application/json" \
  -d '{
    "id": "user_123",
    "attributes": {
      "name": "Jane Smith",
      "email": "jane@acme.com",
      "plan": "pro",
      "signedUpAt": "2026-01-10"
    },
    "companies": [
      { "id": "acme", "attributes": { "name": "Acme Inc." } }
    ]
  }'
await fetch('https://api.guidez.io/v1/users', {
  method: 'POST',
  headers: { ...headers, 'Content-Type': 'application/json' },
  body: JSON.stringify({
    id: 'user_123',
    attributes: {
      name: 'Jane Smith',
      email: 'jane@acme.com',
      plan: 'pro'
    },
    companies: [
      { id: 'acme', attributes: { name: 'Acme Inc.' } }
    ]
  })
});
requests.post(
    "https://api.guidez.io/v1/users",
    headers={**headers, "Content-Type": "application/json"},
    json={
        "id": "user_123",
        "attributes": {
            "name": "Jane Smith",
            "email": "jane@acme.com",
            "plan": "pro"
        },
        "companies": [
            {"id": "acme", "attributes": {"name": "Acme Inc."}}
        ]
    }
)

Response

200 Success
{
  "id": "usr_abc123",
  "externalId": "user_123",
  "attributes": {
    "name": "Jane Smith",
    "email": "jane@acme.com",
    "plan": "pro"
  },
  "createdAt": "2026-05-08T12:00:00Z"
}
DELETE/v1/users/:id

Delete User

Permanently deletes a user and all associated session data. This action cannot be undone. Use this for GDPR right-to-erasure compliance.

Path parameters

ParameterTypeDescription
idreqstringThe user's external ID.
Permanent. Deleting a user removes all their sessions and cannot be reversed.
curl -X DELETE https://api.guidez.io/v1/users/user_123 \
  -H "Authorization: Bearer env_live_sk_xxx" \
  -H "x-environment-id: cm9cs634h..."
await fetch('https://api.guidez.io/v1/users/user_123', {
  method: 'DELETE',
  headers
});
requests.delete(
    "https://api.guidez.io/v1/users/user_123",
    headers=headers
)

Response

200 Success
{ "deleted": true, "id": "user_123" }
GET/v1/companies

List Companies

Returns a paginated list of companies (accounts/organizations). Use expand to include their member users.

Query parameters

ParameterTypeDescription
limitoptintegerItems per page. Default: 20. Max: 100.
cursoroptstringPagination cursor from previous response.
orderByoptstringcreatedAt or -createdAt.
expandoptstring[]users, memberships, memberships.user.
curl "https://api.guidez.io/v1/companies?limit=20" \
  -H "Authorization: Bearer env_live_sk_xxx" \
  -H "x-environment-id: cm9cs634h..."
const { results } = await fetch(
  'https://api.guidez.io/v1/companies?limit=20',
  { headers }
).then(r => r.json());
resp = requests.get(
    "https://api.guidez.io/v1/companies",
    params={"limit": 20},
    headers=headers
).json()

Response

200 Success
{
  "results": [
    {
      "id": "cmp_xyz789",
      "externalId": "acme",
      "attributes": {
        "name": "Acme Inc.",
        "plan": "enterprise",
        "employees": 250
      },
      "createdAt": "2026-01-01T00:00:00Z"
    }
  ],
  "next": null,
  "previous": null
}
GET/v1/companies/:id

Get Company

Retrieve a single company by its external ID.

Path parameters

ParameterTypeDescription
idreqstringThe company's external ID.

Query parameters

ParameterTypeDescription
expandoptstring[]users, memberships, memberships.user.
curl "https://api.guidez.io/v1/companies/acme?expand=memberships.user" \
  -H "Authorization: Bearer env_live_sk_xxx" \
  -H "x-environment-id: cm9cs634h..."
const company = await fetch(
  'https://api.guidez.io/v1/companies/acme?expand=memberships.user',
  { headers }
).then(r => r.json());
company = requests.get(
    "https://api.guidez.io/v1/companies/acme",
    params={"expand": "memberships.user"},
    headers=headers
).json()
POST/v1/companies

Upsert Company

Create or update a company. Attributes are merged on update. Use this to sync account data from your CRM or database.

Request body

FieldTypeDescription
idreqstringYour external company/account ID.
attributesoptobjectKey-value attributes. Common: name, plan, employees, industry.
curl -X POST https://api.guidez.io/v1/companies \
  -H "Authorization: Bearer env_live_sk_xxx" \
  -H "x-environment-id: cm9cs634h..." \
  -H "Content-Type: application/json" \
  -d '{
    "id": "acme",
    "attributes": {
      "name": "Acme Inc.",
      "plan": "enterprise",
      "employees": 250,
      "industry": "Software"
    }
  }'
await fetch('https://api.guidez.io/v1/companies', {
  method: 'POST',
  headers: { ...headers, 'Content-Type': 'application/json' },
  body: JSON.stringify({
    id: 'acme',
    attributes: {
      name: 'Acme Inc.',
      plan: 'enterprise',
      employees: 250
    }
  })
});
requests.post(
    "https://api.guidez.io/v1/companies",
    headers={**headers, "Content-Type": "application/json"},
    json={
        "id": "acme",
        "attributes": {
            "name": "Acme Inc.",
            "plan": "enterprise"
        }
    }
)
DELETE/v1/companies/:id

Delete Company

Permanently deletes a company and all its membership records. User accounts linked to this company are not deleted.

Path parameters

ParameterTypeDescription
idreqstringThe company's external ID.
curl -X DELETE https://api.guidez.io/v1/companies/acme \
  -H "Authorization: Bearer env_live_sk_xxx" \
  -H "x-environment-id: cm9cs634h..."
await fetch('https://api.guidez.io/v1/companies/acme', {
  method: 'DELETE', headers
});
requests.delete(
    "https://api.guidez.io/v1/companies/acme",
    headers=headers
)

Response

200 Success
{ "deleted": true, "id": "acme" }
DELETE/v1/company-memberships

Remove Company Membership

Removes a user from a company. The user account and company are not deleted — only the membership link between them is removed.

Query parameters

ParameterTypeDescription
userIdreqstringThe user's external ID.
companyIdreqstringThe company's external ID.
curl -X DELETE \
  "https://api.guidez.io/v1/company-memberships?userId=user_123&companyId=acme" \
  -H "Authorization: Bearer env_live_sk_xxx" \
  -H "x-environment-id: cm9cs634h..."
await fetch(
  'https://api.guidez.io/v1/company-memberships?userId=user_123&companyId=acme',
  { method: 'DELETE', headers }
);
requests.delete(
    "https://api.guidez.io/v1/company-memberships",
    params={"userId": "user_123", "companyId": "acme"},
    headers=headers
)

Response

200 Deleted
{ "deleted": true }
GET/v1/content

List Content

Returns all content in the environment. Content includes product tours, checklists, banners, and NPS surveys. Filter by type to narrow results.

Query parameters

ParameterTypeDescription
limitoptintegerItems per page. Default: 20. Max: 100.
cursoroptstringPagination cursor.
typeoptstringFilter by content type: tour, checklist, banner, survey.
orderByoptstringcreatedAt or -createdAt.
expandoptstring[]editedVersion, publishedVersion.
curl "https://api.guidez.io/v1/content?type=tour&expand=publishedVersion" \
  -H "Authorization: Bearer env_live_sk_xxx" \
  -H "x-environment-id: cm9cs634h..."
const { results } = await fetch(
  'https://api.guidez.io/v1/content?type=tour&expand=publishedVersion',
  { headers }
).then(r => r.json());
resp = requests.get(
    "https://api.guidez.io/v1/content",
    params={"type": "tour", "expand": "publishedVersion"},
    headers=headers
).json()

Response

200 Success
{
  "results": [
    {
      "id": "cnt_abc123",
      "name": "Onboarding Tour",
      "type": "tour",
      "publishedVersionId": "ver_xyz789",
      "createdAt": "2026-01-15T09:00:00Z"
    }
  ],
  "next": null,
  "previous": null
}
GET/v1/content/:id

Get Content

Retrieve a single piece of content by its ID. Use expand to include the published or edited version with step data.

Path parameters

ParameterTypeDescription
idreqstringContent ID (e.g., cnt_abc123).

Query parameters

ParameterTypeDescription
expandoptstring[]editedVersion, publishedVersion.
curl "https://api.guidez.io/v1/content/cnt_abc123?expand=publishedVersion" \
  -H "Authorization: Bearer env_live_sk_xxx" \
  -H "x-environment-id: cm9cs634h..."
const content = await fetch(
  'https://api.guidez.io/v1/content/cnt_abc123?expand=publishedVersion',
  { headers }
).then(r => r.json());
content = requests.get(
    "https://api.guidez.io/v1/content/cnt_abc123",
    params={"expand": "publishedVersion"},
    headers=headers
).json()
GET/v1/content-versions

List Content Versions

Returns all versions across all content in the environment. A version is a snapshot of a piece of content — including its steps, targeting rules, and theme. Content can have a published version (live) and an edited draft.

Query parameters

ParameterTypeDescription
contentIdoptstringFilter versions by content ID.
limitoptintegerItems per page. Default: 20.
cursoroptstringPagination cursor.
expandoptstring[]questions — include survey question definitions.
curl "https://api.guidez.io/v1/content-versions?contentId=cnt_abc123" \
  -H "Authorization: Bearer env_live_sk_xxx" \
  -H "x-environment-id: cm9cs634h..."
const { results } = await fetch(
  'https://api.guidez.io/v1/content-versions?contentId=cnt_abc123',
  { headers }
).then(r => r.json());
resp = requests.get(
    "https://api.guidez.io/v1/content-versions",
    params={"contentId": "cnt_abc123"},
    headers=headers
).json()

Version object

{
  "id": "ver_xyz789",
  "contentId": "cnt_abc123",
  "status": "published",
  "stepCount": 4,
  "publishedAt": "2026-01-20T10:00:00Z",
  "createdAt": "2026-01-18T08:30:00Z"
}
GET/v1/content-versions/:id

Get Content Version

Retrieve a specific version by its ID. Versions contain the full step list, targeting rules, and theme configuration.

Path parameters

ParameterTypeDescription
idreqstringVersion ID (e.g., ver_xyz789).

Query parameters

ParameterTypeDescription
expandoptstring[]questions — include survey/NPS question definitions with their options.
curl "https://api.guidez.io/v1/content-versions/ver_xyz789" \
  -H "Authorization: Bearer env_live_sk_xxx" \
  -H "x-environment-id: cm9cs634h..."
const version = await fetch(
  'https://api.guidez.io/v1/content-versions/ver_xyz789',
  { headers }
).then(r => r.json());
version = requests.get(
    "https://api.guidez.io/v1/content-versions/ver_xyz789",
    headers=headers
).json()
GET/v1/content-sessions

List Content Sessions

Returns a list of sessions. A session is created each time a user starts interacting with content. Use this to build activation dashboards, churn alerts, or sync completion data to your data warehouse.

Query parameters

ParameterTypeDescription
contentIdreqstringFilter sessions by content ID. Required.
userIdoptstringFilter to sessions for a specific user.
limitoptintegerItems per page. Default: 20. Max: 100.
cursoroptstringPagination cursor.
orderByoptstringcreatedAt or -createdAt.
expandoptstring[]user, company, content, version, answers.
curl "https://api.guidez.io/v1/content-sessions?contentId=cnt_abc123&expand=user" \
  -H "Authorization: Bearer env_live_sk_xxx" \
  -H "x-environment-id: cm9cs634h..."
const { results } = await fetch(
  'https://api.guidez.io/v1/content-sessions?contentId=cnt_abc123&expand=user',
  { headers }
).then(r => r.json());
resp = requests.get(
    "https://api.guidez.io/v1/content-sessions",
    params={
        "contentId": "cnt_abc123",
        "expand": "user"
    },
    headers=headers
).json()

Session object

{
  "id": "cs_abc123",
  "contentId": "cnt_abc123",
  "userId": "user_123",
  "state": "completed",
  "currentStep": 4,
  "totalSteps": 4,
  "startedAt": "2026-05-01T10:00:00Z",
  "completedAt": "2026-05-01T10:04:22Z",
  "user": { "externalId": "user_123", ... }
}
GET/v1/content-sessions/:id

Get Session

Retrieve a single session by ID. Use expand=answers to include the user's survey responses.

Path parameters

ParameterTypeDescription
idreqstringSession ID.

Session states

StateMeaning
startedUser has seen the first step but not yet completed
completedUser completed all steps / submitted survey
dismissedUser dismissed / closed the tour early
expiredSession timed out before completion
curl "https://api.guidez.io/v1/content-sessions/cs_abc123?expand=answers" \
  -H "Authorization: Bearer env_live_sk_xxx" \
  -H "x-environment-id: cm9cs634h..."
const session = await fetch(
  'https://api.guidez.io/v1/content-sessions/cs_abc123?expand=answers',
  { headers }
).then(r => r.json());
session = requests.get(
    "https://api.guidez.io/v1/content-sessions/cs_abc123",
    params={"expand": "answers"},
    headers=headers
).json()
POST/v1/content-sessions/:id/end

End Session

Programmatically end an active session, marking it as completed. Useful when your application knows the user has completed the onboarding objective through another path.

Path parameters

ParameterTypeDescription
idreqstringSession ID to end.
curl -X POST https://api.guidez.io/v1/content-sessions/cs_abc123/end \
  -H "Authorization: Bearer env_live_sk_xxx" \
  -H "x-environment-id: cm9cs634h..."
const updated = await fetch(
  'https://api.guidez.io/v1/content-sessions/cs_abc123/end',
  { method: 'POST', headers }
).then(r => r.json());
resp = requests.post(
    "https://api.guidez.io/v1/content-sessions/cs_abc123/end",
    headers=headers
).json()
DELETE/v1/content-sessions/:id

Delete Session

Permanently delete a session record. Use for GDPR erasure or cleaning test data. The user and content are not affected.

Path parameters

ParameterTypeDescription
idreqstringSession ID to delete.
curl -X DELETE https://api.guidez.io/v1/content-sessions/cs_abc123 \
  -H "Authorization: Bearer env_live_sk_xxx" \
  -H "x-environment-id: cm9cs634h..."
await fetch(
  'https://api.guidez.io/v1/content-sessions/cs_abc123',
  { method: 'DELETE', headers }
);
requests.delete(
    "https://api.guidez.io/v1/content-sessions/cs_abc123",
    headers=headers
)
GET/v1/attribute-definitions

List Attribute Definitions

Returns the schema of custom attributes defined for users and companies. Use this to understand what attributes are available for targeting rules and to validate data before sending.

Query parameters

ParameterTypeDescription
limitoptintegerItems per page. Default: 20. Max: 100.
cursoroptstringPagination cursor.
objectTypeoptstringFilter by object type: user or company.
curl "https://api.guidez.io/v1/attribute-definitions?objectType=user" \
  -H "Authorization: Bearer env_live_sk_xxx" \
  -H "x-environment-id: cm9cs634h..."
const { results } = await fetch(
  'https://api.guidez.io/v1/attribute-definitions?objectType=user',
  { headers }
).then(r => r.json());
resp = requests.get(
    "https://api.guidez.io/v1/attribute-definitions",
    params={"objectType": "user"},
    headers=headers
).json()

Attribute definition object

{
  "id": "attr_plan",
  "name": "plan",
  "displayName": "Subscription Plan",
  "dataType": "string",
  "objectType": "user",
  "isRequired": false
}
GET/v1/event-definitions

List Event Definitions

Returns the schema of custom events that can be tracked on users. Events are used in targeting rules (e.g., "show tour only to users who have NOT completed file_uploaded in the last 7 days").

Query parameters

ParameterTypeDescription
limitoptintegerItems per page. Default: 20.
cursoroptstringPagination cursor.
curl "https://api.guidez.io/v1/event-definitions" \
  -H "Authorization: Bearer env_live_sk_xxx" \
  -H "x-environment-id: cm9cs634h..."
const { results } = await fetch(
  'https://api.guidez.io/v1/event-definitions',
  { headers }
).then(r => r.json());
resp = requests.get(
    "https://api.guidez.io/v1/event-definitions",
    headers=headers
).json()

Event definition object

{
  "id": "evt_file_uploaded",
  "name": "file_uploaded",
  "displayName": "File Uploaded",
  "description": "User uploaded a file to workspace",
  "properties": [
    { "name": "fileType", "dataType": "string" }
  ]
}

Webhooks Overview

Webhooks let Guidez push real-time event notifications to your server when key onboarding events happen — a tour completed, survey submitted, or checklist milestone reached.

How it works

  1. Register an HTTPS endpoint via POST /v1/webhooks
  2. Guidez sends a POST request to your endpoint when events occur
  3. Your server verifies the HMAC-SHA256 signature and responds with 200 OK
  4. If delivery fails, Guidez retries with exponential backoff (up to 5 attempts)

Signature verification

Every webhook request includes a x-guidez-signature header. Verify it to ensure the request came from Guidez and wasn't tampered with.

The signature is HMAC-SHA256(rawBody, signingSecret) encoded as hex.

Always verify signatures. Skipping signature verification opens your endpoint to spoofed requests.

Verify webhook signature

const crypto = require('node:crypto');

function verifySignature(rawBody, sig, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(rawBody)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(sig)
  );
}

// Express example
app.post('/webhook', express.raw({type: '*/*'}), (req, res) => {
  const sig = req.headers['x-guidez-signature'];
  if (!verifySignature(req.body, sig, process.env.WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature');
  }
  const event = JSON.parse(req.body);
  // handle event...
  res.sendStatus(200);
});
import hmac, hashlib, os

def verify_signature(raw_body: bytes, sig: str) -> bool:
    secret = os.environ["WEBHOOK_SECRET"].encode()
    expected = hmac.new(secret, raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, sig)

# Flask example
@app.route("/webhook", methods=["POST"])
def webhook():
    sig = request.headers.get("x-guidez-signature")
    if not verify_signature(request.data, sig):
        return "Invalid", 401
    event = request.json
    # handle event...
    return "", 200
GET/v1/webhooks

List Webhooks

Returns all webhooks registered for the environment. Signing secrets are not included in list responses.

curl "https://api.guidez.io/v1/webhooks" \
  -H "Authorization: Bearer env_live_sk_xxx" \
  -H "x-environment-id: cm9cs634h..."
const { results } = await fetch(
  'https://api.guidez.io/v1/webhooks',
  { headers }
).then(r => r.json());
resp = requests.get(
    "https://api.guidez.io/v1/webhooks",
    headers=headers
).json()

Webhook object

{
  "id": "wh_abc123",
  "url": "https://your-app.com/webhooks/guidez",
  "events": [
    "content.completed",
    "content.dismissed"
  ],
  "enabled": true,
  "createdAt": "2026-01-15T09:00:00Z"
}
POST/v1/webhooks

Create Webhook

Register a new webhook endpoint. The response includes the signing secret — store it securely. It will not be shown again.

Request body

FieldTypeDescription
urlreqstringYour HTTPS endpoint URL. Must be publicly reachable.
eventsreqstring[]Event types to subscribe to. See Event Reference below.
enabledoptbooleanWhether the webhook is active. Default: true.
curl -X POST https://api.guidez.io/v1/webhooks \
  -H "Authorization: Bearer env_live_sk_xxx" \
  -H "x-environment-id: cm9cs634h..." \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-app.com/webhooks/guidez",
    "events": ["content.completed", "content.dismissed", "survey.answered"]
  }'
const webhook = await fetch(
  'https://api.guidez.io/v1/webhooks', {
  method: 'POST',
  headers: { ...headers, 'Content-Type': 'application/json' },
  body: JSON.stringify({
    url: 'https://your-app.com/webhooks/guidez',
    events: ['content.completed', 'survey.answered']
  })
}).then(r => r.json());
resp = requests.post(
    "https://api.guidez.io/v1/webhooks",
    headers={**headers, "Content-Type": "application/json"},
    json={
        "url": "https://your-app.com/webhooks/guidez",
        "events": ["content.completed", "survey.answered"]
    }
).json()

Response (save the secret!)

{
  "id": "wh_abc123",
  "url": "https://your-app.com/webhooks/guidez",
  "events": ["content.completed", "survey.answered"],
  "secret": "whsec_xxxxxxxxxxxxxxxxxxxx",
  "enabled": true,
  "createdAt": "2026-05-08T12:00:00Z"
}
PATCH/v1/webhooks/:id

Update Webhook

Update the URL, event subscriptions, or enabled state of an existing webhook.

Path parameters

ParameterTypeDescription
idreqstringWebhook ID.

Request body

FieldTypeDescription
urloptstringNew HTTPS endpoint URL.
eventsoptstring[]Replaces the current event list.
enabledoptbooleanEnable or disable the webhook.
curl -X PATCH https://api.guidez.io/v1/webhooks/wh_abc123 \
  -H "Authorization: Bearer env_live_sk_xxx" \
  -H "x-environment-id: cm9cs634h..." \
  -H "Content-Type: application/json" \
  -d '{ "enabled": false }'
await fetch('https://api.guidez.io/v1/webhooks/wh_abc123', {
  method: 'PATCH',
  headers: { ...headers, 'Content-Type': 'application/json' },
  body: JSON.stringify({ enabled: false })
});
requests.patch(
    "https://api.guidez.io/v1/webhooks/wh_abc123",
    headers={**headers, "Content-Type": "application/json"},
    json={"enabled": False}
)
DELETE/v1/webhooks/:id

Delete Webhook

Permanently delete a webhook. No further events will be delivered to this endpoint.

curl -X DELETE https://api.guidez.io/v1/webhooks/wh_abc123 \
  -H "Authorization: Bearer env_live_sk_xxx" \
  -H "x-environment-id: cm9cs634h..."
await fetch('https://api.guidez.io/v1/webhooks/wh_abc123', {
  method: 'DELETE', headers
});
requests.delete(
    "https://api.guidez.io/v1/webhooks/wh_abc123",
    headers=headers
)
POST/v1/webhooks/:id/regenerate-secret

Regenerate Signing Secret

Generates a new signing secret for the webhook. The old secret is immediately invalidated. Update your environment variable before calling this to avoid a gap in verification.

Zero-downtime rotation: Deploy your new secret to your server first, then regenerate. Old and new secrets are accepted for 10 minutes during the transition.
curl -X POST \
  https://api.guidez.io/v1/webhooks/wh_abc123/regenerate-secret \
  -H "Authorization: Bearer env_live_sk_xxx" \
  -H "x-environment-id: cm9cs634h..."
const { secret } = await fetch(
  'https://api.guidez.io/v1/webhooks/wh_abc123/regenerate-secret',
  { method: 'POST', headers }
).then(r => r.json());
resp = requests.post(
    "https://api.guidez.io/v1/webhooks/wh_abc123/regenerate-secret",
    headers=headers
).json()
new_secret = resp["secret"]
GET/v1/webhooks/:id/deliveries

Delivery Logs

Returns the delivery attempt history for a webhook. Each delivery record shows the event payload, response status, duration, and any error message on failure.

Retry behavior

Failed deliveries are retried up to 5 times with exponential backoff: 30s, 5m, 30m, 2h, 8h. If all retries fail the delivery is marked failed.

curl "https://api.guidez.io/v1/webhooks/wh_abc123/deliveries" \
  -H "Authorization: Bearer env_live_sk_xxx" \
  -H "x-environment-id: cm9cs634h..."
const { results } = await fetch(
  'https://api.guidez.io/v1/webhooks/wh_abc123/deliveries',
  { headers }
).then(r => r.json());
resp = requests.get(
    "https://api.guidez.io/v1/webhooks/wh_abc123/deliveries",
    headers=headers
).json()

Delivery record

{
  "id": "del_abc123",
  "webhookId": "wh_abc123",
  "eventType": "content.completed",
  "status": "delivered",
  "httpStatus": 200,
  "durationMs": 142,
  "attempt": 1,
  "createdAt": "2026-05-08T12:05:00Z"
}

Event Reference

All available webhook event types. Use * as a wildcard to subscribe to all events in a category.

Content events

content.started content.completed content.dismissed content.step_completed content.*

Survey events

survey.answered survey.submitted survey.*

Checklist events

checklist.item_completed checklist.completed checklist.*

User events

user.identified user.deleted user.*

Wildcard

* — Subscribe to all event types

Event payload structure

{
  "id": "evt_abc123",
  "type": "content.completed",
  "createdAt": "2026-05-08T12:05:00Z",
  "data": {
    "sessionId": "cs_abc123",
    "contentId": "cnt_abc123",
    "contentName": "Onboarding Tour",
    "userId": "user_123",
    "userAttributes": {
      "name": "Jane Smith",
      "plan": "pro"
    },
    "completedAt": "2026-05-08T12:05:00Z",
    "durationMs": 262000
  },
  "environmentId": "cm9cs634h..."
}

Analytics Overview

Guidez tracks detailed analytics for all content. The Analytics API lets you pull completion rates, step-level funnels, time-to-complete, and user-level session data into your own BI tools or dashboards.

What's available

  • Content-level: Views, completions, dismissals, completion rate, avg. time to complete
  • Step-level: Per-step progression funnel and drop-off rates
  • Session-level: Individual user sessions via /v1/content-sessions
  • Survey responses: NPS scores and open-text answers via expand=answers
Tip: For deep analytics, combine the Sessions API with your data warehouse. Export completed sessions nightly to Snowflake, BigQuery, or Redshift for cohort and funnel analysis.

Activation pipeline example

// Pull sessions completed yesterday
const yesterday = new Date();
yesterday.setDate(yesterday.getDate() - 1);

const sessions = [];
for await (const s of paginate(
  `/v1/content-sessions?contentId=${TOUR_ID}&expand=user`,
  headers
)) {
  if (s.state === 'completed') sessions.push(s);
}

// completion rate
const rate = sessions.length / total * 100;
console.log(`Completion rate: ${rate.toFixed(1)}%`);

Content Analytics

Aggregate analytics for a specific piece of content over a date range. Returns views, completions, step-level funnel, completion rate, and average duration.

Content analytics are available via the Guidez Dashboard (real-time) and can be exported via the Sessions API for custom processing. A dedicated Analytics REST endpoint is on the roadmap — subscribe to the changelog below.

Getting analytics programmatically

Use GET /v1/content-sessions with your content ID to pull all sessions, then compute aggregates server-side:

  • Completion rate: sessions where state === 'completed' / total sessions
  • Avg. duration: mean of completedAt - startedAt in ms
  • Drop-off step: highest currentStep value in dismissed sessions
  • NPS score: sessions with expand=answers — parse the numeric answer

Compute completion rate

const all = [], completed = [];

for await (const s of
  paginate(`/v1/content-sessions?contentId=${ID}`, headers)
) {
  all.push(s);
  if (s.state === 'completed') completed.push(s);
}

const completionRate = (completed.length / all.length * 100).toFixed(1);
const avgMs = completed.reduce((sum, s) => {
  return sum + (new Date(s.completedAt) - new Date(s.startedAt));
}, 0) / completed.length;

console.log({ completionRate, avgMs });
GET/v1/themes

List Themes

Returns all themes for the project. Themes control the visual appearance (colors, fonts, border radius, shadows) of tours, checklists, and banners.

Query parameters

ParameterTypeDescription
projectIdreqstringYour project ID.
curl "https://api.guidez.io/v1/themes?projectId=proj_abc" \
  -H "Authorization: Bearer env_live_sk_xxx" \
  -H "x-environment-id: cm9cs634h..."
const themes = await fetch(
  'https://api.guidez.io/v1/themes?projectId=proj_abc',
  { headers }
).then(r => r.json());
themes = requests.get(
    "https://api.guidez.io/v1/themes",
    params={"projectId": "proj_abc"},
    headers=headers
).json()

Theme object

{
  "id": "thm_abc123",
  "name": "Brand Theme",
  "isDefault": true,
  "settings": {
    "primaryColor": "#7c3aed",
    "fontFamily": "Inter",
    "borderRadius": 8
  }
}
POST/v1/themes

Create Theme

Create a new theme for your project. Themes can be applied to individual content items or set as the project default.

Request body

FieldTypeDescription
namereqstringHuman-readable theme name.
projectIdreqstringProject ID to assign theme to.
settingsoptobjectTheme configuration (colors, fonts, spacing).
curl -X POST https://api.guidez.io/v1/themes \
  -H "Authorization: Bearer env_live_sk_xxx" \
  -H "x-environment-id: cm9cs634h..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Dark Mode Theme",
    "projectId": "proj_abc",
    "settings": {
      "primaryColor": "#a78bfa",
      "backgroundColor": "#1a1a2e"
    }
  }'
const theme = await fetch(
  'https://api.guidez.io/v1/themes', {
  method: 'POST',
  headers: { ...headers, 'Content-Type': 'application/json' },
  body: JSON.stringify({
    name: 'Dark Mode Theme',
    projectId: 'proj_abc',
    settings: { primaryColor: '#a78bfa' }
  })
}).then(r => r.json());
theme = requests.post(
    "https://api.guidez.io/v1/themes",
    headers={**headers, "Content-Type": "application/json"},
    json={
        "name": "Dark Mode Theme",
        "projectId": "proj_abc",
    }
).json()
PATCH/v1/themes/:id

Update Theme

Update a theme's name or settings. Changes take effect immediately for all content using this theme.

Path parameters

ParameterTypeDescription
idreqstringTheme ID.
curl -X PATCH https://api.guidez.io/v1/themes/thm_abc123 \
  -H "Authorization: Bearer env_live_sk_xxx" \
  -H "x-environment-id: cm9cs634h..." \
  -H "Content-Type: application/json" \
  -d '{ "settings": { "primaryColor": "#6d28d9" } }'
await fetch('https://api.guidez.io/v1/themes/thm_abc123', {
  method: 'PATCH',
  headers: { ...headers, 'Content-Type': 'application/json' },
  body: JSON.stringify({ settings: { primaryColor: '#6d28d9' } })
});
requests.patch(
    "https://api.guidez.io/v1/themes/thm_abc123",
    headers={**headers, "Content-Type": "application/json"},
    json={"settings": {"primaryColor": "#6d28d9"}}
)
DELETE/v1/themes/:id

Delete Theme

Delete a theme. Content using this theme will fall back to the project default theme.

curl -X DELETE https://api.guidez.io/v1/themes/thm_abc123 \
  -H "Authorization: Bearer env_live_sk_xxx" \
  -H "x-environment-id: cm9cs634h..."
await fetch('https://api.guidez.io/v1/themes/thm_abc123', {
  method: 'DELETE', headers
});
requests.delete(
    "https://api.guidez.io/v1/themes/thm_abc123",
    headers=headers
)

Install & Initialize

The Guidez JavaScript SDK runs in your users' browsers. It handles user identification, tour rendering, targeting evaluation, and event tracking.

Install via npm

npm install @guidez/sdk

Or via script tag (CDN)

<script src="https://cdn.guidez.io/sdk/v1/guidez.min.js" data-token="YOUR_TOKEN" async></script>

Initialize

Call Guidez.init() once at app startup with your environment token (publishable key — safe for browsers).

Framework notes

  • React: Call in useEffect with empty deps or in your root layout
  • Next.js: In _app.tsx inside a useEffect
  • Vue: In mounted() or a plugin
  • SPA: Call Guidez.identify() after auth state resolves

Initialization

import Guidez from '@guidez/sdk';

Guidez.init({
  token: 'YOUR_ENVIRONMENT_TOKEN',
});
import { useEffect } from 'react';
import Guidez from '@guidez/sdk';

export function App() {
  useEffect(() => {
    Guidez.init({ token: 'YOUR_TOKEN' });
  }, []);
  return <YourApp />;
}
// app/layout.tsx
'use client';
import { useEffect } from 'react';
import Guidez from '@guidez/sdk';

export default function RootLayout({ children }) {
  useEffect(() => {
    Guidez.init({ token: process.env.NEXT_PUBLIC_GUIDEZ_TOKEN });
  }, []);
  return <html><body>{children}</body></html>;
}

guidez.identify()

Tell Guidez who the current user is. Call this after the user signs in. Triggers targeting evaluation — if any published tours match this user, they'll start showing.

Parameters

ParameterTypeDescription
userIdreqstringStable unique ID from your database. Must match the id used in server-side API calls.
attributesoptobjectUser properties for targeting (name, email, plan, etc.).
companyoptobject{ id, attributes } — associates user with a company.
Call on every page load after auth resolves, not just on sign-in. This keeps attributes fresh and ensures targeting is re-evaluated.
await Guidez.identify('user_123', {
  name: 'Jane Smith',
  email: 'jane@acme.com',
  plan: 'pro',
  signedUpAt: '2026-01-10',
  company: {
    id: 'acme',
    attributes: { name: 'Acme Inc.', plan: 'enterprise' }
  }
});
import { useEffect } from 'react';
import Guidez from '@guidez/sdk';
import { useAuth } from './auth';

export function useGuidez() {
  const { user } = useAuth();
  useEffect(() => {
    if (!user) return;
    Guidez.identify(user.id, {
      name: user.name,
      email: user.email,
      plan: user.plan,
    });
  }, [user]);
}

guidez.show()

Programmatically show a specific tour, checklist, or banner by content ID. Bypasses targeting rules — useful for "Show me again" buttons or debug flows.

Parameters

ParameterTypeDescription
contentIdreqstringThe content ID to show (e.g., cnt_abc123).
optionsoptobject{ force: boolean } — if true, shows even if already completed.
// Show a specific tour
await Guidez.show('cnt_abc123');

// Force-show even if user already completed it
await Guidez.show('cnt_abc123', { force: true });

// "Show me again" button
button.addEventListener('click', () =>
  Guidez.show('cnt_abc123', { force: true })
);

guidez.track()

Track a custom event for the current user. Events can be used in targeting rules — e.g., only show a tour to users who have NOT fired file_uploaded yet.

Parameters

ParameterTypeDescription
eventNamereqstringThe event name. Use snake_case by convention.
propertiesoptobjectOptional key-value properties attached to the event.
// Simple event
Guidez.track('file_uploaded');

// Event with properties
Guidez.track('payment_completed', {
  plan: 'pro',
  amount: 99,
  currency: 'usd',
});

// Track after user action
async function onInviteSent(email) {
  await sendInvite(email);
  Guidez.track('invite_sent', { recipientEmail: email });
}

guidez.on()

Subscribe to Guidez SDK events. Use this to react to tour lifecycle events in your application — for example, unlock a feature when a tour is completed, or fire an analytics event.

Available events

EventFired when
content.startedUser sees the first step of a tour/checklist
content.completedUser completes all steps
content.dismissedUser closes/skips the tour
content.step_completedUser advances past a step
survey.answeredUser submits a survey or NPS response
// Listen for tour completion
Guidez.on('content.completed', (event) => {
  console.log('Tour completed:', event.contentId);
  // Unlock a feature
  enableFeature('advanced-settings');
  // Fire your analytics
  analytics.track('Onboarding Completed', {
    tourId: event.contentId,
    userId: event.userId,
  });
});

// Listen for NPS submission
Guidez.on('survey.answered', (event) => {
  if (event.score < 7) {
    openChurnSaveModal();
  }
});

guidez.off()

Remove an event listener previously registered with guidez.on(). Call this in cleanup functions to prevent memory leaks.

const handler = (event) => {
  console.log('completed', event);
};

Guidez.on('content.completed', handler);

// Later, remove listener
Guidez.off('content.completed', handler);

// React cleanup pattern
useEffect(() => {
  const h = (e) => analytics.track('Tour Done', e);
  Guidez.on('content.completed', h);
  return () => Guidez.off('content.completed', h);
}, []);

guidez.reset()

Clears all identity data and session state from the browser. Always call this on sign-out to prevent the next user on a shared device from seeing tours targeted at the previous user.

Call on sign-out. Missing this causes tours to appear incorrectly for new sessions or shared devices.
async function signOut() {
  await auth.signOut();
  Guidez.reset(); // clear Guidez session
  router.push('/login');
}

// Or with async reset
async function signOut() {
  await Promise.all([
    auth.signOut(),
    Guidez.reset(),
  ]);
  router.push('/login');
}

guidez.getUser()

Returns the currently identified user object from the local SDK state. Useful to check if a user is identified before showing UI elements, or to read back attributes you've set.

Returns

A User object with id, attributes, and company, or null if no user is identified.

const user = Guidez.getUser();

if (!user) {
  console.log('No user identified');
} else {
  console.log('Current user:', user.id);
  console.log('Plan:', user.attributes.plan);
}

// Type-safe (TypeScript)
type GuidezUser = {
  id: string;
  attributes: Record<string, unknown>;
  company?: { id: string; attributes: Record<string, unknown> };
};

guidez.update()

Update attributes of the currently identified user without re-identifying. Use this when user properties change mid-session (e.g., they upgrade their plan). Attributes are merged, not replaced.

Parameters

ParameterTypeDescription
attributesreqobjectAttributes to merge into the current user.
// User upgrades mid-session
async function onUpgrade(newPlan) {
  await upgradePlan(newPlan);
  await Guidez.update({
    plan: newPlan,
    upgradedAt: new Date().toISOString(),
  });
  // Guidez re-evaluates targeting with new plan
}

Guidez CLI

The Guidez CLI (@guidez/cli) lets you manage users, companies, content, sessions, and webhooks directly from your terminal. Ideal for scripts, CI/CD pipelines, and quick data lookups.

Install

npm install -g @guidez/cli

Or use without installing:

npx @guidez/cli <command>

Commands

CommandDescription
guidez loginAuthenticate and save API key to ~/.guidez/config.json
guidez usersList, get, identify, and delete users
guidez companiesList, get, upsert, and delete companies
guidez contentList and get content
guidez sessionsList, get, end, and delete sessions
guidez webhooksList, create, and delete webhooks
guidez export analyticsExport session analytics to JSON or CSV

Global flags

FlagDescription
--jsonOutput raw JSON (great for piping to jq)
--env <id>Override saved environment ID
--helpShow help for any command
Terminal
$ guidez --help
Guidez CLI v1.0.0
Commands:
login Authenticate with Guidez
logout Remove saved credentials
whoami Show current credentials
users Manage users
companies Manage companies
content Browse content
sessions Manage content sessions
webhooks Manage webhooks
export Export analytics data
Flags:
--json Output raw JSON
--env <id> Override environment ID

login / logout / whoami

Authenticate the CLI by saving your API key and environment ID to ~/.guidez/config.json. Your credentials are stored locally and never sent to Guidez servers directly.

Login flags

FlagDescription
--api-keyYour Guidez API secret key
--base-urlAPI base URL (default: https://api.guidez.io)
--envDefault environment ID
Terminal
$ guidez login --api-key env_live_sk_xxx --env cm9cs634h...
✓ Logged in successfully
$ guidez whoami
API Key: env_live_sk_xxx... (last 4: _xxx)
Environment: cm9cs634h00001mp50l45n7kz
Base URL: https://api.guidez.io
$ guidez logout
✓ Logged out

guidez users

Manage users from the terminal. Great for customer support lookups, data scripts, and GDPR deletion workflows.

SubcommandDescription
users listList all users with table output
users get <id>Get a user by external ID
users identifyCreate or update a user
users delete <id>Permanently delete a user
Terminal
$ guidez users list --limit 5
ID NAME EMAIL CREATED
user_123 Jane Smith jane@acme.com 2026-01-15
user_456 Bob Jones bob@stripe.com 2026-01-16
$ guidez users get user_123 --json | jq .attributes
{ "name": "Jane Smith", "plan": "pro" }
$ guidez users identify --id user_789 --name "New User" --email new@co.com
✓ User user_789 identified
$ guidez users delete user_789
✓ User user_789 deleted

guidez companies

Manage company accounts from the terminal. Sync CRM data, look up accounts, or clean up test data.

SubcommandDescription
companies listList all companies
companies get <id>Get a company by external ID
companies upsert --id <id> --name <name>Create or update a company
companies delete <id>Delete a company
Terminal
$ guidez companies list
ID NAME CREATED
acme Acme Inc. 2026-01-01
stripe Stripe, Inc. 2026-01-02
$ guidez companies upsert --id newco --name "New Co Ltd"
✓ Company newco upserted

guidez content

Browse and inspect content. Useful for finding content IDs to use in scripts, or auditing what's published.

SubcommandDescription
content list [--type <type>]List all content, optionally filtered by type
content get <id>Get a single piece of content by ID
Terminal
$ guidez content list --type tour
ID NAME TYPE STATUS
cnt_abc123 Onboarding Tour tour published
cnt_def456 Feature Spotlight tour draft
$ guidez content get cnt_abc123 --json | jq .name
"Onboarding Tour"

guidez sessions

Inspect and manage content sessions. Look up a specific user's completion status or bulk-clean test sessions.

SubcommandDescription
sessions list --content <id>List sessions for a content item
sessions get <id>Get a single session by ID
sessions end <id>Mark a session as completed
sessions delete <id>Delete a session record
Terminal
$ guidez sessions list --content cnt_abc123 --user user_123
ID STATE STEP STARTED
cs_abc123 completed 4/4 2026-05-01
$ guidez sessions end cs_xyz789
✓ Session cs_xyz789 ended

guidez webhooks

Manage webhook endpoints. Create, list, or delete webhooks from CI/CD or setup scripts.

SubcommandDescription
webhooks listList all webhooks
webhooks create --url <url> --events <ev>Create a new webhook
webhooks delete <id>Delete a webhook
Terminal
$ guidez webhooks create \
--url https://app.com/webhooks/guidez \
--events content.completed,survey.answered
✓ Webhook wh_abc123 created
Secret: whsec_xxxxxxxxxxxx (save this!)
$ guidez webhooks list
ID URL ENABLED
wh_abc123 https://app.com/webhooks/g true

guidez export analytics

Export session data for a content item to JSON or CSV. Iterates all pages automatically and writes to stdout or a file.

Flags

FlagDescription
--content <id>Content ID to export sessions for
--start <date>Start date filter (YYYY-MM-DD)
--end <date>End date filter (YYYY-MM-DD)
--format json|csvOutput format. Default: json
--output <file>Write to file instead of stdout
Terminal
$ guidez export analytics \
--content cnt_abc123 \
--format csv \
--output sessions.csv
Fetching sessions for cnt_abc123...
Page 1: 100 sessions
Page 2: 100 sessions
Page 3: 47 sessions
✓ Exported 247 sessions to sessions.csv
$ guidez export analytics --content cnt_abc123 --json | \
jq '[.[] | select(.state=="completed")] | length'
189

Guidez MCP Server

The Model Context Protocol (MCP) server exposes all Guidez API capabilities as tools that AI assistants — Claude, Cursor, Windsurf, and any MCP-compatible client — can call natively.

This means you can ask your AI assistant:

  • "Show me all users who haven't completed the onboarding tour"
  • "Which companies have the most sessions this week?"
  • "Identify user_789 with name 'Alice' and plan 'pro'"
  • "Create a webhook for content.completed events pointing to https://my-app.com/hooks"

Your AI assistant calls Guidez directly — no copy-pasting IDs, no manual API calls.

Tools included

list_usersUsers

List all users in the environment

identify_userUsers

Create or update a user with attributes

get_userUsers

Get a user by external ID

delete_userUsers

Permanently delete a user

list_companiesCompanies

List all companies

upsert_companyCompanies

Create or update a company

remove_company_membershipCompanies

Remove a user from a company

list_contentContent

List all tours, checklists, and banners

list_sessionsSessions

List content sessions for a content item

end_sessionSessions

Mark an active session as completed

list_webhooksWebhooks

List all registered webhook endpoints

create_webhookWebhooks

Register a new webhook endpoint

Claude Desktop demo

// You ask Claude:
"Who are our 5 newest users?"

// Claude calls:
list_users({ limit: 5 })

// Returns:
[
  { id: "user_789", name: "Alice Wang", ... },
  { id: "user_456", name: "Bob Kim", ... },
  ...
]

// Claude responds:
"Your 5 newest users are:
1. Alice Wang (user_789) — signed up 2 hours ago
2. Bob Kim (user_456) — signed up yesterday
..."

Setup & Configuration

The MCP server communicates over stdio — the standard MCP transport. Configure it in your AI assistant's settings once, and it's available in every conversation.

Install

npm install -g @guidez/mcp

Required environment variables

VariableDescription
GUIDEZ_API_KEYYour API secret key (env_live_sk_xxx)
GUIDEZ_ENV_IDYour environment ID
GUIDEZ_BASE_URLOptional. Default: https://api.guidez.io

Add to Claude Desktop

Edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows).

Claude Desktop config

{
  "mcpServers": {
    "guidez": {
      "command": "npx",
      "args": ["@guidez/mcp"],
      "env": {
        "GUIDEZ_API_KEY": "env_live_sk_xxx",
        "GUIDEZ_ENV_ID": "cm9cs634h00001mp50l45n7kz"
      }
    }
  }
}

Cursor / Windsurf (.cursor/mcp.json)

{
  "mcpServers": {
    "guidez": {
      "command": "node",
      "args": ["/path/to/node_modules/@guidez/mcp/index.js"],
      "env": {
        "GUIDEZ_API_KEY": "env_live_sk_xxx",
        "GUIDEZ_ENV_ID": "cm9cs634h..."
      }
    }
  }
}

Test the connection

# Start the server manually to test
GUIDEZ_API_KEY=env_live_sk_xxx \
GUIDEZ_ENV_ID=cm9cs634h... \
node $(npm root -g)/@guidez/mcp/index.js

User Tools

Four tools cover the full user lifecycle — list, get, identify/upsert, and delete.

list_users

List users. Optional: limit (int), cursor (string).

get_user

Required: id (string). Returns full user object with attributes.

identify_user

Required: id. Optional: name, email, company_id, attributes (object).

delete_user

Required: id. Permanently deletes user and all session data.

Example tool call

// MCP tool call (JSON)
{
  "name": "identify_user",
  "arguments": {
    "id": "user_123",
    "name": "Alice Wang",
    "email": "alice@example.com",
    "attributes": {
      "plan": "pro",
      "signedUpAt": "2026-05-08"
    }
  }
}

// Response
{
  "id": "usr_abc123",
  "externalId": "user_123",
  "attributes": { "name": "Alice Wang", ... },
  "createdAt": "2026-05-08T12:00:00Z"
}

Company Tools

list_companies

List companies. Optional: limit, cursor.

get_company

Required: id. Returns company with attributes.

upsert_company

Required: id, name. Optional: attributes (object).

delete_company

Required: id. Deletes company and all membership links.

remove_company_membership

Required: user_id, company_id. Removes user from company.

Natural language → tool call

// You say to Claude:
"Add Acme Inc. as a company with 500 employees in the tech industry"

// Claude calls:
upsert_company({
  id: "acme",
  name: "Acme Inc.",
  attributes: {
    employees: 500,
    industry: "Technology"
  }
})

Content Tools

list_content

List all content. Optional: type (tour/checklist/banner), limit.

get_content

Required: id. Returns content with metadata.

list_content_versions

Optional: content_id. Lists all versions.

get_content_version

Required: id. Returns a version with step data.

Content audit via Claude

// You ask:
"How many tours do we have published?"

// Claude calls:
list_content({ type: "tour", limit: 100 })

// Claude responds:
"You have 12 tours in total.
8 are published, 4 are drafts.
Your most recent is 'Feature Spotlight'
published 2 days ago."

Session Tools

list_sessions

Required: content_id. Optional: user_id, limit.

get_session

Required: id. Returns session with state, steps, and timestamps.

end_session

Required: id. Marks session as completed.

delete_session

Required: id. Permanently removes session record.

Power example

Ask Claude: "Show me which users started the onboarding tour but didn't complete it in the last 7 days"

Claude will call list_sessions, filter for state === 'started', and return the user IDs — which you can then target with a follow-up email.

Churn prevention workflow

// You ask Claude:
"Which users started but didn't complete
the onboarding tour?"

// Claude calls:
list_sessions({
  content_id: "cnt_onboarding",
  limit: 100
})

// Claude filters, then calls for each:
get_user({ id: session.userId })

// Claude responds:
"14 users started but didn't finish:
- user_789 (alice@co.com) — started 3 days ago, step 2/5
- user_456 (bob@co.com) — started 5 days ago, step 1/5
..."

Definition & Webhook Tools

list_attribute_definitions

No required args. Returns all custom attribute schemas for users and companies.

list_event_definitions

No required args. Returns all trackable event types with their property schemas.

list_webhooks

No required args. Returns all registered webhooks.

create_webhook

Required: url (string), events (string[]). Creates webhook and returns signing secret.

delete_webhook

Required: id. Permanently removes webhook.

Setup webhook via Claude

// You say:
"Create a webhook for tour completions
pointing to https://my-crm.com/guidez-hook"

// Claude calls:
create_webhook({
  url: "https://my-crm.com/guidez-hook",
  events: ["content.completed"]
})

// Claude responds:
"Done! Webhook wh_abc123 created.
Your signing secret is: whsec_xxxx
(store this in your environment variables)"

What's New

Stay up to date with API changes. We version the API and maintain backwards compatibility. Breaking changes get a new version prefix.

May 2026
CLI, MCP Server, and complete API coverage
  • Launched @guidez/cli — full terminal interface for all API operations
  • Launched @guidez/mcp — Model Context Protocol server for Claude, Cursor, Windsurf
  • Added REST documentation for Companies, Company Memberships, Content Versions, Content Sessions, Attribute Definitions, and Event Definitions
  • Added Quickstart guide, Core Concepts, and Environments sections
  • Added SDK methods: on(), off(), getUser(), update()
  • Added Webhook Delivery Logs endpoint
  • Added Webhook Update + Regenerate Secret endpoints
April 2026
A/B Experiments and Webhooks beta
  • A/B experiment content delivery now live — users see consistent variant across sessions
  • Webhook system launched with HMAC-SHA256 signing and exponential retry
  • Content Sessions API launched — programmatically track and export session data
  • SDK: track() now supports arbitrary event properties
March 2026
Companies API and User expand
  • Companies API launched: full CRUD for company accounts and memberships
  • User list and get endpoints now support expand=memberships.company
  • SDK identify() now accepts company parameter for direct association
  • Attribute Definitions and Event Definitions endpoints launched
January 2026
v1 API launch
  • REST API v1 launched with Users, Content, and Themes endpoints
  • JavaScript SDK @guidez/sdk published to npm
  • Rate limiting enabled (plan-based limits)
  • Cursor-based pagination across all list endpoints

API versioning

# Current stable version
GET https://api.guidez.io/v1/users

# We maintain backwards compatibility
# Breaking changes get a new version:
# v2 (future)
GET https://api.guidez.io/v2/users

Get notified

# Subscribe to API changelog:
# https://guidez.io/changelog

# Status page:
# https://status.guidez.io

# Developer community:
# https://community.guidez.io