pasbydocs
Resources

TypeScript / Node.js SDK

@finsel-dgi/pasby — v2 REST client for identification, signing, flows, and documents.

The official Node.js library is @finsel-dgi/pasby. It targets API v2 on the public gateway (l.pasby.africa / s.pasby.africa) and maps one-to-one to the routes in Endpoint index.

Repository: github.com/Finsel-DGI/pasby-typescript-sdk

This package does not include OIDC (kipindi / shake / resource). For hosted login use @finsel-dgi/pasby-next or @finsel-dgi/pasby-react.

Requirements

  • Node.js 10 or higher
  • Dependency: axios (bundled with the package)
npm install @finsel-dgi/pasby

Configure the client

Use a named import (there is no default export):

import { Pasby } from "@finsel-dgi/pasby";

const pasby = new Pasby({
  apikeyAuth: "bk-test_YOUR_KEY",
  appSecretKey: "YOUR_APP_SECRET",
  basePath: "https://s.pasby.africa", // sandbox
  version: "v2", // default; only v2 is typed
});
OptionRequiredDefaultMaps to
apikeyAuthYesHeader x-api-key
appSecretKeyYesHeader x-access-secret
basePathNohttps://l.pasby.africaRequest host
versionNo"v2"Path segment /api/v2/...
baseOptionsNo{}Merged into every Axios call
EnvironmentbasePathKey prefix
Sandboxhttps://s.pasby.africabk-test_
Productionhttps://l.pasby.africabk-live_

See Credentials.

Client layout

The Pasby class exposes five namespaces:

NamespaceClassREST domain
pasby.healthHealthApiGET /api/health/check
pasby.identificationIdentificationApi/api/v2/identification/*
pasby.signingSigningApi/api/v2/signing/*
pasby.flowsFlowsApi/api/v2/flow/* (partial)
pasby.docsDocsApi/api/v2/document/*

Method → endpoint map

pasby.health

SDK methodHTTPPathHeaders
healthCheck()GET/api/health/checkx-api-key only

pasby.identification

SDK methodHTTPPath
sameDevice({ action, claims, payload })POST/api/v2/identification/same-device
differentDevice({ action, claims, payload, user })POST/api/v2/identification/different-device
wildcard({ action, claims, payload, seeds })POST/api/v2/identification/wildcard

action: "login" | "signup" | "link".
claims: typed claim keys from the SDK (e.g. "naming.given", "contact.email").

pasby.signing

SDK methodHTTPPath
sameDevice({ nin, action, payload, webhook? })POST/api/v2/signing/same-device
differentDevice({ nin, action, payload, webhook? })POST/api/v2/signing/different-device
wildcard({ action, payload, seeds, webhook? })POST/api/v2/signing/wildcard

action: "sign" (requires webhook) or "confirm" (no webhook).

pasby.flows

SDK methodHTTPPathIn SDK?
ping({ request })POST/api/v2/flow/pingYes
cancel({ request })POST/api/v2/flow/cancelYes
authorize({ sub, app })GET/api/v2/flow/authorizeGenerated but not public on FlowsApi
longPolling({ request })POST/api/v2/flow/pollingGenerated but not public on FlowsApi

Use pasby.flows (plural), not pasby.flow. For SSE (GET /api/v2/flow/sse) and v1 authorize, call the REST API directly or use Axios — the SDK does not expose those methods on the public class.

pasby.docs

SDK methodHTTPPath
docSign({ to, file, webhook })POST/api/v2/document/signing
docReview({ signee, file, webhook })POST/api/v2/document/review
docSignatureRefresh({ flow })POST/api/v2/document/refresh

flow on refresh must be at least 40 characters.

Reading responses

All methods return an Axios response. The pasby JSON envelope is on response.data:

const { data } = await pasby.identification.wildcard({
  action: "signup",
  claims: ["naming.given", "contact.email"],
  seeds: 4,
  payload: "Create your account",
});

console.log(data.status); // e.g. "successful"
console.log(data.data.request.id); // flow id for ping
console.log(data.data.seeds); // QR seeds (wildcard)

Poll with:

const { data: ping } = await pasby.flows.ping({
  request: data.data.request.id,
});

Errors

Failed HTTP calls throw PasbyError (exported from the package) with status, reason, responseBody, and validation details when the API returns Zod-style arrays.

import { Pasby, PasbyError } from "@finsel-dgi/pasby";

try {
  await pasby.identification.differentDevice({ /* ... */ });
} catch (err) {
  if (err instanceof PasbyError) {
    console.error(err.status, err.message);
  }
}

See Errors reference.

End-to-end example (sandbox)

import { Pasby } from "@finsel-dgi/pasby";

const pasby = new Pasby({
  apikeyAuth: process.env.PASBY_API_KEY!,
  appSecretKey: process.env.PASBY_APP_SECRET!,
  basePath: "https://s.pasby.africa",
});

// 1. Start identification
const { data: start } = await pasby.identification.wildcard({
  action: "signup",
  claims: ["naming.given", "contact.email"],
  seeds: 4,
  payload: "Create your account",
});

const flowId = start.data.request.id;

// 2. Poll until complete (simplified)
let done = false;
while (!done) {
  const { data: ping } = await pasby.flows.ping({ request: flowId });
  const req = ping.data.request;
  if (req.cancelled || req.signature) done = true;
  else await new Promise((r) => setTimeout(r, 2000));
}

// 3. Decrypt claims on your server — see Handling encrypted claims guide

More examples: Quickstart, SampleCode, SDK repo examples/document-signature-refresh.ts.

v1 and OIDC

FeatureThis SDK
API v2 RESTSupported (default)
API v1 / x-access-tokenNot typed; use REST or migrate to v2
OIDCUse @finsel-dgi/pasby-next / @finsel-dgi/pasby-react

Exported types

The package re-exports request/response interfaces (e.g. FlowsPingResponse, IdentificationSameDeviceResponse, PasbyDocSignRequest) for TypeScript consumers. Import from @finsel-dgi/pasby when you need strict typing.

On this page