RapidfolioRapidfolio
SDK

Connection SDK (Node.js)

Connect local services, internal APIs, and proprietary systems to Rapidfolio procedures without opening firewall ports.

Overview

The Connection SDK lets you expose functions from any service running inside your own infrastructure — internal APIs, proprietary databases, core banking systems — as callable tools within Rapidfolio procedures. No firewall rules, no public IP, no VPN required.

The SDK runs inside your service and maintains an outbound long-poll connection to Rapidfolio. When a procedure step needs to call one of your registered functions, Rapidfolio queues the invocation. The SDK picks it up, executes your handler locally, and posts the result back. The procedure then resumes with the result.

How It Works

Your service (SDK)                     Rapidfolio
      │                                  │
      │── GET /v1/sdk/poll ─────────────>│  (long-poll, waits for work)
      │                                  │
      │          [Procedure runs, calls your function]
      │                                  │
      │<── invocation payload ──────────│
      │                                  │
      │  [handler executes locally]      │
      │                                  │
      │── POST /v1/sdk/result ──────────>│
      │                                  │
      │          [Procedure resumes]     │
      │                                  │
      │── GET /v1/sdk/poll ─────────────>│  (immediately re-polls)

Key properties of this design:

  • All connections are outbound from your service — nothing needs to be open inbound.
  • Handlers run inside your network, with full access to your databases and internal services.
  • The SDK reconnects and re-polls automatically on transient network errors.
  • One SDK process can register multiple functions under a single connection.

Creating a Connection

  1. In the Rapidfolio dashboard, go to Connections → New Connection.
  2. Select Private Connection.
  3. Give the connection a name (e.g. Core Banking API).
  4. Rapidfolio generates two tokens — one for sandbox, one for live. Copy them now — they are shown once and cannot be retrieved again.
  5. Store the tokens in your service's environment variables (see Token Management).

Installation

npm install @rapidfolio/connection-sdk-node

Quick Start

import { Connection } from '@rapidfolio/connection-sdk-node'
import { z } from 'zod'

const conn = new Connection()
// Token is read automatically from the RAPID_TOKEN environment variable.

conn.register('getCustomer', {
  description: 'Fetch a customer by their ID',
  input: z.object({ customerId: z.string() }),
  handler: async ({ customerId }) => {
    return db.customers.findById(customerId)
  }
})

await conn.start()
console.log('Connected to Rapidfolio')

Registering Functions

Each registered function needs a description (shown to the AI agent), an input Zod schema, and a handler. register is chainable:

conn
  .register('getCustomer', {
    description: 'Fetch a customer by their ID from the core banking system',
    input: z.object({
      customerId: z.string().describe('The customer ID to look up')
    }),
    handler: async ({ customerId }, ctx) => {
      console.log(`[${ctx.environment}] Looking up customer ${customerId}`)
      return db.customers.findById(customerId)
    }
  })
  .register('createTransfer', {
    description: 'Initiate an internal bank transfer between two accounts',
    input: z.object({
      fromAccount: z.string().describe('Source account number'),
      toAccount: z.string().describe('Destination account number'),
      amount: z.number().positive().describe('Amount to transfer'),
      currency: z.string().default('GBP').describe('ISO 4217 currency code')
    }),
    requiresReview: true,
    handler: async ({ fromAccount, toAccount, amount, currency }) => {
      return bankingService.transfer({ fromAccount, toAccount, amount, currency })
    }
  })
  .register('freezeAccount', {
    description: 'Freeze a customer account to prevent further transactions',
    input: z.object({
      accountId: z.string(),
      reason: z.string().describe('Reason for the freeze, recorded in audit log')
    }),
    requiresReview: true,
    handler: async ({ accountId, reason }, ctx) => {
      console.log(`[${ctx.runId}] Freezing account ${accountId}: ${reason}`)
      return bankingService.freeze(accountId, reason)
    }
  })

await conn.start()

Human Review Gate

Set requiresReview: true to pause the procedure run for human approval before your handler is called:

  • Approved — your handler is called with the proposed arguments. The procedure resumes with the result.
  • Rejected — your handler is not called. The procedure receives a rejection signal and can handle it gracefully.

This is useful for high-impact operations such as fund transfers, account freezes, or any action that should require a second pair of eyes before executing.

Handler Context

Every handler receives an InvocationContext as its second argument:

PropertyTypeDescription
ctx.idstringUnique ID for this invocation
ctx.environment'sandbox' | 'live'The environment this run is executing in
ctx.runIdstring | nullThe ID of the current procedure run
ctx.procedureIdstring | nullThe ID of the procedure being executed
ctx.procedureVersionstring | nullThe version name of the procedure

Use ctx.environment to apply different behaviour in sandbox vs. live:

handler: async ({ customerId }, ctx) => {
  const db = ctx.environment === 'sandbox' ? sandboxDb : productionDb
  return db.customers.findById(customerId)
}

Token Management

Rapidfolio issues two tokens per connection:

Token prefixEnvironmentUsage
run_sandbox_xxxSandboxDevelopment and testing
run_live_xxxLiveProduction traffic

Set the appropriate token via the RAPID_TOKEN environment variable, or pass it explicitly:

RAPID_TOKEN=run_sandbox_xxxxxxxxxxxx node server.js
const conn = new Connection({ token: 'run_sandbox_xxxxxxxxxxxx' })

Regenerating Tokens

If a token is compromised or lost, regenerate it in the dashboard:

  1. Go to Connections → your connection → Regenerate Token.
  2. The old token is immediately invalidated — your running SDK will receive a 401 on the next poll and stop.
  3. Update RAPID_TOKEN in your environment and restart your service.

401 Behaviour

When the SDK receives a 401 it stops polling immediately and logs a clear error. It does not retry with an invalid token.

Connection Status API

Check whether your SDK is currently connected and see which functions are registered:

GET /api/v1/connections/:connectionId/private-connection/status?environment=sandbox

Response:

{
  "status": "connected",
  "lastPollAt": "2024-03-15T10:30:00.000Z",
  "registeredFunctions": [
    "getCustomer",
    "createTransfer",
    "freezeAccount"
  ]
}

status is "connected" if the SDK has polled within the last 60 seconds, otherwise "disconnected".

Local Testing

Use conn.connectLocal() to test handlers in-process without any network calls or token. Useful for unit tests:

import { Connection } from '@rapidfolio/connection-sdk-node'
import { z } from 'zod'

const conn = new Connection()

conn.register('getCustomer', {
  description: 'Fetch a customer by ID',
  input: z.object({ customerId: z.string() }),
  handler: async ({ customerId }) => ({
    id: customerId,
    name: 'Test User',
    status: 'active'
  })
})

const local = conn.connectLocal({ environment: 'sandbox' })

const result = await local.invoke('getCustomer', { customerId: 'cust_test' })
// result => { id: 'cust_test', name: 'Test User', status: 'active' }

Error Handling

Throw an error inside a handler to report a failure back to the procedure:

handler: async ({ customerId }) => {
  const customer = await db.customers.findById(customerId)
  if (!customer) throw new Error(`Customer ${customerId} not found`)
  return customer
}

The error message is surfaced in the procedure run's step output.

Security

  • Tokens are long-lived bearer tokens. Treat them like passwords.
  • Always store tokens in environment variables — never hard-code them.
  • Use the sandbox token during development; switch to live only in production.
  • Rotate tokens immediately if you suspect exposure.
  • The SDK communicates over HTTPS only.

On this page