Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.firma.dev/llms.txt

Use this file to discover all available pages before exploring further.

Firma lets you add legally binding e-signatures to anything you build with Claude Code. Connect Firma’s MCP servers and Claude Code can generate accurate Firma integration code, manage your signing requests, and operate on your Firma data directly from the terminal or your IDE.

Prerequisites

Firma uses the raw API key as the Authorization header value - do not prefix it with Bearer. This differs from many other APIs.

Getting started

Step 1: Add the Firma MCP servers

Add both Firma MCP servers to your project settings. In your project root, create or edit .claude/settings.json:
{
  "mcpServers": {
    "firma-api": {
      "url": "https://mcp.firma.dev/mcp"
    },
    "firma-docs": {
      "url": "https://docs.firma.dev/mcp"
    }
  }
}
Alternatively, add them to your user settings at ~/.claude/settings.json to make them available across all projects.
  • firma-api gives Claude Code direct access to the Firma API - 84 tools across signing requests, templates, workspaces, and webhooks.
  • firma-docs gives Claude Code access to Firma’s full documentation so it generates accurate integration code.
Restart Claude Code after saving the config. On first use of a Firma API tool, Claude Code will walk you through signing in with your Firma account via OAuth.
When to use which server: firma-api is for doing things (sending signing requests, managing templates). firma-docs is for building things (generating integration code with accurate API details). Most developers want both connected.

Step 2: Use Firma from Claude Code

Once connected, you can ask Claude Code to build Firma integrations or operate on your data: Generate a backend integration:
Using the Firma API docs, create an Express route that:
1. Accepts a name, template_id, signer email, and signer name
2. Uses the create-and-send endpoint to send a signing request
3. Returns the signing request ID and the signer's signing link
Store the API key in process.env.FIRMA_API_KEY.
List your signing requests:
List all pending signing requests in my default workspace.
Send a signing request:
Create a signing request from the NDA template and send it to jane@example.com
Add embedded signing to a React app:
Using the Firma docs, add an embedded signing view to this React app.
After a signing request is created, render the signer's signing_link
in an iframe.
Wire up webhooks:
Using the Firma docs, create a webhook handler that listens for
signing_request.completed events and updates the contract status
in our Postgres database.
Referencing “the Firma docs” explicitly tells Claude Code to query the firma-docs MCP server before writing code. Without that, it may fall back to general knowledge and miss endpoint or auth details.

What Claude Code generates

When you ask Claude Code to build a Firma integration, the generated backend code should look like this:
import express from "express";

const FIRMA_API = "https://api.firma.dev/functions/v1/signing-request-api";
const app = express();
app.use(express.json());

app.post("/api/signing-requests", async (req, res) => {
  const { name, template_id, signer_email, signer_first_name, signer_last_name } =
    req.body;

  const response = await fetch(
    `${FIRMA_API}/signing-requests/create-and-send`,
    {
      method: "POST",
      headers: {
        Authorization: process.env.FIRMA_API_KEY,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        name,
        template_id,
        recipients: [
          {
            first_name: signer_first_name,
            last_name: signer_last_name,
            email: signer_email,
            designation: "Signer",
            order: 1,
          },
        ],
      }),
    }
  );

  const data = await response.json();

  if (!response.ok) return res.status(response.status).json({ error: data });
  res.json({
    signing_request_id: data.id,
    signing_request_user_id: data.first_signer.id,
    signing_link: data.first_signer.signing_link,
  });
});

app.listen(3000);
The create-and-send endpoint creates the signing request and sends it to recipients atomically. If you need to review or modify the request before sending, use POST /signing-requests to create a draft, then POST /signing-requests/{id}/send separately.
Never expose your API key in frontend code. Always call the Firma API from a backend where secrets are kept secure.

Webhook integration

To track signing events in real time, ask Claude Code to add a webhook handler:
Using the Firma docs, create a webhook handler that receives Firma events.
When signing_request.completed fires, update the contract record in the database.
The agent will generate something like this:
app.post("/api/firma-webhook", async (req, res) => {
  const { type, data } = req.body;

  if (type === "signing_request.completed") {
    const signingRequestId = data.signing_request.id;
    // Update your database or trigger the next workflow step.
  }

  res.json({ received: true });
});
In the Firma dashboard under Settings > Webhooks, register your endpoint URL. Firma sends events for all major state changes. See the webhooks guide for the full event list and signature verification.
Always verify the webhook signature using your Firma webhook signing secret in production. See the webhooks guide for implementation details.

Embedded signing

For apps where signers complete documents inside your UI instead of opening a Firma-hosted page, the create-and-send response includes first_signer.id (the signing_request_user_id) and a ready-made first_signer.signing_link. Load the signer URL in an iframe:
<iframe
  src="https://app.firma.dev/signing/{signing_request_user_id}"
  style="width:100%;height:900px;border:0;"
  allow="camera;microphone;clipboard-write"
  title="Document Signing"
></iframe>
See the embedded signing guide for full setup including security best practices.

Tips

  • Use firma-docs when building, firma-api when operating. The docs server helps Claude Code write correct integration code. The API server lets it manage signing requests, templates, and workspaces directly.
  • Pass template_id explicitly. Templates are the safest way to constrain what the agent can send.
  • Validate before sending. For higher-stakes documents, ask Claude Code to create a draft with POST /signing-requests, then confirm before calling POST /signing-requests/{id}/send.
  • Workspaces for multi-tenant apps. If you are building a SaaS product, give each end customer their own Firma workspace so templates and usage stay isolated.

Next steps