Skip to content

TypeScript SDK

The Scopebound TypeScript SDK is the official Node.js client for the Scopebound enforcement plane. Use it to evaluate AI agent workflows against authorization scopes before they execute.

Install

npm install @scopebound/sdk

The SDK has zero runtime dependencies — only the Scopebound API key and base URL are needed.

Quickstart

import { ScopeboundClient } from '@scopebound/sdk';

const client = new ScopeboundClient({
  apiKey: process.env.SCOPEBOUND_API_KEY!,
  baseUrl: 'https://your-partner.api.scopebound.ai',
});

const result = await client.evaluate({
  roleId: '747b0d54-3b89-48ab-b0d3-5f0f551630d6',
  evaluationProfile: ['PRODUCTION_READINESS'],
  workflow: {
    workflowId: 'invoice-processor',
    nodes: [
      { id: 'src', type: 'source', tool: 'manual_trigger' },
      { id: 'dst', type: 'destination', tool: 'post_to_erp', credentials: ['sap-prod-api'] },
    ],
    edges: [{ from: 'src', to: 'dst' }],
  },
});

console.log(result.productionReadinessStatus);  // "pass" or "fail"
console.log(result.violations);                  // [] or violation objects
console.log(result.attestationToken);            // Signed JWT for audit retention

Workflow formats

The SDK accepts two workflow shapes via the sourceFormat parameter:

canonical (default)

Scopebound's native workflow shape. Use this when constructing workflow definitions in your code:

await client.evaluate({
  roleId: '...',
  evaluationProfile: ['PRODUCTION_READINESS'],
  sourceFormat: 'canonical',  // Default — can be omitted
  workflow: {
    workflowId: 'my-workflow',
    nodes: [
      { id: 'src', type: 'source', tool: 'manual_trigger' },
      { id: 'mid', type: 'transform', tool: 'parse_invoices' },
      { id: 'dst', type: 'destination', tool: 'post_to_erp', credentials: ['sap-prod-api'] },
    ],
    edges: [
      { from: 'src', to: 'mid' },
      { from: 'mid', to: 'dst' },
    ],
  },
});

n8n

Native n8n workflow exports. Use this when you have an n8n workflow JSON (from n8n's UI export):

const n8nWorkflow = {
  name: 'invoice-processor',
  nodes: [/* ... n8n node definitions ... */],
  connections: {/* ... n8n connections ... */},
};

await client.evaluate({
  roleId: '...',
  evaluationProfile: ['PRODUCTION_READINESS'],
  sourceFormat: 'n8n',
  workflowRaw: n8nWorkflow,
});

Supported source formats: canonical, n8n, make, zapier.

Response shape

{
  evaluationId: string;              // Unique ID for this evaluation
  workflowId: string;                // From the input workflow
  roleId: string;                    // The role evaluated against
  workflowHash: string;              // SHA-256 of the canonical workflow
  status: 'pass' | 'fail' | 'warnings';
  productionReadinessStatus?: 'pass' | 'fail' | 'warnings';
  soc1Status?: 'pass' | 'fail' | 'warnings' | 'not_evaluated';
  soc2Status?: 'pass' | 'fail' | 'warnings' | 'not_evaluated';
  violations: EvaluationViolation[];
  warnings: EvaluationViolation[];
  profile: EvaluationProfile[];
  attestationToken?: string;         // Signed JWT for audit
  evaluatedAt: string;               // ISO-8601 timestamp
}

Each violation has a code (e.g. SB-SCOPE-001), severity (critical, high, medium, low, info), the offending nodeId, a human-readable message, and (optionally) remediation text.

Common patterns

Block execution on critical violations

const result = await client.evaluate({
  roleId,
  evaluationProfile: ['PRODUCTION_READINESS'],
  workflow,
});

const critical = result.violations.filter(v => v.severity === 'critical');
if (critical.length > 0) {
  throw new Error(
    `Workflow blocked by ${critical.length} critical violations: ` +
    critical.map(v => `${v.code} on ${v.nodeId}`).join(', ')
  );
}

// Proceed with workflow execution

Verify the attestation token offline

The attestation token is a signed JWT. You can verify it without calling Scopebound at runtime:

import { verifyAttestation } from '@scopebound/sdk';

const isValid = await verifyAttestation(result.attestationToken, {
  publicKeyUrl: 'https://your-partner.api.scopebound.ai/v1/attestation/pubkey',
});

Store the public key locally (or in your secrets manager) once, then verify tokens offline. Useful for audit retention pipelines that can't call back to Scopebound.

Run multiple compliance profiles

await client.evaluate({
  roleId,
  evaluationProfile: ['SOC1', 'SOC2_TYPE_II', 'PRODUCTION_READINESS', 'HIPAA'],
  workflow,
});

Each profile's status surfaces independently in the response (soc1Status, soc2Status, etc.). The overall status is fail if any profile fails.

Error handling

The SDK throws typed errors:

import {
  ScopeboundAuthError,        // 401 / 403 — API key issue
  ScopeboundNotFoundError,    // 404 — role not found
  ScopeboundRequestError,     // 400 — request shape invalid
  ScopeboundServerError,      // 5xx — enforcement plane unavailable
  ScopeboundUnreachableError, // Network failure
} from '@scopebound/sdk';

try {
  await client.evaluate({/* ... */});
} catch (err) {
  if (err instanceof ScopeboundAuthError) {
    // Refresh API key, then retry
  } else if (err instanceof ScopeboundNotFoundError) {
    // Role doesn't exist — provision it via the management API
  } else {
    throw err;
  }
}

All errors carry the HTTP status code (err.status) and the server's response body (err.responseBody) when available, making them easy to log or surface to downstream systems.

Next steps