Core Workflows
These workflows are the building blocks most applications need after receiving an organization API token.
Default API base URL:
https://cloud.schedule-x.comThe SDK uses this URL automatically. Pass baseUrl only if you need to target another deployment.
Required backend environment:
SCHEDULE_X_ORGANIZATION_ID=<organization-id>SCHEDULE_X_ORG_API_TOKEN=sx_org_...Authenticate Backend Requests
Section titled “Authenticate Backend Requests”Server-to-server organization routes accept the organization API token as the SDK apiKey, which sends the X-ScheduleX-Api-Key header.
import { ScheduleXServerClient } from '@schedule-x-cloud/sdk/server'
const serverClient = new ScheduleXServerClient({ apiKey: process.env.SCHEDULE_X_ORG_API_TOKEN!,})Equivalent HTTP:
GET /v1/orgs/{organizationId}/calendarsX-ScheduleX-Api-Key: sx_org_...Bootstrap A Frontend Session
Section titled “Bootstrap A Frontend Session”The normal integration maps your authenticated app user and issues its frontend token in one call:
const serverClient = new ScheduleXServerClient({ apiKey: process.env.SCHEDULE_X_ORG_API_TOKEN!, organizationId: process.env.SCHEDULE_X_ORGANIZATION_ID!,})
const frontendSession = await serverClient.auth.createFrontendSession({ externalUserId: appUser.id, email: appUser.email, displayName: appUser.name,})Equivalent HTTP:
POST /v1/orgs/{organizationId}/auth/frontend-sessionX-ScheduleX-Api-Key: sx_org_...Content-Type: application/json
{ "externalUserId": "app-user-123", "email": "ada@example.com", "displayName": "Ada Lovelace"}The first call creates a Member. Later calls update profile fields, preserve the role, and issue a fresh one-hour token.
Manage Users And Tokens Separately
Section titled “Manage Users And Tokens Separately”Advanced integrations may create a Cloud user, store its ID, and issue tokens separately.
const cloudUser = await serverClient.users.create( process.env.SCHEDULE_X_ORGANIZATION_ID!, { email: 'ada@example.com', displayName: 'Ada Lovelace', role: 'Member', })Equivalent HTTP:
POST /v1/orgs/{organizationId}/usersX-ScheduleX-Api-Key: sx_org_...Content-Type: application/json
{ "email": "ada@example.com", "displayName": "Ada Lovelace", "role": "Member"}Cloud user authentication happens by issuing a frontend token for that userId after the user has authenticated with your application:
const frontendToken = await serverClient.auth.createFrontendToken({ organizationApiToken: process.env.SCHEDULE_X_ORG_API_TOKEN!, organizationId: process.env.SCHEDULE_X_ORGANIZATION_ID!, userId: cloudUser.id,})Equivalent HTTP:
POST /v1/orgs/{organizationId}/auth/frontend-tokenX-ScheduleX-Org-Token: sx_org_...Content-Type: application/json
{ "userId": "..."}Send the returned token, expiresAt, organizationId, and userId to the browser. Do not send the organization API token.
Create Calendars
Section titled “Create Calendars”Calendars belong to an organization. Events can reference a calendar by its id or slug.
const workCalendar = await serverClient.calendars.create( process.env.SCHEDULE_X_ORGANIZATION_ID!, { name: 'Work', slug: 'work', colorName: 'work', lightMainColor: '#2563eb', lightContainerColor: '#dbeafe', lightOnContainerColor: '#172554', })Equivalent HTTP:
POST /v1/orgs/{organizationId}/calendarsX-ScheduleX-Api-Key: sx_org_...Content-Type: application/json
{ "name": "Work", "slug": "work", "colorName": "work", "lightMainColor": "#2563eb", "lightContainerColor": "#dbeafe", "lightOnContainerColor": "#172554"}Required fields are name, slug, and colorName. Color values are optional but recommended so Schedule-X can render the calendar immediately.
Load Calendars
Section titled “Load Calendars”Backend code can list calendars with the organization token:
const calendars = await serverClient.calendars.list( process.env.SCHEDULE_X_ORGANIZATION_ID!)Browser code should usually load the Schedule-X-ready config instead:
import 'temporal-polyfill/global'import { ScheduleXBrowserClient } from '@schedule-x-cloud/sdk'
const browserClient = new ScheduleXBrowserClient({ token: frontendToken.token,})
const config = await browserClient.scheduleX.getCalendarAppConfig()To load a bounded event window:
const config = await browserClient.scheduleX.getCalendarAppConfig({ from: Temporal.ZonedDateTime.from('2026-06-01T00:00:00+00:00[UTC]'), to: Temporal.ZonedDateTime.from('2026-07-01T00:00:00+00:00[UTC]'), calendarIds: ['work'],})Create Events
Section titled “Create Events”Browser event creation uses the frontend token:
const event = await browserClient.events.create({ calendarId: workCalendar.id, title: 'Planning', description: 'Weekly planning session', location: 'Room 12', start: Temporal.ZonedDateTime.from( '2026-06-10T09:00:00+02:00[Europe/Berlin]' ), end: Temporal.ZonedDateTime.from( '2026-06-10T10:00:00+02:00[Europe/Berlin]' ), isPrivate: false, people: ['ada@example.com'],})Equivalent HTTP:
POST /v1/eventsAuthorization: Bearer sx_front_...Content-Type: application/json
{ "calendarId": "...", "title": "Planning", "start": "2026-06-10T09:00:00+02:00", "end": "2026-06-10T10:00:00+02:00", "timeZone": "Europe/Berlin", "people": ["ada@example.com"]}The public SDK requires calendarId, start, and end. Both range values must
use Temporal.PlainDate for an all-day event or Temporal.ZonedDateTime for a
timed event. Timed values must use the same timezone. The equivalent raw HTTP
request uses ISO strings plus the derived timeZone and isAllDay fields.
Update And Delete Events
Section titled “Update And Delete Events”await browserClient.events.update(event.id, { calendarId: workCalendar.id, title: 'Updated planning', start: Temporal.ZonedDateTime.from( '2026-06-10T09:30:00+02:00[Europe/Berlin]' ), end: Temporal.ZonedDateTime.from( '2026-06-10T10:30:00+02:00[Europe/Berlin]' ),})
await browserClient.events.delete(event.id)Event writes require the frontend-token user to have Owner, Admin, or Member membership in the organization.