Saltar al contenido principal
Firma te permite agregar firmas electrónicas legalmente vinculantes a cualquier app creada en InsForge. Como InsForge le da a tu agente de código cómputo, hosting, autenticación y almacenamiento listos para usar, puedes integrar Firma en una app ya construida por un agente agregando una función de cómputo y un manejador de webhook. Esta guía cubre dos caminos de integración:
  1. Función de cómputo (por app) — Escribe una función de TypeScript que llama directamente a la API REST de Firma. Ideal para apps individuales o lógica personalizada.
  2. Generación asistida por MCP (a nivel de agente) — Conecta el servidor MCP de Firma Docs a tu agente de código para que pueda escribir la integración por ti usando referencias precisas de la API.

Requisitos previos

  • Una cuenta de Firma con una clave API
  • Un proyecto de InsForge con cómputo y almacenamiento habilitados
  • Al menos una plantilla de Firma con campos de firma configurados
Firma usa la clave API sin procesar como el valor del encabezado Authorization; no la antepongas con Bearer. Esto difiere de muchas otras APIs.

Primeros pasos

Este es el enfoque más directo. Escribes una función de cómputo en TypeScript que llama a la API REST de Firma.

Paso 1: Guarda tu clave API como un secreto

En el panel de tu proyecto de InsForge, agrega un secreto llamado FIRMA_API_KEY con tu clave API de Firma como valor. Consulta la documentación de secretos de InsForge para más detalles.El secreto está encriptado y disponible automáticamente para tus funciones de cómputo mediante Deno.env.get("FIRMA_API_KEY").
Nunca expongas tu clave API en código de frontend. Llama siempre a la API de Firma desde funciones de cómputo, donde los secretos se mantienen seguros.

Paso 2: Crea una función de cómputo para enviar solicitudes de firma

Crea una nueva función en tu proyecto de InsForge, o pídele a tu agente de código que genere una. Esta función crea una solicitud de firma a partir de una plantilla y la envía en una sola llamada a la API usando el endpoint create-and-send:
import { createClient } from "npm:@insforge/sdk";

const FIRMA_API = "https://api.firma.dev/functions/v1/signing-request-api";

const corsHeaders = {
  "Access-Control-Allow-Origin": "*",
  "Access-Control-Allow-Headers": "authorization, content-type",
};

export default async function handler(req: Request) {
  if (req.method === "OPTIONS") {
    return new Response("ok", { headers: corsHeaders });
  }

  const insforge = createClient({
    baseUrl: Deno.env.get("INSFORGE_BASE_URL")!,
    anonKey: Deno.env.get("ANON_KEY")!,
  });

  const authHeader = req.headers.get("Authorization");
  if (!authHeader) {
    return new Response(JSON.stringify({ error: "Unauthorized" }), {
      status: 401,
      headers: { ...corsHeaders, "Content-Type": "application/json" },
    });
  }

  const token = authHeader.replace("Bearer ", "");
  const client = createClient({
    baseUrl: Deno.env.get("INSFORGE_BASE_URL")!,
    edgeFunctionToken: token,
  });

  const { data: userData } = await client.auth.getCurrentUser();
  if (!userData?.user) {
    return new Response(JSON.stringify({ error: "Unauthorized" }), {
      status: 401,
      headers: { ...corsHeaders, "Content-Type": "application/json" },
    });
  }

  const { template_id, signer_email, signer_first_name, signer_last_name } =
    await req.json();

  const apiKey = Deno.env.get("FIRMA_API_KEY")!;

  const response = await fetch(
    `${FIRMA_API}/signing-requests/create-and-send`,
    {
      method: "POST",
      headers: {
        Authorization: apiKey,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        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 new Response(JSON.stringify({ error: data }), {
      status: response.status,
      headers: { ...corsHeaders, "Content-Type": "application/json" },
    });
  }

  return new Response(
    JSON.stringify({
      signing_request_id: data.id,
      first_signer_id: data.first_signer.id,
      signing_link: data.first_signer.signing_link,
      status: "sent",
    }),
    {
      status: 201,
      headers: { ...corsHeaders, "Content-Type": "application/json" },
    }
  );
}
El endpoint create-and-send crea la solicitud de firma y la envía a los destinatarios de forma atómica. Si necesitas revisar o modificar la solicitud antes de enviarla, usa POST /signing-requests para crear un borrador y luego POST /signing-requests/{id}/send por separado.
La respuesta incluye first_signer.id (el signing_request_user_id) y first_signer.signing_link, que necesitarás si quieres incrustar la experiencia de firma directamente en tu app.

Paso 3: Llama a la función desde la UI de tu app

Invoca la función de cómputo desde tu frontend usando el SDK de InsForge:
import { insforge } from "@/lib/insforge";

const { data, error } = await insforge.functions.invoke(
  "sendSigningRequest",
  {
    body: {
      template_id: "your-template-id",
      signer_email: "alice@example.com",
      signer_first_name: "Alice",
      signer_last_name: "Johnson",
    },
  }
);
También puedes pedirle a tu agente de código que conecte esto: “Cuando el usuario haga clic en Enviar Contrato, llama a la función sendSigningRequest con el ID de la plantilla y los datos del firmante del formulario.”

Integración de webhooks

Para hacer seguimiento de cuándo se firman los documentos, configura un webhook de Firma que apunte a una función de cómputo de InsForge.
  1. Crea una nueva función de cómputo para manejar los eventos de webhook entrantes.
  2. En el panel de Firma, en Configuración -> Webhooks, registra un webhook que apunte a la URL de tu función: https://<your-app>.functions.insforge.app/<function-name>.
  3. Selecciona los eventos que deseas recibir, como signing_request.completed y signing_request.recipient.signed.
import { createClient } from "npm:@insforge/sdk";

export default async function handler(req: Request) {
  const insforge = createClient({
    baseUrl: Deno.env.get("INSFORGE_BASE_URL")!,
    anonKey: Deno.env.get("ANON_KEY")!,
  });

  const payload = await req.json();
  const { type, data } = payload;

  if (type === "signing_request.completed") {
    const signingRequestId = data.signing_request.id;

    await insforge.database
      .from("contracts")
      .update({
        status: "signed",
        signed_at: new Date().toISOString(),
      })
      .eq("firma_signing_request_id", signingRequestId);
  }

  return Response.json({ received: true });
}
Firma envía eventos para todos los cambios de estado clave. Consulta la guía de webhooks para ver la lista completa de tipos de eventos y estructuras de payload.
Para uso en producción, verifica la firma del webhook usando tu secreto de firma de webhook de Firma. Consulta la guía de webhooks para más detalles sobre la verificación de firma HMAC.

Firma incrustada

Para apps donde los firmantes completan documentos directamente en tu UI, Firma ofrece una experiencia de firma incrustable. La respuesta de create-and-send incluye un first_signer.id (el signing_request_user_id) y un first_signer.signing_link listo para usar. Carga la URL del firmante en un iframe dentro de tu app de InsForge:
<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>
Consulta la guía de firma incrustada para instrucciones completas de configuración, incluyendo mejores prácticas de seguridad y manejo de eventos postMessage.

Próximos pasos