Desarrolladores
API de tableros
La API de tableros te permite listar los tableros de un espacio de trabajo, leer sus listas y tarjetas, crear tarjetas nuevas, cambiarlas o moverlas de lista, y borrarlas. Es la forma más rápida de convertir lo que pasa fuera (un formulario, un correo, una alerta) en tarjetas con las que tu equipo pueda trabajar.
Antes de empezar
- URL base:
https://app.tylode.com/api/v1 - Manda tu token en la cabecera
Authorization: Bearer tylode_pat_xxx. Los tokens de acceso personal necesitan el plan Pro. Consulta Autenticación. - Obtén el ID del espacio con
GET /api/v1/workspaceso en la app, en Ajustes → Workspace → Datos del espacio → ID del espacio → Copiar. - Cada petición actúa en tu nombre, así que ves los tableros que ves en la app. Los errores que puede dar cualquier endpoint (
401,403,429) se explican en Errores y convenciones. - Los ejemplos en JavaScript usan la función
tylode()de la API de páginas.
Endpoints
| Método | Ruta | Qué hace | Permiso (scope) |
|---|---|---|---|
| GET | /api/v1/boards | Lista los tableros de un espacio | boards:read |
| GET | /api/v1/boards/:id/lists | Lista las listas (columnas) de un tablero | boards:read |
| GET | /api/v1/boards/:id/cards | Lista las tarjetas de un tablero | boards:read |
| POST | /api/v1/boards/:id/cards | Crea una tarjeta | boards:write |
| PATCH | /api/v1/boards/:id/cards/:cardId | Cambia o mueve una tarjeta | boards:write |
| DELETE | /api/v1/boards/:id/cards/:cardId | Borra una tarjeta | boards:delete |
| DELETE | /api/v1/boards/:id | Mueve un tablero a la papelera | boards:delete |
Los permisos solo cuentan para las aplicaciones OAuth.
Listar tableros
GET /api/v1/boards
Devuelve los tableros de un espacio, del más antiguo al más reciente, con su id, workspace_id y name. Los que están en la papelera no aparecen.
Permiso (scope): boards:read
| Parámetro | Dónde | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
workspace_id | query | string | Sí | El espacio que quieres listar. |
curl "https://app.tylode.com/api/v1/boards?workspace_id=WORKSPACE_ID" \
-H "Authorization: Bearer tylode_pat_xxx"const boards = await tylode(`/boards?workspace_id=${WORKSPACE_ID}`);
const leads = boards.find((b) => b.name === "Leads");Respuesta 200
{
"data": [
{
"id": "1a4d7f0c-3e6b-4c9e-a2f5-8b1d4e7a0c63",
"workspace_id": "7c1e2a4b-3f5d-4e8a-9b21-6d0f5c8e1a37",
"name": "Product"
},
{
"id": "5e8b1d4f-7a0c-4e3b-9d6f-2c5e8b1a4d70",
"workspace_id": "7c1e2a4b-3f5d-4e8a-9b21-6d0f5c8e1a37",
"name": "Leads"
}
]
}Errores
| Estado | Cuándo |
|---|---|
400 | Falta workspace_id. |
Listar listas
GET /api/v1/boards/:id/lists
Devuelve las listas (columnas) de un tablero en el orden en que se ven, de izquierda a derecha, con id, board_id, name y position. De aquí sale el list_id para crear una tarjeta en una lista concreta o para moverla a otra.
Permiso (scope): boards:read
| Parámetro | Dónde | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string | Sí | ID del tablero. |
curl https://app.tylode.com/api/v1/boards/BOARD_ID/lists \
-H "Authorization: Bearer tylode_pat_xxx"const lists = await tylode(`/boards/${BOARD_ID}/lists`);
const done = lists.find((l) => l.name === "Done");Respuesta 200
{
"data": [
{
"id": "9b2e5c8f-1d4a-4b7e-a0c3-6f9d2b5e8a17",
"board_id": "1a4d7f0c-3e6b-4c9e-a2f5-8b1d4e7a0c63",
"name": "To do",
"position": 0
},
{
"id": "0c3f6a9d-2e5b-4c8f-b1d4-7a0e3c6f9b28",
"board_id": "1a4d7f0c-3e6b-4c9e-a2f5-8b1d4e7a0c63",
"name": "Doing",
"position": 1
},
{
"id": "3e6b9d2f-5a8c-4e1b-a4d7-0b3e6c9f2a51",
"board_id": "1a4d7f0c-3e6b-4c9e-a2f5-8b1d4e7a0c63",
"name": "Done",
"position": 2
}
]
}Si el tablero no existe o no puedes verlo, recibes una lista vacía, no un error.
Errores
| Estado | Cuándo |
|---|---|
400 | El ID del tablero no es válido. |
Listar tarjetas
GET /api/v1/boards/:id/cards
Devuelve todas las tarjetas de un tablero, ordenadas por position.
Permiso (scope): boards:read
| Parámetro | Dónde | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string | Sí | ID del tablero. |
Cada tarjeta trae:
| Campo | Tipo | Descripción |
|---|---|---|
id | string | ID de la tarjeta. |
board_id | string | Tablero en el que está. |
list_id | string | Lista (columna) en la que está. |
title | string | Título de la tarjeta. |
description | string | Descripción (puede ir vacía). |
due_date | string o null | Fecha de vencimiento en formato YYYY-MM-DD. |
position | number | Orden dentro de su lista. |
Cada tarjeta trae el list_id de su lista, no su nombre. Para saber cómo se llama cada lista, usa Listar listas.
curl https://app.tylode.com/api/v1/boards/BOARD_ID/cards \
-H "Authorization: Bearer tylode_pat_xxx"const cards = await tylode(`/boards/${BOARD_ID}/cards`);
const today = new Date().toLocaleDateString("sv-SE"); // YYYY-MM-DD
const dueToday = cards.filter((c) => c.due_date === today);Respuesta 200
{
"data": [
{
"id": "c4f7a0d3-6b9e-4c2f-8a5d-1e4b7c0f3a96",
"board_id": "1a4d7f0c-3e6b-4c9e-a2f5-8b1d4e7a0c63",
"list_id": "9b2e5c8f-1d4a-4b7e-a0c3-6f9d2b5e8a17",
"title": "Fix the signup email",
"description": "The link points to the old domain.",
"due_date": "2026-09-25",
"position": 0
},
{
"id": "d5a8b1e4-7c0f-4d3a-9b6e-2f5c8d1a4b07",
"board_id": "1a4d7f0c-3e6b-4c9e-a2f5-8b1d4e7a0c63",
"list_id": "0c3f6a9d-2e5b-4c8f-b1d4-7a0e3c6f9b28",
"title": "Write release notes",
"description": "",
"due_date": null,
"position": 1
}
]
}Si el tablero no existe o no puedes verlo, recibes una lista vacía, no un error.
Crear una tarjeta
POST /api/v1/boards/:id/cards
Crea una tarjeta en un tablero. Si no dices en qué lista, va a la primera lista del tablero.
Permiso (scope): boards:write
| Parámetro | Dónde | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string | Sí | ID del tablero. |
title | body | string | Sí | Título de la tarjeta. |
description | body | string | No | Descripción. Por defecto, vacía. |
list_id | body | string | No | Lista en la que se crea. Por defecto, la primera lista del tablero (la de más a la izquierda). |
Al crearla no puedes poner fechas, responsables ni otros campos: la tarjeta se crea con título, descripción y lista. Las fechas se ponen después con Cambiar o mover una tarjeta; los responsables y lo demás, en la app (mira Tableros).
curl -X POST https://app.tylode.com/api/v1/boards/BOARD_ID/cards \
-H "Authorization: Bearer tylode_pat_xxx" \
-H "Content-Type: application/json" \
-d '{
"title": "Call back Laura (Northwind)",
"description": "Wants a demo for 12 people. Phone: +34 600 000 000"
}'const card = await tylode(`/boards/${BOARD_ID}/cards`, {
method: "POST",
body: {
title: "Call back Laura (Northwind)",
description: "Wants a demo for 12 people. Phone: +34 600 000 000",
},
});
console.log(card.id, card.list_id);Respuesta 201
{
"data": {
"id": "e6b9c2f5-8d1a-4e4b-a7c0-3a6d9e2b5c18",
"board_id": "5e8b1d4f-7a0c-4e3b-9d6f-2c5e8b1a4d70",
"list_id": "2d5a8c1f-4e7b-4a0d-9c3e-6b9f2c5a8d41",
"title": "Call back Laura (Northwind)",
"description": "Wants a demo for 12 people. Phone: +34 600 000 000",
"due_date": null,
"position": 0
}
}Errores
| Estado | Cuándo |
|---|---|
400 | Falta title. |
400 | No has mandado list_id y el tablero todavía no tiene listas. Crea una lista en la app primero. |
400 | No se ha podido crear la tarjeta (por ejemplo, el list_id no es válido o no puedes editar ese tablero). |
Cambiar o mover una tarjeta
PATCH /api/v1/boards/:id/cards/:cardId
Cambia el título, la descripción o las fechas de una tarjeta, o la mueve a otra lista del mismo tablero. Solo cambia lo que mandas; el resto de la tarjeta se queda como está.
Permiso (scope): boards:write
| Parámetro | Dónde | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string | Sí | ID del tablero. |
cardId | path | string | Sí | ID de la tarjeta. |
title | body | string | No | Título nuevo. No puede ir en blanco. |
description | body | string | No | Descripción nueva. Con "" se queda vacía. |
due_date | body | string o null | No | Fecha de vencimiento en formato YYYY-MM-DD, o null para quitarla. |
start_date | body | string o null | No | Fecha de inicio en formato YYYY-MM-DD, o null para quitarla. |
list_id | body | string | No | Lista a la que se mueve, de Listar listas. Tiene que ser del mismo tablero. La tarjeta va al final de esa lista. |
Manda al menos uno de los campos del cuerpo.
curl -X PATCH https://app.tylode.com/api/v1/boards/BOARD_ID/cards/CARD_ID \
-H "Authorization: Bearer tylode_pat_xxx" \
-H "Content-Type: application/json" \
-d '{ "list_id": "LIST_ID", "due_date": "2026-10-16" }'// Mueve una tarjeta a la lista "Done"
const lists = await tylode(`/boards/${BOARD_ID}/lists`);
const done = lists.find((l) => l.name === "Done");
const card = await tylode(`/boards/${BOARD_ID}/cards/${CARD_ID}`, {
method: "PATCH",
body: { list_id: done.id },
});Respuesta 200
La tarjeta tal como queda. Además de los campos de Listar tarjetas, trae start_date.
{
"data": {
"id": "c4f7a0d3-6b9e-4c2f-8a5d-1e4b7c0f3a96",
"board_id": "1a4d7f0c-3e6b-4c9e-a2f5-8b1d4e7a0c63",
"list_id": "3e6b9d2f-5a8c-4e1b-a4d7-0b3e6c9f2a51",
"title": "Fix the signup email",
"description": "The link points to the old domain.",
"start_date": null,
"due_date": "2026-10-16",
"position": 4
}
}Errores
| Estado | Cuándo |
|---|---|
400 | El ID del tablero o de la tarjeta no es válido. |
400 | No has mandado nada que cambiar, o title va en blanco. |
400 | due_date o start_date no tienen el formato YYYY-MM-DD ni son null. |
400 | list_id no es un ID válido o no es una lista de este tablero. |
404 | La tarjeta no existe, no es de ese tablero o no puedes cambiarla. |
Borrar una tarjeta
DELETE /api/v1/boards/:id/cards/:cardId
Borra una tarjeta de un tablero. Las tarjetas no tienen papelera: no se puede recuperar.
Permiso (scope): boards:delete
| Parámetro | Dónde | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string | Sí | ID del tablero. |
cardId | path | string | Sí | ID de la tarjeta. |
curl -X DELETE https://app.tylode.com/api/v1/boards/BOARD_ID/cards/CARD_ID \
-H "Authorization: Bearer tylode_pat_xxx"Respuesta 200
{ "data": { "id": "c4f7a0d3-6b9e-4c2f-8a5d-1e4b7c0f3a96", "papelera": false } }Errores
| Estado | Cuándo |
|---|---|
400 | El ID del tablero o de la tarjeta no es válido. |
404 | La tarjeta no existe, no es de ese tablero o no puedes borrarla. |
Mover un tablero a la papelera
DELETE /api/v1/boards/:id
Manda un tablero a la papelera con sus listas y tarjetas, igual que al eliminarlo en la app. Se puede recuperar desde la papelera, y mientras está ahí no sale en Listar tableros.
Permiso (scope): boards:delete
| Parámetro | Dónde | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string | Sí | ID del tablero. |
curl -X DELETE https://app.tylode.com/api/v1/boards/BOARD_ID \
-H "Authorization: Bearer tylode_pat_xxx"Respuesta 200
{ "data": { "id": "5e8b1d4f-7a0c-4e3b-9d6f-2c5e8b1a4d70", "papelera": true } }Errores
| Estado | Cuándo |
|---|---|
400 | El ID no es válido. |
403 | Puedes ver el tablero, pero tu rol no te deja mandarlo a la papelera. |
404 | El tablero no existe, ya está en la papelera o no puedes verlo. |
Lo que tienen en común todos los DELETE está en Borrar: papelera o para siempre.
Webhooks de tarjetas
En lugar de consultar GET /cards una y otra vez, suscríbete a los eventos de tarjetas con un webhook (Ajustes → API y webhooks → Webhooks; para admins de un espacio con plan Pro). Saltan con los cambios hechos desde cualquier sitio: la app, la API o una extensión.
| Evento | Cuándo | data |
|---|---|---|
card.created | Se crea una tarjeta | card_id, board_id, list_id, title, list_name, board_name |
card.moved | Una tarjeta cambia de lista | card_id, board_id, from_list_id, to_list_id, title, list_name, board_name |
Crear una tarjeta con POST /boards/:id/cards también dispara card.created, y moverla con PATCH /boards/:id/cards/:cardId (cambiando list_id) dispara card.moved, así que cuidado con los bucles si creas o mueves tarjetas desde el manejador de un webhook.
Ejemplo: crear una tarjeta desde un formulario
El formulario de contacto de tu web puede dejar cada envío en un tablero Leads. El formulario envía los datos a una pequeña función de servidor que guarda tu token y llama a la API; el token nunca llega al navegador.
// api/lead.js: una función serverless (Request/Response estándar)
const BOARD_ID = process.env.TYLODE_LEADS_BOARD_ID;
export async function POST(request) {
const form = await request.formData();
const name = String(form.get("name") ?? "").trim();
const email = String(form.get("email") ?? "").trim();
const message = String(form.get("message") ?? "").trim();
if (!name || !email) return new Response("Name and email are required", { status: 400 });
const res = await fetch(`https://app.tylode.com/api/v1/boards/${BOARD_ID}/cards`, {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.TYLODE_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
title: `${name} <${email}>`,
description: message,
}),
});
if (!res.ok) return new Response("Couldn't save your message", { status: 502 });
return Response.redirect(new URL("/thanks", request.url), 303);
}La versión completa, con el formulario HTML y una trampa contra el spam, está en Recetas.
Relacionado
- Tableros en la app
- Webhooks
- API de calendario, para una agenda diaria que también incluye las tarjetas que vencen hoy
- Recetas