Skip to main content

Setting Up SCP TypeScript Client

Overview

This guide shows how to set up the SCP TypeScript SDK client for the Service Commerce Platform API, authenticate using a Bearer token, and perform basic Tenant CRUD operations.

Getting Started

Prerequisites

  • Node.js >= 18
  • SCP API running locally on port 4000 (or use Docker Compose)
  • Admin credentials for authentication

Quick Start with Docker

The SCP Docker image is hosted on GitHub Container Registry (GHCR). You'll need a Personal Access Token (PAT) with read:packages scope to pull the image.

Step 1: Authenticate with GHCR

Your PAT will be provided by your team lead via secure channel (email, 1Password, etc.).

# Login to GitHub Container Registry
# Replace YOUR_GITHUB_USERNAME and YOUR_PAT with actual values
echo "YOUR_PAT" | docker login ghcr.io -u YOUR_GITHUB_USERNAME --password-stdin

Step 2: Download and Start

# Download docker-compose.yml from the documentation site
curl -O https://service-commerce-platform.alvera.ai/docker-compose.yml

# Download environment file
curl -O https://service-commerce-platform.alvera.ai/scp.env

# Start the platform
docker compose up -d

# API is now available at http://localhost:5001

Note: The Docker image pulls from ghcr.io/alvera-ai/service-commerce-platform:0.4.0. Ensure you're authenticated before running docker compose up.

Installation

# Create a new project
mkdir my-scp-app && cd my-scp-app
npm init -y

# Install the SDK (generated from OpenAPI)
npm install @scp/sdk

# Or generate your own from the OpenAPI spec
npx openapi-typescript-codegen \
--input http://localhost:4000/api/openapi.yaml \
--output src/sdk \
--client fetch

API Flow

Code Examples

1. Authentication

import { OpenAPI, AuthenticationService } from '@scp/sdk';

// Configure base URL
OpenAPI.BASE = 'http://localhost:4000';

// Authenticate and get Bearer token
const auth = await AuthenticationService.sessionCreate({
requestBody: {
email: 'admin@alvera-scp-dev.local',
password: 'DevPassword123!',
tenant_name: 'alvera-scp-dev',
},
});

// Set token for all subsequent requests
OpenAPI.TOKEN = auth.token;
console.log('Authenticated successfully');

2. Create a Tenant

import { TenantService } from '@scp/sdk';

const tenant = await TenantService.tenantCreate({
requestBody: {
name: `My Salon ${Date.now()}`,
type: 'enterprise',
domain_name: 'my-salon.example.com',
},
});

console.log(`Created tenant: ${tenant.data.name} (${tenant.data.id})`);

3. Get Tenant by ID

const tenant = await TenantService.tenantShow({
id: tenantId,
});

console.log(`Retrieved tenant: ${tenant.data.name}`);
console.log(`Domain: ${tenant.data.domain_name}`);

4. List Tenants with Pagination

const result = await TenantService.tenantList({
page: 1,
pageSize: 10,
});

console.log(`Total tenants: ${result.meta.total_count}`);
console.log(`Page ${result.meta.page} of ${result.meta.total_pages}`);

for (const tenant of result.data) {
console.log(`- ${tenant.name} (${tenant.type})`);
}

5. Update Tenant

const updated = await TenantService.tenantUpdate({
id: tenantId,
requestBody: {
name: `Updated Salon ${Date.now()}`,
domain_name: 'updated.example.com',
},
});

console.log(`Updated tenant: ${updated.data.name}`);

6. Delete Tenant

await TenantService.tenantDelete({
id: tenantId,
});

console.log(`Deleted tenant: ${tenantId}`);

Using Client Samples

For convenience, you can use the pre-built client samples:

import { createTenant } from '@scp/client-samples/tenants/create';
import { listTenants } from '@scp/client-samples/tenants/list';
import { getTenant } from '@scp/client-samples/tenants/show';
import { updateTenant } from '@scp/client-samples/tenants/update';
import { deleteTenant } from '@scp/client-samples/tenants/delete';

// Create
const tenant = await createTenant();

// Read
const fetched = await getTenant(tenant.id);

// List
const { data, meta } = await listTenants();

// Update
const updated = await updateTenant(tenant.id);

// Delete
await deleteTenant(tenant.id);

Download: TypeScript Client Samples

Error Handling

try {
const tenant = await TenantService.tenantCreate({
requestBody: {
name: '', // Invalid - empty name
type: 'invalid_type', // Invalid enum
},
});
} catch (error) {
if (error.status === 422) {
console.error('Validation errors:', error.body.errors);
// { name: ["can't be blank"], type: ["is invalid"] }
}
}

API Response Format

Single Resource (GET, POST, PUT)

{
"data": {
"id": "80dbf797-6e35-4b5c-8cfb-703a79cce584",
"name": "My Salon",
"type": "enterprise",
"domain_name": "my-salon.example.com",
"inserted_at": "2024-01-15T10:30:00.123456Z",
"updated_at": "2024-01-15T10:30:00.123456Z"
}
}

List Response (GET with pagination)

{
"data": [
{ "id": "uuid1", "name": "Tenant 1", "..." : "..." },
{ "id": "uuid2", "name": "Tenant 2", "..." : "..." }
],
"meta": {
"page": 1,
"page_size": 10,
"total_count": 42,
"total_pages": 5
}
}

Error Response (422)

{
"errors": {
"name": ["can't be blank"],
"type": ["is invalid"]
}
}

Next Steps

After setting up the client, you can:

  1. Create merchant organizations under the tenant
  2. Set up service providers and services
  3. Configure appointment slots and availability
  4. Process bookings and payments

See the API Reference for all available endpoints.

Downloads