Tutorial de inicio rápido
¿Usas Cursor, Claude u otra herramienta de codificación AI? Conéctala a la documentación de Legalesign para recibir ayuda contextual mientras sigues este tutorial.
En este tutorial completarás las llamadas API clave que la mayoría de los desarrolladores necesita para una integración de firma electrónica: subir un documento y enviarlo para firma.
La API de Legalesign es escalable, versátil y ha sido probada en producción en los sistemas de nuestros clientes durante muchos años. Puedes usarla para un documento simple con un firmante, o enviar documentos para testigos o aprobaciones, optimizados para lotes, con formularios y más. Puedes integrarla con un solo propósito o incrustarla dentro de tu software para tus clientes; consulta integraciones.
La API REST realiza la mayoría de las funciones y es la forma más fácil de empezar. 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 (consulta Obtén verificado para acceso a la API).
- Confirmar que las credenciales funcionan y obtener tu ID de equipo.
- Subir un documento a través de la aplicación web.
- Enviar ese documento para firmar vía API.
- Descargarlo después de la firma.
- Subir un documento mediante la 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 si no, solo copia y pega directamente en tu código.
Figura 1: El editor de código de la API REST.
Bibliotecas cliente
O para la interfaz GraphQL Node.js
Recomendamos que los desarrolladores trabajen directamente con la API en lugar de con los SDKs. Para ayudar, hay un generador de código de copiar y pegar en la especificación técnica, y tu AI puede producir ejemplos rápidamente usando la especificación OpenAPI. ¿Por qué? La API fuente tiene más funcionalidades que los SDKs, de todas formas querrás conocer los endpoints que usas, evitarás la sobrecarga de abstracciones y dependencias, y según nuestra experiencia, también se hace más rápido.
1. Crear una cuenta
Ve a registro en legalesign y sigue el proceso para crear una cuenta.
Se te pedirá crear un equipo. Los equipos son los bloques constructores de Legalesign. Todo el procesamiento de documentos ocurre dentro de un equipo. Debes referirte a tu equipo en la mayoría de las llamadas API.
Un 'equipo' o un 'grupo' es lo mismo. En la aplicación web hablamos de 'equipos', pero en el esquema API es un grupo.
Configuración de API
Accede al Panel de API. Genera tus credenciales API en la sección de 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 en las direcciones de correo electrónico de los destinatarios.
Cuando tu integración esté lista: pasa a modo producción.
Crea un segundo equipo. Usa tu primer equipo para desarrollo y otros equipos para producción. Informa a soporte el nombre de tu equipo de desarrollo para excluirlo de la facturación.
Clave API
En la sección de clave API verás los detalles de tus claves API. Solo verás la clave propiamente dicha cuando la crees.
La sección de inicio rápido 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: GET group referencia API.
Cuando ejecutes la consulta anterior, verás que se devuelven tus grupos en formato JSON. Éxito. 👏
Los datos de respuesta contienen el 'resource uri' para tu grupo y se ven así /api/v1/group/:groupId/. Toma nota de esto, lo necesitarás para la mayoría de las llamadas 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 todas las URIs terminan con una barra (/). Eso también es cierto para las URLs de tus llamadas API, siempre termínalas con una barra.
Si la solicitud GET falló, entonces verifica que:
- tu encabezado Authorization esté formateado correctamente (comience con
Bearer), - tienes un encabezado Content-Type para application/json, y
- tu URL termina con una barra (/).
Consulta también resolución de problemas.
3. Subir un documento a través de la aplicación web
Para comenzar, subiremos un documento a través de la aplicación web y lo enviaremos mediante la API. Más adelante cubriremos cómo subir un documento mediante la API.
Ve a la aplicación 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 formularios, copia el largo ID alfanumérico de la URL, decodifícalo en base64 y descarta las primeras 3 letras (que deberían ser 'tpl'). El resto es un UUID que es tu ID.
En el lenguaje de la API REST, el resource uri para este documento es /api/v1/templatepdf/UUID/.
Aprende más sobre IDs web y API.
Nuestra nomenclatura es que un documento subido es una 'plantilla' y cuando envías uno creas un 'documento'.
Si quieres archivar una plantilla cuando el documento es enviado, establece 'archive_upon_send' como un atributo en la solicitud de subida. Si quieres que la plantilla nunca aparezca y eliminarla tras el envío, dale el título '[deleted]'; nuestros sistemas de limpieza la detectarán y eliminarán después de uno o dos días. También puedes definir tiempos de retención cortos a nivel de grupo - aprende más.
4. Enviar un documento para firma
Ahora enviaremos esto mediante la API. Usa las pestañas abajo para obtener la solicitud en tu lenguaje 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 todos los corchetes. Referencia API para enviar un documento.
Cuando visites la documentación de referencia para enviar un documento echa un buen vistazo a todos los posibles atributos. Verás muchos que ayudarán con las particularidades de una integración: etiquetas para tus propias referencias e IDs (que te devuelven en los webhooks), redirección para firmantes, texto personalizado en el PDF y más.
Una llamada exitosa devolverá código de estado 201. ✨
Obtener el nuevo ID del documento enviado
La parte importante de la respuesta es el encabezado location. Contiene tu nuevo ID de documento.
Usa atributos 'tag' del documento y añade tus propias referencias para facilitar la relación con tu propia base de datos.
El encabezado location se verá así: /api/v1/status/:documentId/.
La URI 'status' devuelve un conjunto corto (y rápido de consultar) de atributos del documento.
Para solicitar todo de un documento usa /api/v1/document/:documentId/.
Si una solicitud no tiene éxito, el CUERPO de la respuesta usualmente contiene información de error. Si no obtienes un estado de éxito, revisa el CUERPO para texto explicativo. Consulta también resolución de problemas.
Aprende más sobre la llamada API Send Document.
5. Descargar el documento firmado
Con el ID del documento enviado que recibiste arriba, realiza una solicitud de descarga PDF en el lenguaje de tu preferencia:
- 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 de 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 bibliotecas REST o HTTP tratan los objetos de respuesta HTTP como si fueran archivos, en cuyo caso simplemente guarda tu objeto de respuesta como un archivo normal.
Usa webhooks para recibir notificaciones de un evento de firma y luego descargar el documento. Consulta webhooks.
6. Subir un PDF
Haz clic aquí para descargar un PDF de ejemplo con etiquetas de texto, más sobre campos de formulario PDF a continuación.
Para esta llamada, convierte tu PDF en una cadena codificada en base64. Esto no se hace correctamente en el generador de código de la documentación. En su lugar, copia este pseudocódigo y tu AI amigable 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']
Como de costumbre, una respuesta POST exitosa devolverá estado '201' y el nuevo ID estará en el encabezado 'location' de la respuesta.
assert response.status == 201
pdfId = response.headers['location']
El resource URI de tu PDF se verá como /api/v1/templatepdf/:pdfId/.
Enviar el nuevo PDF
Vuelve al código que usaste para enviar tu primer documento y reemplaza el valor de templatepdf.
Realiza la solicitud de nuevo y eso es todo, enviaste tu PDF para firmar.
Antes de empezar a programar, sin embargo, sigue leyendo para aprender más sobre los campos PDF.
¿Qué hay de los campos PDF?
¿Cómo sabe Legalesign dónde debe firmar la persona en el PDF, o las secciones a modificar al enviar? La respuesta es que nuestro PDF fue preparado con etiquetas: pusimos una etiqueta de texto de Legalesign dentro del PDF y configuramos 'process_tags' a 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 colocar en un PDF. Legalesign analizará el texto en tu archivo, reemplazando las etiquetas con campos de firma y formulario. Para un firmante solo necesitas añadir: <<t=signature>>. Legalesign lo identificará y ubicará la firma allí. Aprende sobre etiquetas de texto.
Las etiquetas de texto tienen una curva de aprendizaje y requieren prueba y error. Otros métodos se describen a continuación, pero obtienes toda la capacidad del sistema de formularios de Legalesign con ellas. Usa la aplicación web para probar las etiquetas. Contacta a soporte para asistencia y ejemplos.
Aquí hay 4 formas más de configurar campos:
1. La versión más fácil/rápida. Configura tu PDF usando la aplicación 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 anota el ID codificado en la dirección web. Esto se verá algo como 'dHBsMTRlZTQ0ZWUtZGE0Ni0xMWVmLTllZmUtMDI5ZGQ0ODkzZGRk'.
Decodifica este ID en base64 y verás que es un UUID con el prefijo 'tpl'. La parte UUID (quita 'tpl') es tu pdfID. Aprende más sobre los IDs de Legalesign.
Tu URI recurso PDF API será - /api/v1/templatepdf/:pdfId/.
Pon eso en el atributo 'templatepdf' de la llamada enviar documento.
Si planeas enviar este PDF más de una vez, asegúrate de que 'Archivo automático' esté desactivado. Consulta cómo
2. Usa coordenadas x/y para campos.
La forma más sencilla de comenzar con coordenadas x/y es configurar un PDF en la aplicación web y luego consultar esos campos vía API (GET PDF Fields - /api/v1/templatepdf/:pdfId/fields/).
El objeto JSON que recibes es el mismo esquema JSON exacto que necesitas para crear campos también.
Úsalo como plantilla. Modifica los valores que necesites y envíalo con POST al mismo endpoint (ajustando el ID del PDF según corresponda). Endpoint para crear campo PDF.
3. Incrusta nuestra página de edición de PDF. ¡NUEVO!
Usa nuestro componente editor para incrustar nuestro editor PDF directamente en tu propia aplicación. 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 de forma automática.
¡Feliz codificación!
En este tutorial obtuviste credenciales API, consultaste con éxito tus grupos, enviaste un documento para firmar usando HTML y PDF, y descargaste un documento firmado.
¡Feliz codificación! Estamos aquí para ayudar, contacta a soporte para cualquier asistencia.
Genial, llegaste al final - gracias por leer esto. Nuestra última petición y consejo, basado en años de experiencia de desarrolladores que integran esta API, es que tomes un momento para leer todos los atributos del endpoint crear documento (y hagas clic para ver qué contienen 'signers', 'pdftext' y 'signertext*) - es la llamada más importante en tu integración. Crear un documento para firma.