Skip to content
Testnet only: a reference implementation, not a production service.Tokens and bank transfers here are simulated and have no value.

SDK reference

Every export of @scr/sdk, generated from its source. For the operations themselves, see the API reference.

createScrClient function

Creates a typed client for the public API. Every request is authenticated (API key or OAuth client credentials) and retried by {@link retryingFetch}.

function createScrClient(opts: ScrClientOptions)
Copied
const client = createScrClient({ baseUrl: "https://api.example.com", apiKey: "sk_test_123" });
const { data } = await client.GET("/v1/transfers");
Copied

importOAuthKey function

Imports a private JWK as a non-extractable, sign-only WebCrypto key for {@link ScrOauthOptions}: ECDSA P-256 for ES256, Ed25519 for EdDSA.

async function importOAuthKey(jwk: JsonWebKey, alg: "ES256" | "EdDSA"): Promise<CryptoKey>
Copied
const key = await importOAuthKey(JSON.parse(process.env.OAUTH_CLIENT_JWK!), "ES256");
Copied

paths type

Generated TypeScript types for every public API path, produced from the OpenAPI document. createScrClient is typed with it, so paths, parameters and bodies are checked at compile time. See /docs/api for each operation.

Operations are documented in the API reference.

type paths = { [path: string]: { [method: string]: Operation } }
Copied
import type { paths } from "@scr/sdk";

type CreateTransferBody = paths["/v1/transfers"]["post"]["requestBody"];
Copied

retryingFetch function

Wraps fetch with authentication (a bearer API key, or an OAuth client-credentials token that is cached and refreshed), an automatic Idempotency-Key on every POST, and retries with exponential backoff on network errors and 429/500/502/503/504 responses (Retry-After is honoured, capped at 30 s). PATCH requests are never retried. With OAuth, a 401 clears the cached token and the call is retried once with a new token and the same Idempotency-Key.

function retryingFetch(opts: RetryingFetchOptions): (req: Request) => Promise<Response>
Copied
const doFetch = retryingFetch({ apiKey: "sk_test_123", maxRetries: 3 });
const res = await doFetch(new Request("https://api.example.com/v1/transfers"));
Copied

RetryingFetchOptions type

Options for {@link retryingFetch}: either an `apiKey` or `oauth` client credentials with a required `tokenUrl`, plus optional retry tuning and a fetch override for tests.

type RetryingFetchOptions = Tuning &
  (
    | { apiKey: string; oauth?: never }
    | { apiKey?: never; oauth: ScrOauthOptions & { tokenUrl: string } }
  );
Copied
const opts: RetryingFetchOptions = { oauth: { clientId: "client_123", key, kid: "key_1", alg: "ES256", tokenUrl: "https://api.example.com/v1/oauth/token" } };
Copied

ScrClientOptions type

Options for {@link createScrClient}: the API base URL and either an `apiKey` or `oauth` client credentials (passing both is a type error), plus optional retry tuning and a fetch override for tests.

type ScrClientOptions = Tuning &
  (
    | { baseUrl: string; apiKey: string; oauth?: never }
    | { baseUrl: string; apiKey?: never; oauth: ScrOauthOptions }
  );
Copied
const opts: ScrClientOptions = { baseUrl: "https://api.example.com", apiKey: "sk_test_123", maxRetries: 5 };
Copied

ScrOauthOptions type

OAuth client-credentials settings (private_key_jwt) for {@link createScrClient }: the client ID, the signing key and its key ID, with optional token URL and scopes. `tokenUrl` defaults to `${baseUrl}/v1/oauth/token` and is also the assertion's `aud`, so it must equal the server's `OAUTH_TOKEN_AUDIENCE`.

interface ScrOauthOptions {
  clientId: string;
  key: CryptoKey;
  kid: string;
  alg: "ES256" | "EdDSA";
  tokenUrl?: string;
  scope?: string[];
}
Copied
const key = await importOAuthKey(jwk, "ES256");
const oauth: ScrOauthOptions = { clientId: "client_123", key, kid: "key_1", alg: "ES256", scope: ["accounts:read"] };
Copied

signWebhook function

Signs a webhook delivery in the Standard Webhooks format: `v1,<base64 HMAC-SHA256 over id.timestamp.body>`.

function signWebhook(secret: string, id: string, timestamp: number, body: string): string
Copied
const signature = signWebhook("whsec_test", "msg_1", 1700000000, '{"type":"transfer.completed"}');
Copied

verifyWebhook function

Verifies a webhook delivery: checks the webhook-id, webhook-timestamp and webhook-signature headers, rejects timestamps outside the tolerance (300 s by default) and compares signatures in constant time. Returns true only when one signature matches.

function verifyWebhook(
  secret: string,
  headers: Headers | Record<string, string>,
  body: string,
  now: Date = new Date(),
  toleranceSeconds = 300,
): boolean
Copied
const ok = verifyWebhook("whsec_test", request.headers, rawBody);
if (!ok) throw new Error("bad signature");
Copied

Edit on GitHub