DocumentationLocal Emulator

Local Emulator

The cPod emulator is a lightweight Node.js server that runs the full REST API locally with 100+ seed records across every EDM domain. No Docker. No external services. No credentials required — any Bearer token is accepted.

http://localhost:4000

Works with every SDK language. Point CPOD_API_URL at http://localhost:4000 and the SDK works exactly as it does in production. No code changes required to switch environments.


Quickstart

Clone the repo and install dependencies

git clone https://github.com/cpod-ai/cpod-sdk.git
cd cpod-sdk/emulator
npm install

Start the emulator

node src/index.js

You should see:

cPod Emulator v1.0.0
  Listening on http://localhost:4000
  Seed data: 8 people, 4 groups, 6 technology assets, 6 vulnerabilities, ...
  Auth: any Bearer token accepted (dev mode)

Verify it’s running

curl http://localhost:4000/v1/health
{
  "status": "ok",
  "version": "1.0.0",
  "uptime": 3,
  "edm": {
    "people": 8,
    "groups": 4,
    "technology": 6,
    "entitlements": 10,
    "licenses": 4,
    "vulnerabilities": 6,
    "complianceControls": 5,
    "riskItems": 3
  }
}

Set your environment variables

export CPOD_API_URL=http://localhost:4000
export CPOD_API_KEY=any-token-works-in-dev

That’s it — the emulator accepts any non-empty Bearer token. No OAuth registration needed for local development.


Make your first call

With the emulator running, try this in each language:

import { CpodClient } from '@cpod/sdk'
 
const sdk = CpodClient.fromEnv()
// Reads CPOD_API_URL and CPOD_API_KEY from env
 
const people = await sdk.people.list({ limit: 5 })
console.log(people.items)
// → [ { id: 'per-001', displayName: 'Alice Chen', ... }, ... ]

Seed Data

The emulator starts with real-looking seed data across every domain:

DomainEntities
People8 people (employees, contractors)
Groups4 groups (Engineering, Security, Compliance, IT)
Technology6 assets + 10 access entitlements
Licenses4 software licenses + 20 assignments
Assets5 physical assets + 5 cloud resources
Risk6 vulnerabilities, 5 controls, 3 risk items
Relationships8 graph edges
Data Sources4 connectors (Okta, GitHub, AWS, Jira)
Platform3 skills, 3 user profiles, 2 pods

All IDs use the correct prefix format (per-, grp-, vuln-, etc.) so you can build and test ID-based lookups immediately.


Available Endpoints

Every endpoint in the API Contract is available on the emulator. Key groups:

PrefixDomain
/v1/peoplePeople
/v1/groupsGroups
/v1/technology/assetsTechnology Assets
/v1/technology/entitlementsAccess Entitlements
/v1/licensesSoftware Licenses
/v1/assets/physicalPhysical Assets
/v1/assets/cloudCloud Resources
/v1/risk/vulnerabilitiesVulnerabilities
/v1/risk/controlsCompliance Controls
/v1/risk/itemsRisk Items
/v1/relationshipsGraph Relationships
/v1/datasourcesData Sources
/v1/storage/files/*Blob Storage
/v1/storage/db/*Document Storage
/v1/storage/kv/*Key-Value Storage
/v1/telemetry/audit/*Audit Events
/v1/telemetry/tracesLLM Traces
/v1/telemetry/eventsApp Events
/v1/organizations/currentOrganization
/v1/oauth/tokenToken endpoint (returns mock token)
/v1/healthHealth check

Auth in Dev Mode

The emulator accepts any non-empty Bearer token:

curl -H "Authorization: Bearer literally-anything" http://localhost:4000/v1/people
# Works ✓

The token is parsed but signature validation is skipped. The emulator injects a fixed tenantId, appId, and userId from the token’s claims if present, or uses sensible defaults.

To test the full OAuth flow (token issuance, scopes, refresh):

curl -X POST http://localhost:4000/v1/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials&client_id=emulator-client&client_secret=emulator-secret"
{
  "access_token": "eyJ...",
  "token_type": "bearer",
  "expires_in": 3600
}

Interactive API Browser

With the emulator running, open Swagger UI to explore and call every endpoint interactively:

npx @redocly/cli preview-docs docs/api-contract/openapi.yaml \
  --base-url http://localhost:4000

Or use Stoplight Elements (if installed):

npx @stoplight/elements-cli serve docs/api-contract/openapi.yaml

Auto-Instrumentation

The emulator mirrors production behaviour — every write operation (POST, PUT, PATCH, DELETE) automatically emits an audit event:

# Create a person
curl -X POST http://localhost:4000/v1/people \
  -H "Authorization: Bearer dev-token" \
  -H "Content-Type: application/json" \
  -d '{"email":"test@example.com","displayName":"Test User","firstName":"Test","lastName":"User","type":"employee"}'
 
# Check the audit log — the event was auto-emitted
curl -H "Authorization: Bearer dev-token" \
  http://localhost:4000/v1/telemetry/audit/events

CI Integration

Use the emulator in GitHub Actions without Docker:

# .github/workflows/integration.yml
jobs:
  integration:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
 
      - uses: actions/setup-node@v4
        with:
          node-version: '22'
 
      - name: Start emulator
        working-directory: emulator
        run: |
          npm install
          node src/index.js &
          sleep 2
          curl -sf http://localhost:4000/v1/health
 
      - name: Run integration tests
        env:
          CPOD_API_URL: http://localhost:4000
          CPOD_API_KEY: ci-dev-token
        run: pnpm test:integration

Environment Variables Reference

VariableEmulator valueProduction value
CPOD_API_URLhttp://localhost:4000https://api.yourdomain.com
CPOD_API_KEYany stringreal API key from dashboard
CPOD_CLIENT_IDemulator-clientyour registered client_id
CPOD_CLIENT_SECRETemulator-secretyour registered client_secret
⚠️

The emulator stores data in memory only — all writes are lost when the process restarts. It is not a substitute for a real database in staging environments.