> ## Documentation Index
> Fetch the complete documentation index at: https://docs.formabledocs.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Node

> Install and use formable-node, the official Node.js SDK for the Formable API.

[`formable-node`](https://www.npmjs.com/package/formable-node) is the official Node.js SDK for the Formable API (v1). It covers templates, signature requests, redlining, and billing.

* Zero runtime dependencies (uses native `fetch`)
* Full TypeScript types for every request and response
* Node.js 18+

Source code is on [GitHub](https://github.com/FormableDocs/formable-node).

## Installation

<CodeGroup>
  ```bash npm theme={null}
  npm install formable-node
  ```

  ```bash bun theme={null}
  bun add formable-node
  ```

  ```bash yarn theme={null}
  yarn add formable-node
  ```

  ```bash pnpm theme={null}
  pnpm add formable-node
  ```
</CodeGroup>

## Initialize the client

Pass your API key from [Settings](https://app.formabledocs.com/settings). It's sent as a bearer token on every request.

```ts theme={null}
import Formable from "formable-node";

const formable = new Formable({ apiKey: process.env.FORMABLE_API_KEY! });
```

## Templates

Upload a document to create a reusable template, then mint edit URLs to place fields in the embedded editor. See the [embedded templates walkthrough](/walkthroughs/embedded-templates).

```ts theme={null}
import { readFile } from "node:fs/promises";

const file = await readFile("./nda.docx");

const { templateId, editTemplateAccess } = await formable.templates.create({
  file,
  filename: "nda.docx",
  signerRoles: [
    { name: "Client", order: 0 },
    { name: "Witness", order: 1 },
  ],
});

// Mint a fresh edit URL later (expires after 1 day)
const { editUrl, expiresAt } = await formable.templates.createEditUrl(templateId);
```

## Signature requests

Send a template for signing by email, or embed the signing experience in your product. See the [embedded signing walkthrough](/walkthroughs/embedded-signing).

```ts theme={null}
// Formable emails each signer a signing link
const request = await formable.signatureRequests.create({
  templateId,
  signers: [
    { email: "jane@example.com", name: "Jane Doe", role: "Client" },
    { email: "bob@example.com", name: "Bob Smith", role: "Witness" },
  ],
});

// Embedded flow: mint signing URLs to embed in an iframe yourself
const embedded = await formable.signatureRequests.createEmbedded({
  templateId,
  signers: [{ email: "jane@example.com", name: "Jane Doe", role: "Client" }],
  testMode: true,
});

const [signer] = embedded.signers;
const { signingUrl } = await formable.signatureRequests.createSigningUrl(
  signer.recipientSignatureId
);

// Track progress
const current = await formable.signatureRequests.get(embedded.signatureRequestId);
const all = await formable.signatureRequests.list({ updatedSince: new Date("2026-01-01") });
const { signatureRequestEvents } = await formable.signatureRequests.getEvents(
  embedded.signatureRequestId
);

// Download the signed document once completed
const { signedEnvelopePresignedUrl } =
  await formable.signatureRequests.getSignedEnvelope(embedded.signatureRequestId);
```

<Note>
  `getSignedEnvelope` returns `409` until the document is complete. Wait for the [`document_completed`](/webhooks/events#document_completed) webhook, or poll `get` until `status` is `Completed`.
</Note>

## Redline requests

Run turn-based contract negotiation before signing. See the [redlining walkthrough](/walkthroughs/redlining).

```ts theme={null}
const { redlineRequestId } = await formable.redlineRequests.create({
  templateId,
  members: [
    { email: "us@example.com", displayName: "John Doe", role: "DisclosingParty" },
    { email: "them@example.com", displayName: "Jane Smith", role: "ReceivingParty" },
  ],
  metadata: { subject: "Mutual NDA" },
});

// Mint a redline URL for a member (embed in an iframe)
const { redlineUrl } = await formable.redlineRequests.createUrl(
  redlineRequestId,
  "them@example.com"
);

// Manage members and track progress
await formable.redlineRequests.updateMembers(redlineRequestId, [
  { email: "counsel@example.com", displayName: "Counsel", role: "ReceivingCounsel" },
]);
const redline = await formable.redlineRequests.get(redlineRequestId);
const { redlineRequestEvents } = await formable.redlineRequests.getEvents(redlineRequestId);
```

## Billing and health

```ts theme={null}
const { numberOfRedliningSessions } = await formable.billing();
const health = await formable.health();
```

## Error handling

All non-2xx responses throw a `FormableError` with the server's error message, HTTP status, and parsed response body.

```ts theme={null}
import { FormableError } from "formable-node";

try {
  await formable.signatureRequests.get("missing-id");
} catch (error) {
  if (error instanceof FormableError) {
    console.error(error.status, error.message);
  }
}
```

## Configuration

| Option    | Description                                               | Default                           |
| --------- | --------------------------------------------------------- | --------------------------------- |
| `apiKey`  | Your Formable API key (sent as a bearer token). Required. | -                                 |
| `baseUrl` | Override the API base URL.                                | `https://api.formabledocs.com/v1` |
| `fetch`   | Custom `fetch` implementation.                            | `globalThis.fetch`                |

## Next steps

<CardGroup cols={2}>
  <Card title="Quickstart" icon="rocket" href="/quickstart">
    Go from a plain document to a signed PDF in 4 calls.
  </Card>

  <Card title="API reference" icon="code" href="/api-reference/introduction">
    Every endpoint the SDK wraps, with a live playground.
  </Card>
</CardGroup>
