JSPM

@craftedxp/sdk-node

0.8.0
    • ESM via JSPM
    • ES Module Entrypoint
    • Export Map
    • Keywords
    • License
    • Repository URL
    • TypeScript Types
    • README
    • Created
    • Published
    • Downloads 12
    • Score
      100M100P100Q83289F
    • License MIT

    Node.js / TypeScript SDK for the voice agent platform. Server-side API client — mint call tokens, manage agents, query calls, upload knowledge-base docs.

    Package Exports

    • @craftedxp/sdk-node

    Readme

    @craftedxp/sdk-node

    Node.js / TypeScript SDK for the voice agent platform. Use it from your backend to mint short-lived call tokens, manage agents, query calls, and upload knowledge-base docs.

    Pairs with @craftedxp/voice-rn (the React Native client SDK). Your app calls fetchToken → your backend uses this SDK → the platform mints a ct_ token → returned to the app. The sk_ API key only ever lives on your backend.

    Zero runtime dependencies. Node 18+.

    Install

    npm install @craftedxp/sdk-node

    Quick start — minting a call token

    The most common use:

    import { PlatformClient } from '@craftedxp/sdk-node'
    
    const client = new PlatformClient({
      apiKey: process.env.VOICE_AGENT_SK!, // never ship this to a client
      baseUrl: 'https://api.your-server.com', // or http://localhost:8080 for dev
    })
    
    // In your "/voice-token" route handler — called by the RN SDK's fetchToken:
    async function mintForCall({ agentId, userId, context, metadata }) {
      const { token } = await client.callTokens.mint({
        agentId,
        ttlSeconds: 600, // 10 min default; up to 3600 (60 min)
        contactId: userId, // optional → cross-call memory
        context, // optional arbitrary JSON, lowered into agent's system prompt
        metadata, // optional opaque keys round-tripped on call.ended webhook (≤1 KB)
      })
      return { token } // hand to the RN SDK
    }

    The full call-token surface:

    client.callTokens.mint({ agentId, ttlSeconds, context, metadata, contactId, vars, allowedOrigins })
    client.callTokens.list({ includeRevoked, includeExpired, limit })
    client.callTokens.revoke(tokenId)

    Other resources

    client.me.get()                                              // the org behind the sk_
    
    client.agents.create({ name, systemPrompt, ... })            // CRUD on agents
    client.agents.list({ limit, cursor })
    client.agents.get(agentId)
    client.agents.update(agentId, patch)
    client.agents.delete(agentId)
    client.agents.webhooks(agentId).create({ url, secret, events })
    client.agents.webhooks(agentId).list()
    // ...
    
    client.calls.list({ agentId, status, limit, cursor })        // call records
    client.calls.listAll({ agentId })                            // async iterator across pages
    client.calls.get(callId)
    
    client.knowledgeBases.create({ name })                       // KB CRUD + uploads
    client.knowledgeBases.list()
    client.knowledgeBases.uploadFile(kbId, filePath)
    client.knowledgeBases.delete(kbId)
    
    client.credits.getBalance()                                  // billing
    client.credits.getLedger({ limit, cursor })
    
    client.webhooks.deliveries({ agentId, callId, webhookId })   // org-wide delivery log

    Webhook signature verification

    import express from 'express'
    import { verifyWebhookSignature } from '@craftedxp/sdk-node'
    
    const app = express()
    
    app.post(
      '/webhooks/voice-agent',
      // Raw body — we need the exact bytes to recompute the HMAC.
      express.raw({ type: 'application/json' }),
      (req, res) => {
        const sig = req.header('X-Platform-Signature-256') ?? ''
        if (!verifyWebhookSignature(req.body, sig, process.env.VOICE_AGENT_WEBHOOK_SECRET!)) {
          return res.status(401).send('invalid signature')
        }
        const event = JSON.parse(req.body.toString('utf8'))
        // ...handle event
        res.status(200).end()
      },
    )

    The function is timing-safe; copy it into your middleware verbatim. No PlatformClient instance required — verifyWebhookSignature is a standalone helper so any framework (Koa, Next.js route handlers, Hono, etc.) can use it.

    Errors

    All HTTP errors throw a typed PlatformError:

    import { PlatformError } from '@craftedxp/sdk-node'
    
    try {
      await client.callTokens.mint({ agentId })
    } catch (err) {
      if (err instanceof PlatformError) {
        console.error(err.code, err.status, err.message, err.field, err.docsUrl)
      }
      throw err
    }

    The HTTP layer auto-retries 429 (honouring Retry-After) and 5xx responses with exponential backoff. Default maxRetries = 2 (3 total attempts); pass 0 to new PlatformClient({ maxRetries: 0 }) to disable.

    Pagination

    Cursor-based. Use the listAll async iterator if you want every page without managing the cursor manually:

    for await (const call of client.calls.listAll({ agentId })) {
      // process each call across all pages
    }

    What's NOT in this SDK

    • Voice / WebSocket / audio streaming. Use @craftedxp/voice-rn (React Native) for the call path itself.
    • Browser-side use. This SDK assumes a server-side environment with native fetch. The sk_ API key must never reach a browser.
    • Phone numbers, outbound dialling. Telephony is on the platform roadmap; the SDK will surface it when the server endpoints land.

    Migration from @voxline/node@0.1.0

    @voxline/node was a pre-launch internal name. This package replaces it under the @craftedxp org. API surface is unchanged except for the Phase 12 additions (context / metadata / contactId on callTokens.mint).

    - import { PlatformClient } from '@voxline/node'
    + import { PlatformClient } from '@craftedxp/sdk-node'
    
      const client = new PlatformClient({ apiKey })
    - await client.callTokens.mint({ agentId, vars: { name: 'Arun' } })
    + await client.callTokens.mint({ agentId, context: { name: 'Arun', orders: [/* nested ok */] } })

    vars is still accepted server-side for backward compatibility.