Tutorial Rápido
¿Usas Cursor, Claude, u otra herramienta IA para codificación? Conéctala con la documentación de Legalesign para ayuda contextual mientras sigues este tutorial.
En este tutorial completarás las llamadas clave a la API que la mayoría de desarrolladores necesitan en una integración de firma electrónica: subir un documento y enviarlo para ser firmado.
La API de Legalesign es escalable, versátil y probada en producción en los sistemas de nuestros clientes durante muchos años. Puedes usarla para un documento con un solo firmante, o enviar documentos para atestiguamiento o aprobaciones, optimizada para lotes, con formularios y más. Puedes integrar para un propósito específico o insertarla dentro de tu software para tus clientes - ver integraciones.
La API REST realiza la mayoría de funciones y es la forma más fácil de comenzar. Si necesitas más, consulta la interfaz GraphQL. Legalesign es API-first con GraphQL. Puedes usar cualquiera, según prefieras.
Seguiremos estos pasos:
- Crear una cuenta + clave API (ver Obtén verificación para acceso API).
- Confirmar que las credenciales funcionan y obtener tu ID de equipo.
- Subir un documento a través de la app web.
- Enviar ese documento para ser firmado vía API.
- Descargarlo luego de la firma.
- Subir un documento vía API.
La API REST de Legalesign es fácil de usar. La referencia técnica incluye un editor de código. Puedes hacer solicitudes directamente desde la referencia técnica con tu clave API, pero normalmente solo copia y pega en tu código.
Figura 1: El editor de código para la API REST.
Bibliotecas cliente
O para la interfaz GraphQL Node.js
Recomendamos que los desarrolladores trabajen directamente con la API en lugar de los SDKs. Para ayudar, hay un generador de código para copiar y pegar en la especificación técnica, y tu IA puede producir rápidamente ejemplos usando la especificación OpenAPI. ¿Por qué? La API original tiene más funcionalidades que los SDKs, terminarás queriendo conocer los endpoints que usas de todos modos, evitarás sobrecarga de abstracciones y dependencias, y—basado en nuestra experiencia—lo harás más rápido también.
1. Crear una cuenta
Visita registro en legalesign y sigue el proceso para crear una cuenta.
Se te pedirá crear un equipo. Los equipos son las unidades básicas de Legalesign. Todo el procesamiento de documentos ocurre en un equipo. Necesitas referenciar tu equipo en la mayoría de llamadas a la API.
Un 'equipo' o un 'grupo' son lo mismo. En la app web hablamos de 'equipos', pero en el esquema API es un grupo.
Configuración de la API
Ve al Panel de API. Genera tus credenciales API en la sección Clave API.
Tómate un momento para revisar el Portal de Desarrolladores.
Sandbox
En la sección de Entorno, una alerta muestra si estás en modo sandbox o producción.
El modo sandbox aplica un límite de 100 llamadas por hora. No hay restricciones sobre direcciones de email de destinatarios.
Cuando tu integración esté lista: pasa a modo producción.
Crea un segundo equipo. Usa tu primer equipo para dev y otro(s) para prod. Informa a soporte el nombre de tu equipo dev para excluirlo de facturación.
Clave API
En la sección Clave API verás los detalles de tus claves API. Solo se muestra la clave al crearla.
El Portal de Desarrolladores contiene ejemplos para copiar y pegar para probar tu clave.

Webhooks y registros
Agrega webhooks (tus listeners para eventos de Legalesign) y revisa tus registros.

2. Una solicitud GET exitosa
La url raíz siempre es: https://eu-api.legalesign.com/
Comienza con una solicitud GET para confirmar que tus credenciales funcionan. Reemplaza your_api_key con tu clave del Portal de Desarrolladores.
Curl se usa en los ejemplos, y puedes cambiar entre cURL, Node.js, Python, C# y Go usando las pestañas abajo.
- cURL
- Node.js
- Python
- C#
- Go
curl -H "Authorization: Bearer your_api_key" -H "Content-Type: application/json" -X GET https://eu-api.legalesign.com/api/v1/group/
import fetch from 'node-fetch';
async function getGroups() {
const response = await fetch('https://eu-api.legalesign.com/api/v1/group/', {
method: 'GET',
headers: {
'Authorization': 'Bearer your_api_key',
'Content-Type': 'application/json',
},
});
if (!response.ok) {
throw new Error(`Request failed with status ${response.status}`);
}
const data = await response.json();
console.log(data);
}
getGroups().catch((error) => {
console.error(error);
process.exit(1);
});
import requests
headers = {
"Authorization": "Bearer your_api_key",
"Content-Type": "application/json",
}
response = requests.get(
"https://eu-api.legalesign.com/api/v1/group/",
headers=headers,
timeout=30,
)
response.raise_for_status()
print(response.json())
using System;
using System.Net.Http;
using System.Threading.Tasks;
public class Program
{
public static async Task Main()
{
using var client = new HttpClient();
using var request = new HttpRequestMessage(
HttpMethod.Get,
"https://eu-api.legalesign.com/api/v1/group/"
);
request.Headers.TryAddWithoutValidation("Authorization", "Bearer your_api_key");
request.Headers.TryAddWithoutValidation("Content-Type", "application/json");
using var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
var body = await response.Content.ReadAsStringAsync();
Console.WriteLine(body);
}
}
package main
import (
"fmt"
"io"
"log"
"net/http"
)
func main() {
req, err := http.NewRequest(http.MethodGet, "https://eu-api.legalesign.com/api/v1/group/", nil)
if err != nil {
log.Fatal(err)
}
req.Header.Set("Authorization", "Bearer your_api_key")
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
if resp.StatusCode >= 400 {
log.Fatalf("request failed: %s", resp.Status)
}
body, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(body))
}
Documentación API: Referencia GET group.
Al ejecutar la consulta anterior, verás tus grupos devueltos en JSON. Éxito. 👏
Los datos de respuesta contienen el 'resource uri' para tu grupo y se ve como /api/v1/group/:groupId/. Toma nota de esto, lo necesitarás para la mayoría de llamadas a la API.
Un resource uri siempre tendrá el mismo formato. Para un PDF sería '/api/v1/templatepdf/:pdfId/', para un documento enviado será '/api/v1/document/:documentId/'. Observa que todos los URIs terminan con una barra inclinada (/). Eso también es cierto para las URLs de tus llamadas API, siempre termínalas con una barra.
Si la solicitud GET falló verifica que:
- el encabezado Authorization esté correctamente formateado (comienza con
Bearer), - tengas un encabezado Content-Type para application/json, y
- tu url termine con una barra.
Consulta también solución de problemas.
3. Subir un documento vía la app web
Para empezar, subiremos un documento a través de la app web y lo enviaremos vía API. Cubriremos cómo subir un documento vía API más adelante.
Ve a la app web y sube tu documento. Añade un rol de firmante único y arrastra un campo de firma. La página del editor indicará si el documento es 'válido' (un ejemplo de 'inválido' podría ser si agregas un rol de firmante sin un campo de firma relacionado).
En el editor de formulario, copia el largo ID alfanumérico de la URL, decodifícalo en base64 y descarta las primeras 3 letras (que deberían ser 'tpl'). Lo restante es un UUID que es tu ID. Más sobre IDs web y API.
El ID REST API para este documento es /api/v1/templatepdf/UUID/.
Nuestra nomenclatura es que un documento subido es una 'plantilla' y cuando envías uno creas un 'documento'.
Si quieres archivar una plantilla cuando se envíe el documento configura 'archive_upon_send' como atributo en la solicitud de subida. Si quieres que la plantilla nunca aparezca y se borre después de enviar, ponle el título '[deleted]' - nuestros sistemas de limpieza lo detectarán y borrarán después de uno o dos días. También puedes establecer tiempos de retención cortos a nivel de grupo - más información.
4. Enviar un documento para firma
Ahora enviamos esto vía API. Usa las pestañas abajo para obtener la solicitud en tu idioma preferido.
- cURL
- Node.js
- Python
- C#
- Go
curl -H "Authorization: Bearer your_api_key" -H "Content-Type: application/json" -X POST --data '{ "group": "/api/v1/group/[:groupId]/", "name": "Name of doc", "templatepdf": "/api/v1/templatepdf/UUID/", "signers": [{"firstname": "Joe", "lastname": "Bloggs", "email": "[your@email.com]", "order": 0 }], "do_email": true }' https://eu-api.legalesign.com/api/v1/document/
import fetch from 'node-fetch';
const payload = {
group: '/api/v1/group/[:groupId]/',
name: 'Name of doc',
templatepdf: '/api/v1/templatepdf/UUID/',
signers: [
{
firstname: 'Joe',
lastname: 'Bloggs',
email: '[your@email.com]',
order: 0,
},
],
do_email: true,
};
async function sendDocument() {
const response = await fetch('https://eu-api.legalesign.com/api/v1/document/', {
method: 'POST',
headers: {
'Authorization': 'Bearer your_api_key',
'Content-Type': 'application/json',
},
body: JSON.stringify(payload),
});
if (response.status !== 201) {
const errorBody = await response.text();
throw new Error(`Request failed with status ${response.status}: ${errorBody}`);
}
console.log('Document sent successfully');
const location = response.headers.get('location');
if (location) {
console.log(`Location: ${location}`);
}
}
sendDocument().catch((error) => {
console.error(error);
process.exit(1);
});
import requests
payload = {
"group": "/api/v1/group/[:groupId]/",
"name": "Name of doc",
"templatepdf": "/api/v1/templatepdf/UUID/",
"signers": [
{
"firstname": "Joe",
"lastname": "Bloggs",
"email": "[your@email.com]",
"order": 0,
}
],
"do_email": true,
}
headers = {
"Authorization": "Bearer your_api_key",
"Content-Type": "application/json",
}
response = requests.post(
"https://eu-api.legalesign.com/api/v1/document/",
json=payload,
headers=headers,
timeout=30,
)
response.raise_for_status()
print("Document sent successfully")
print("Location:", response.headers.get("Location"))
using System;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
public class Program
{
public static async Task Main()
{
var payload = new
{
group = "/api/v1/group/[:groupId]/",
name = "Name of doc",
templatepdf = "/api/v1/templatepdf/UUID/",
signers = new[]
{
new
{
firstname = "Joe",
lastname = "Bloggs",
email = "[your@email.com]",
order = 0,
},
},
do_email = true,
};
using var client = new HttpClient();
using var request = new HttpRequestMessage(
HttpMethod.Post,
"https://eu-api.legalesign.com/api/v1/document/"
);
request.Headers.TryAddWithoutValidation("Authorization", "Bearer your_api_key");
var json = JsonSerializer.Serialize(payload);
request.Content = new StringContent(json, Encoding.UTF8, "application/json");
using var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
Console.WriteLine("Document sent successfully");
if (response.Headers.Location is not null)
{
Console.WriteLine($"Location: {response.Headers.Location}");
}
}
}
package main
import (
"bytes"
"encoding/json"
"fmt"
"log"
"net/http"
)
func main() {
payload := map[string]any{
"group": "/api/v1/group/[:groupId]/",
"name": "Name of doc",
"templatepdf": "/api/v1/templatepdf/UUID/",
"signers": []map[string]any{
{
"firstname": "Joe",
"lastname": "Bloggs",
"email": "[your@email.com]",
"order": 0,
},
},
"do_email": true,
}
body, err := json.Marshal(payload)
if err != nil {
log.Fatal(err)
}
req, err := http.NewRequest(
http.MethodPost,
"https://eu-api.legalesign.com/api/v1/document/",
bytes.NewReader(body),
)
if err != nil {
log.Fatal(err)
}
req.Header.Set("Authorization", "Bearer your_api_key")
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusCreated {
log.Fatalf("unexpected status: %s", resp.Status)
}
fmt.Println("Document sent successfully")
fmt.Println("Location:", resp.Header.Get("Location"))
}
Actualiza todo dentro de los corchetes. Referencia API para enviar un documento.
Cuando visites la documentación de referencia para enviar un documento mira bien todos los posibles atributos. Verás muchos que te ayudarán con la practicidad de una integración: etiquetas para tus propias referencias e IDs (que vuelven en webhooks), un redireccionamiento para firmantes, poner texto personalizado en el pdf y más.
Una llamada exitosa devuelve código de estado 201. ✨
Obtener el nuevo ID del documento enviado
La parte importante de la respuesta es el encabezado location. Este contiene el nuevo ID de documento.
Usa atributos 'tag' de documento y añade tus propias referencias para facilitar la vinculación con tu base de datos.
El encabezado location se verá como /api/v1/status/:documentId/.
La URI 'status' devuelve un conjunto corto (y rápido de consultar) de atributos del documento.
Para pedir todo de un documento usa /api/v1/document/:documentId/.
Si una solicitud no tiene éxito el CUERPO de la respuesta generalmente contiene información de error. Si no obtienes un estado de éxito, revisa el CUERPO para texto explicativo. Ver también solución de problemas.
Más sobre la llamada API Send Document.
5. Descargar el documento firmado
Con el ID del documento enviado que recibiste arriba, haz una solicitud de descarga PDF en el lenguaje de tu elección:
- cURL
- Node.js
- Python
- C#
- Go
curl -H "Authorization: Bearer your_api_key" -o download.pdf -X GET https://eu-api.legalesign.com/api/v1/pdf/:documentId/
import { writeFile } from 'node:fs/promises';
import fetch from 'node-fetch';
async function downloadPdf() {
const response = await fetch('https://eu-api.legalesign.com/api/v1/pdf/:documentId/', {
method: 'GET',
headers: {
'Authorization': 'Bearer your_api_key',
},
});
if (!response.ok) {
throw new Error(`Request failed with status ${response.status}`);
}
const buffer = await response.arrayBuffer();
await writeFile('download.pdf', Buffer.from(buffer));
console.log('Saved download.pdf');
}
downloadPdf().catch((error) => {
console.error(error);
process.exit(1);
});
import requests
headers = {"Authorization": "Bearer your_api_key"}
response = requests.get(
"https://eu-api.legalesign.com/api/v1/pdf/:documentId/",
headers=headers,
stream=True,
timeout=30,
)
response.raise_for_status()
with open("download.pdf", "wb") as file:
for chunk in response.iter_content(chunk_size=8192):
file.write(chunk)
using System;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
public class Program
{
public static async Task Main()
{
using var client = new HttpClient();
using var request = new HttpRequestMessage(
HttpMethod.Get,
"https://eu-api.legalesign.com/api/v1/pdf/:documentId/"
);
request.Headers.TryAddWithoutValidation("Authorization", "Bearer your_api_key");
using var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
var bytes = await response.Content.ReadAsByteArrayAsync();
await File.WriteAllBytesAsync("download.pdf", bytes);
Console.WriteLine("Saved download.pdf");
}
}
package main
import (
"io"
"log"
"net/http"
"os"
)
func main() {
req, err := http.NewRequest(
http.MethodGet,
"https://eu-api.legalesign.com/api/v1/pdf/:documentId/",
nil,
)
if err != nil {
log.Fatal(err)
}
req.Header.Set("Authorization", "Bearer your_api_key")
resp, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
if resp.StatusCode >= 400 {
log.Fatalf("request failed: %s", resp.Status)
}
file, err := os.Create("download.pdf")
if err != nil {
log.Fatal(err)
}
defer file.Close()
if _, err := io.Copy(file, resp.Body); err != nil {
log.Fatal(err)
}
log.Println("Saved download.pdf")
}
Referencia API para descarga PDF.
El binario PDF está en el cuerpo de la respuesta. El comando curl '-o' pone el CUERPO de la respuesta directamente en un archivo.
Muchas librerías REST o HTTP tratan los objetos de respuesta HTTP como archivos, en cuyo caso simplemente guarda tu objeto de respuesta como un archivo normal.
Usa webhooks para ser notificado de un evento de firma y luego descarga el documento. Consulta webhooks.
6. Subir un documento vía API
Haz clic aquí para descargar un PDF con etiquetas de texto de ejemplo, más información sobre campos de formulario PDF a seguir.
Para esta llamada, convierte tu PDF en una cadena codificada en base64. Esto no se hace adecuadamente dentro del generador de código de la documentación. Copia este pseudocódigo y la IA lo convertirá a tu lenguaje preferido:
$data = (
'group': '/api/v1/group/:groupId/',
'title': 'title of pdf',
'pdf_file': base64encode(open('/path/to/file','rb')),
'process_tags': true
)
$headers = (
'Authorization': 'Bearer your_api_key',
'Content-Type': 'application/json'
)
response = httplibrary.post('https://eu-api.legalesign.com/api/v1/templatepdf/', jsonEncode($data), $headers)
assert response.status == 201
pdfId = response.headers['location']
Referencia API para subir PDF.
Una respuesta POST exitosa devolverá el estado 201 y el nuevo ID estará en el encabezado location de la respuesta.
Tu recurso pdf URI se verá como /api/v1/templatepdf/:pdfId/.
Otros formatos de archivo
Word, HTML, texto plano, XLSX y archivos de imagen son soportados. Súbelos usando el subidor de archivos GraphQL, que detecta el formato automáticamente y convierte a PDF. Recupera el ID y envíalo vía REST API normalmente. También consulta entendiendo REST y GraphQL IDs. Las etiquetas de texto serán detectadas como siempre.
Envía el nuevo PDF
Regresa al código que usaste para enviar tu primer documento, y reemplaza el valor de templatepdf.
Realiza la solicitud otra vez y listo, enviaste tu PDF para firmar.
Antes de empezar a codificar sin embargo, lee más para saber sobre campos PDF.
¿Qué pasa con los campos PDF?
¿Cómo sabe Legalesign dónde debe firmar la persona en el PDF, o qué secciones cambiar al enviarlo? La respuesta es que nuestro PDF estaba pre-preparado con etiquetas: ponemos una etiqueta de texto Legalesign dentro del PDF y configuramos 'process_tags' como true en la solicitud de subida del PDF.
Descarga un PDF de ejemplo con etiquetas de texto.
Las etiquetas de texto son texto especialmente formateado para poner en un PDF. Legalesign analizará el texto de tu archivo, reemplazando las etiquetas con campos de firma y formulario. Para un firmante solo necesitas añadir: <<t=signature>>. Legalesign lo identificará y colocará la firma ahí. Aprende sobre etiquetas de texto.
Otros métodos para localizar tus campos se detallan abajo, pero con etiquetas de texto obtienes toda la capacidad del sistema de formularios Legalesign. Usa la app web para probar tus etiquetas. Contacta a soporte para ayuda y ejemplos.
Aquí hay 4 formas más de configurar campos:
1. Versión más fácil/rápida. Configura tu PDF usando la app web de Legalesign.
Después de subir un PDF irás a la interfaz del editor donde puedes arrastrar y soltar campos de formulario.
Arrastra y suelta una firma, luego nota el ID codificado en la dirección web. Esto se verá algo como 'dHBsMTRlZTQ0ZWUtZGE0Ni0xMWVmLTllZmUtMDI5ZGQ0ODkzZGRk'.
Decodifica en base64 este ID y verás que es un UUID prefijado con 'tpl'. La parte UUID (quita 'tpl') es tu pdfID. Más sobre IDs Legalesign.
Tu recurso API URI para PDF será - /api/v1/templatepdf/:pdfId/.
Pon eso en el atributo 'templatepdf' de la llamada para enviar documento.
Si planeas enviar este PDF más de una vez, asegúrate que 'Auto archive' esté desactivado. Ver cómo
2. Usa coordenadas x/y para campos.
La forma más sencilla de empezar con coordenadas x/y es configurar un PDF en la app web y luego hacer una consulta API para esos campos (GET PDF Fields - /api/v1/templatepdf/:pdfId/fields/).
El objeto JSON que recibes es exactamente el mismo esquema JSON que necesitas para crear campos también.
Úsalo como plantilla. Modifica cualquier valor y envíalo mediante POST al mismo endpoint (ajustando el ID del PDF según corresponda). Crear endpoint de campos PDF.
3. Inserta nuestra página de edición PDF. ¡NUEVO!
Usa nuestro componente editor para incrustar nuestro editor PDF directamente en tu propia app. Aprende más sobre el componente editor de documentos.
4. Campos de formulario PDF ¡NUEVO!
Si tu PDF contiene campos de formulario PDF normales, Legalesign puede importarlos automáticamente.
¡Feliz codificación!
En este tutorial adquiriste credenciales API, consultaste con éxito tus grupos, enviaste un documento para firmar usando PDF y descargaste un documento firmado.
Estamos aquí para ayudarte, contacta a soporte para cualquier asistencia.
Revisa las opciones de envío disponibles para ti. Tómate un momento para leer todos los atributos en el endpoint crear documento, especialmente 'signers', 'pdftext' y 'signertext'. Crear un documento para firma.