JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 208
  • Score
    100M100P100Q81009F
  • License Apache-2.0

Official TypeScript SDK for the Fola form-filling API — auto-fill USCIS, EOIR immigration court, DOL ETA/PERM, and US district court PDFs from typed JSON. 72 forms ship typed; pay-per-fill via API key.

Package Exports

  • @folaform/forms-sdk

Readme

@folaform/forms-sdk

Official TypeScript SDK for the Fola form-filling API — auto-fill US immigration, immigration-court, labor-certification, and district-court PDFs from typed JSON, with one method per form, built-in wallet management, and zero runtime dependencies.

npm license

Runs on Node 18+ and modern browsers. Pure TypeScript, ships typed schemas for every form, fetch-based — no Axios, no node-fetch shim.


Install

npm install @folaform/forms-sdk
# or
pnpm add @folaform/forms-sdk
# or
yarn add @folaform/forms-sdk

Quick start

import { FolaClient } from '@folaform/forms-sdk';
import { writeFile } from 'node:fs/promises';

const client = new FolaClient({
  apiKey: process.env.FOLA_KEY!,    // fk_live_… or fk_test_…
});

const result = await client.fill('i-130', {
  petitioner_family_name: 'Doe',
  petitioner_given_name:  'John',
  beneficiary_family_name: 'Doe',
  beneficiary_given_name:  'Jane',
  // …intellisense lists every field, type-checks enums, dates, etc.
});

await writeFile('i-130.pdf', result.pdf);
console.log(`Charged ${result.costCents}¢ — wallet now ${result.balanceCents}¢`);

What's covered

72 forms ship typed in this release, across five sectors:

Sector Examples
USCIS I-9, I-90, I-129(F/S), I-130(A), I-131, I-134, I-140, I-192, I-290B, I-352, I-360, I-485 (+ Sup A/J), I-526(E), I-539(A), I-589, I-601, I-730, I-751, I-765(WS), I-821(D), I-824, I-829, I-864(A/EZ), I-907, I-912, I-914, I-918(A/B), AR-11, N-336, N-400, N-470, N-565, N-600, N-648
EOIR / Immigration Court EOIR-26, EOIR-26A, EOIR-27, EOIR-28, EOIR-29, EOIR-33 (BIA / IC), EOIR-40, EOIR-42A, EOIR-42B
DOL / ETA (PERM, H-2A, H-2B) ETA-9035, ETA-9089, ETA-9141, ETA-9142A, ETA-9142B, ETA-9142C
US District Court AO-440 summons, JS-44 civil cover sheet, mandamus action shell
Department of State (visa prep) DS-160 prep, DS-260 prep
G-forms G-28 (attorney appearance), G-639 (FOIA), G-1145 (e-notification), G-1450 (fee)

Tax-form coverage is intentionally not bundled in this SDK release.

API key + wallet

Generate keys and top up your wallet from the Fola workspace at /workspace/developer.

Each fill debits a per-form rate based on complexity tier:

Tier Cost / fill Examples
LARGE 50¢ I-485, I-589, N-400, ETA-9089
MEDIUM 30¢ I-130, I-765, EOIR-42A
SMALL 15¢ G-28, G-639, AO-440
Mandamus $2.00 mandamus action shell

Refunds are automatic if the engine errors after debiting.

Errors

import {
  FolaAuthError,
  FolaForbiddenError,
  InsufficientBalanceError,
  ValidationError,
  UnknownFormError,
} from '@folaform/forms-sdk';

try {
  await client.fill('i-130', { /* … */ });
} catch (err) {
  if (err instanceof InsufficientBalanceError) {
    console.error(`Top up — only ${err.balanceCents}¢ left, need ${err.costCents}¢`);
  } else if (err instanceof ValidationError) {
    // err.fieldErrors → { petitioner_family_name: 'required', ... }
    console.error(err.fieldErrors);
  } else if (err instanceof FolaAuthError) {
    console.error('API key revoked or invalid');
  } else if (err instanceof FolaForbiddenError) {
    // V225 introduced per-key scopes + IP allowlist. Branch on the
    // body code if you want different remediation copy:
    //   - 'developer_key_scope_missing' — widen scopes in the dashboard
    //   - 'developer_key_ip_blocked'    — add the egress IP to the allowlist
    //   - 'developer_api_disabled'      — email support to re-enable
    console.error(`Forbidden (${err.code}): ${err.message}`);
  } else if (err instanceof UnknownFormError) {
    console.error(`No such form: ${err.formId}`);
  } else throw err;
}

Per-key scopes and IP allowlist

Keys minted from the Developer Console can carry an explicit scope set (forms:fill, forms:read, account:read) and an optional IP allowlist (CIDR or bare IP, IPv4

  • IPv6). A request that hits an endpoint outside the key's scopes returns 403 developer_key_scope_missing; a request from a source IP outside the allowlist returns 403 developer_key_ip_blocked. Both surface as FolaForbiddenError with the code on err.code, and both can be widened or cleared from the dashboard's Edit restrictions dialog without re-minting the secret.

Typed schemas

Per-form TypeScript interfaces are auto-generated from the engine's form definitions at SDK release time:

import type { I130Inputs, N400Inputs, Eta9089Inputs } from '@folaform/forms-sdk';

const inputs: I130Inputs = {
  petitioner_family_name: 'Doe',
  petitioner_given_name:  'John',
  // intellisense lists every field, type-checks enums, dates, etc.
};

await client.fill('i-130', inputs);

There's also a runtime registry for callers that need to enumerate fields generically (e.g., to scaffold a UI):

import { FORM_REGISTRY } from '@folaform/forms-sdk';

const meta = FORM_REGISTRY['i-130'];
// → { title, complexityTier, inputs: { [field]: { type, required, label, help, example, enumValues? } } }

Webhooks

Subscribe to async fill / engine events with the bundled verifier:

import { verifyWebhook } from '@folaform/forms-sdk';

app.post('/fola/webhook', express.raw({ type: '*/*' }), (req, res) => {
  const event = verifyWebhook({
    body: req.body,
    signatureHeader: req.header('Fola-Signature')!,
    secret: process.env.FOLA_WEBHOOK_SECRET!,
  });
  // event.type → 'form.filled' | 'wallet.low_balance' | 'case.status_changed' | …
});

Architecture note

This SDK is the only documented client for the Fola public API. The REST surface (/api/public/v1/...) deliberately exposes no schema-introspection endpoint — to discover field names, install this SDK or read the generated TypeScript types in the published tarball. The fill engine still validates everything server-side, so bad inputs return field-level errors progressively without leaking the full schema upfront.

License

Apache-2.0. See LICENSE.