La API es la misma que usa la aplicación de Gradiently, así que una clave ve los mismos datos y pasa las mismas comprobaciones que su creador en la aplicación, limitada a un espacio de trabajo y a sus permisos. Una clave que llama a un endpoint que no cubre ninguno de sus permisos recibe un 403.
URL base y autenticación
Todas las rutas de abajo están bajo https://gradiently.design. Envía tu clave como token bearer con cada petición. Los cuerpos son JSON con Content-Type: application/json, salvo en las subidas.
curl https://gradiently.design/api/marks/mine \
-H "Authorization: Bearer gr_live_…"- Una clave siempre está vinculada al espacio de trabajo en el que se creó. No hace falta indicar el espacio de trabajo; si envías
X-Workspaceo?workspace=, debe ser el de la clave, o la petición falla con 403. - Los cuerpos de las peticiones se validan de forma estricta: un campo que el endpoint no conoce falla con 422.
- Las respuestas son JSON salvo que se indique lo contrario (imágenes, redirecciones y el flujo del Designer). Los mensajes de error para claves de API están en inglés.
- Una clave actúa como su creador. Los diseños y las marcas que crea pertenecen al espacio de trabajo; los Marks que reserva pasan a su creador.
Espacio de trabajo
| Método | Ruta | Permiso | Qué hace |
|---|---|---|---|
| GET | /api/me | workspaces:read y designs:read | Tú, el espacio de trabajo de la clave y sus marcas. |
| GET | /api/workspaces | workspaces:read | El espacio de trabajo de la clave y tu rol. |
| GET | /api/workspaces/:id | workspaces:read | Un espacio de trabajo. |
| GET | /api/workspaces/:id/members | workspaces:read | Los miembros con nombre, correo y rol. |
| GET | /api/workspaces/:id/audit | workspaces:read | El registro de auditoría del espacio de trabajo. |
| POST | /api/workspaces/:id/invites | members:write | Envía por correo una invitación de siete días. |
GET /api/me
{
"viewer": { "id": "…", "name": "Ada Moss", "handle": "ada", "workspaceId": "…" },
"workspaces": [{ "id": "…", "name": "Hearth", "role": "owner" }],
"activeWorkspaceId": "…",
"personalities": [{ "id": "…", "slug": "hearth", "name": "Hearth", "markId": "…" }]
}POST /api/workspaces/:id/invites
{ "email": "sam@example.com", "role": "editor" }
{ "id": "…", "expiresInDays": 7 }role es admin, editor o viewer. La persona debe verificar la misma dirección de correo antes de aceptar.Marcas
| Método | Ruta | Permiso | Qué hace |
|---|---|---|---|
| GET | /api/personalities | designs:read | Las marcas del espacio de trabajo, como { items }. |
| POST | /api/personalities | personalities:write | Crea una marca. |
| PATCH | /api/personalities/:id | personalities:write | Cambia el nombre de una marca o define su Mark, su perfil o su estilo. |
| DELETE | /api/personalities/:id | personalities:write | Elimina una marca y sus diseños. Un espacio de trabajo conserva al menos una. |
| GET | /api/personalities/:id/designs | designs:read | Los diseños de una marca, del más reciente al más antiguo. |
| GET | /api/personalities/:id/brand | designs:read | Las fuentes, los logotipos y los colores guardados de una marca. Una clave puede leerlos, nunca cambiarlos. |
POST /api/personalities
{ "name": "Hearth Bakery", "markId": "…" }
PATCH /api/personalities/:id
{ "profile": { "about": "A neighbourhood bakery", "voice": "warm, plain" } }
{ "id": "…", "slug": "hearth-bakery", "name": "Hearth Bakery", "markId": "…", "profile": { … } }markId es opcional al crear. Un perfil también puede incluir audience, uses, keywords, dos, donts, website, handle y fonts.La lista de diseños acepta ?q= para buscar por título y ?mark= para filtrar por Mark. Cada elemento tiene id, personalityId, markId, title, form, thumb, shared y updatedAt, sin el documento.
Diseños
| Método | Ruta | Permiso | Qué hace |
|---|---|---|---|
| POST | /api/agent/compose | designs:write | Maqueta textos, reinterpreta una plantilla o aplica cambios, y guarda. |
| POST | /api/designs | designs:write | Crea un diseño a partir de un documento. |
| GET | /api/designs/:id | designs:read | Un diseño con su documento. |
| PATCH | /api/designs/:id | designs:write | Cambia su título, su documento, su Mark o si se comparte. |
| DELETE | /api/designs/:id | designs:write | Elimina un diseño. |
| POST | /api/designs/:id/duplicate | designs:write | Guarda una copia junto a él. |
| GET | /api/designs/:id/thumb | designs:read | Su miniatura. |
| POST | /api/designs/:id/render | designs:read | Lo renderiza en PNG o PDF. |
La forma más fácil de crear un diseño desde código es POST /api/agent/compose: describes el contenido y el motor de maquetación lo coloca con el Mark de la marca. El mismo endpoint reinterpreta una plantilla (template con text, photos, icons, hide) o, con designId y ops, edita un diseño guardado.
POST /api/agent/compose
{
"personalityId": "…",
"composition": {
"size": "ig-post",
"layout": "statement",
"blocks": [
{ "role": "headline", "text": "Fresh bread from 7am" },
{ "role": "cta", "text": "Visit us" }
]
}
}
{ "id": "…", "url": "/studio/…", "issues": [ … ], "elements": [ … ] }issues enumera lo que encontró la revisión (márgenes, solapamientos, jerarquía, contraste).POST /api/designs
{
"personalityId": "…",
"form": "blank",
"title": "Launch post",
"doc": { "ratio": "custom", "width": 1080, "height": 1350, "shift": [0.5, 0.5, 0.5, 0.5], "elements": [] }
}
{ "id": "…", "personalityId": "…", "markId": null, "title": "Launch post", "form": "blank", "doc": { … }, "updatedAt": "…", "thumb": null, "shared": false }markId es opcional; sin él, el diseño lleva el Mark de la marca. Lee un diseño con GET /api/designs/:id para ver un documento completo.PATCH /api/designs/:id acepta cualquiera de title, doc, markId y shared. Poner shared a true publica un enlace de visualización en /d/:id. Envía baseUpdatedAt, el updatedAt que leíste por última vez, para que el guardado se rechace con 409 si alguien ha cambiado el diseño desde entonces.
POST /api/designs/:id/render
{ "width": 1080, "height": 1350, "format": "png", "page": 0 }
{ "id": "…", "data": "iVBORw0KGgo…", "encoding": "base64", "mimeType": "image/png", "width": 1080, "height": 1350, "pages": 1 }page empieza en 0; un PDF sin page incluye todas las páginas, cada una a su tamaño del Estudio, que la petición debe respetar. Cuenta con hasta tres minutos.Renderizar requiere la misma licencia de exportación para el Mark del diseño que el Estudio; sin ella, la respuesta es 402. El renderizado nunca publica el diseño ni guarda ningún archivo.
Subidas
| Método | Ruta | Permiso | Qué hace |
|---|---|---|---|
| POST | /api/uploads | designs:write | Sube una imagen para usarla en diseños. |
| GET | /api/uploads | designs:read | Las subidas del espacio de trabajo, de la más reciente a la más antigua. |
| GET | /api/uploads/:id | designs:read | Redirige a la imagen. ?w= pide un ancho. |
| DELETE | /api/uploads/:id | designs:write | Elimina una de tus subidas. |
curl https://gradiently.design/api/uploads \
-H "Authorization: Bearer $GRADIENTLY_API_KEY" \
-F "file=@shopfront.jpg;type=image/jpeg"
# { "id": "…", "url": "/api/uploads/…" }file: PNG, JPEG, WebP, GIF o AVIF, de 8 MB como máximo, con un tipo que coincida con su contenido. Usa la url devuelta como src de una imagen o como foto de una plantilla.Marks
| Método | Ruta | Permiso | Qué hace |
|---|---|---|---|
| GET | /api/marks | marks:read | Busca en el Mercado. |
| GET | /api/marks/:code | marks:read | Un Mark con su receta, por código o id. |
| GET | /api/marks/mine | marks:read | Los Marks reservados para el espacio de trabajo, y tus borradores en él. |
| POST | /api/agent/mark | marks:read | Crea o edita una receta y la revisa. No guarda nada. |
| POST | /api/marks | brand:generate | Guarda una receta como Mark en borrador. |
| PATCH | /api/marks/:id | brand:generate | Cambia un borrador que has creado. |
| POST | /api/marks/:code/claim | marks:claim | Reserva un Mark disponible. |
| POST | /api/marks/:code/buy | marks:claim | Reserva un Mark que otro titular ha puesto a la venta. |
GET /api/marks acepta q (nombre o código), tone (dark o light), material, status (listed, house o sale) y cursor. Responde { "items": [ … ], "nextCursor": "…" } con 24 Marks por página. Un Mark tiene id, code, name, recipe, status, creator, holder y createdAt.
POST /api/marks
{ "name": "Night Harbour", "recipe": { … }, "personalityId": "…" }
{ "id": "…", "code": "GR·K7Q2·MX", "name": "Night Harbour", "status": "draft", "recipe": { … } }recipe válida de POST /api/agent/mark con un spec. personalityId guarda el borrador en esa marca. Sin él, una clave guarda el borrador en la primera marca de su espacio de trabajo, y falla con 404 si no hay ninguna. Cada persona puede tener hasta 50 borradores.Una reserva se hace para el creador de la clave, nunca para el espacio de trabajo. Las reservas gratuitas, y las cubiertas por un crédito de reserva, se completan al instante. Una reserva que requiere pago responde 402 con checkout: true, y buy responde 409 con checkout: true; termínalas en Gradiently, porque una clave no puede pagar. buy acepta { "priceCents": … }, el precio publicado que viste, y falla con 409 si ha cambiado.
Versiones de un Mark
| Método | Ruta | Permiso | Qué hace |
|---|---|---|---|
| GET | /api/marks/:code/versions | marks:read | Las versiones, de la más reciente a la más antigua, como { items, next, canEdit }. |
| GET | /api/marks/:code/versions/:vid | marks:read | Una versión. |
| POST | /api/marks/:code/versions | brand:generate | Guarda una versión: { label, recipe }, ambos opcionales. |
| PATCH | /api/marks/:code/versions/:vid | brand:generate | Cambia el nombre o marca con estrella: { label, starred }. |
| DELETE | /api/marks/:code/versions/:vid | brand:generate | Elimina una versión. |
| POST | /api/marks/:code/versions/:vid/restore | brand:generate | Vuelve a poner la versión como borrador. |
Generación de marcas
| Método | Ruta | Permiso | Qué hace |
|---|---|---|---|
| POST | /api/brand/generate | brand:generate | Devuelve propuestas de marca. No guarda nada. |
| POST | /api/brand/adopt | brand:generate | Crea un Mark en borrador, una marca y tres diseños iniciales a partir de una propuesta. |
POST /api/brand/generate
{ "name": "Hearth", "description": "A neighbourhood bakery", "tone": ["calm", "warm"], "count": 4 }
[{ "key": "…", "name": "Hearth One", "recipe": { … }, "personality": { "name": "Hearth", "handle": "…" }, "starters": [ … ], "why": "…" }]
POST /api/brand/adopt
{ "input": { "name": "Hearth", "description": "A neighbourhood bakery", "tone": ["calm", "warm"], "count": 4 }, "key": "…" }
{ "mark": { … }, "personality": { … }, "designs": [ … ] }El Designer
| Método | Ruta | Permiso | Qué hace |
|---|---|---|---|
| POST | /api/agent | designs:write | Un turno del Designer, transmitido como JSON delimitado por saltos de línea. |
| POST | /api/batches | designs:write | Inicia un conjunto de diseños a partir de un solo brief. |
| GET | /api/batches | designs:read | Tus conjuntos, en curso y recientes. |
| GET | /api/batches/:id | designs:read | El progreso de un conjunto. |
| DELETE | /api/batches/:id | designs:write | Detiene un conjunto. Los diseños ya creados se conservan. |
| GET | /api/agent/runs?designId= | designs:read | Los turnos del Designer que siguen en curso para un diseño. |
| DELETE | /api/agent/runs/:id | designs:write | Detiene un turno en curso. |
POST /api/batches
{
"personalityId": "…",
"see": false,
"plan": {
"brief": "Autumn menu launch, Saturday 4 October",
"items": [
{ "size": "ig-post", "brief": "The announcement" },
{ "size": "ig-story", "brief": "Three new loaves, one line each" }
]
}
}
{ "id": "…", "state": "running", "items": [{ "index": 0, "title": "…", "state": "…" }] }GET /api/batches/:id; cada elemento obtiene un designId y una url en cuanto se guarda. state termina en done, stopped o failed.El Designer gasta los créditos de IA del espacio de trabajo. Si el saldo es inferior a lo que necesita un turno, /api/agent y /api/batches responden 402 con code: "credits". Cada persona puede tener como máximo dos conjuntos en curso a la vez. La herramienta design de MCP y asistentes de IA lee el flujo del Designer y guarda el resultado por ti, algo más sencillo que gestionar el flujo tú mismo.
Errores
Un error responde con un código de estado y un cuerpo JSON con un mensaje error legible. Algunos añaden campos, que se indican abajo. La única excepción es /api/mcp: un cuerpo que no es JSON válido responde 400 con un objeto de error JSON-RPC en su lugar, { "jsonrpc": "2.0", "id": null, "error": { "code": -32700, "message": "Parse error" } }.
{ "error": "API key lacks required scope for this endpoint." }| Estado | Cuándo |
|---|---|
| 401 | No hay clave, la clave está mal formada, está revocada o su creador ya no es propietario ni administrador. |
| 402 | Hace falta un pago o crédito: una reserva con precio (checkout: true), falta la licencia de exportación o no quedan suficientes créditos de IA (code: "credits"). |
| 403 | A la clave le falta un permiso, pertenece a otro espacio de trabajo o el rol de su creador no permite la acción. |
| 404 | El elemento no existe o la clave no puede verlo. |
| 409 | Un conflicto: el elemento ha cambiado desde que lo leíste, un nombre ya está en uso o la acción requiere pasar por caja. |
| 422 | La petición no ha superado la validación. El mensaje indica qué campo y por qué. |
| 429 | Demasiadas peticiones. Espera los segundos que indica Retry-After y vuelve a intentarlo. |
| 503 | Ocupado o no disponible temporalmente, por ejemplo el Designer o las exportaciones. Respeta Retry-After. |
| 504 | Un renderizado ha tardado demasiado. Prueba con un tamaño menor o una sola página. |
Límites de uso
Los límites se cuentan en una ventana deslizante de un minuto salvo que se indique lo contrario. Si los superas, la respuesta es 429 con una cabecera Retry-After en segundos y un campo retryAfter en el cuerpo. Ve más despacio y vuelve a intentarlo pasado ese tiempo; no reintentes al momento.
| Límite | Margen |
|---|---|
| Cada petición con una clave | 120 por minuto por clave |
| Escrituras (POST, PATCH, DELETE) | 90 por minuto por cuenta, compartidas con la aplicación |
| Renderizados | 10 por minuto por cuenta |
| Diseños nuevos y duplicados | 60 por minuto por cuenta |
| Subidas | 60 por minuto por cuenta |
| Reservas | 20 cada diez minutos y 100 al día por cuenta |
| Invitaciones | 30 por hora por cuenta |
Las exportaciones y el Designer también tienen una capacidad compartida. Cuando está llena, la respuesta es 503 o 429 con Retry-After, aunque no hayas llegado a tus propios límites. A través de MCP, una llamada a una herramienta cuenta una vez por la petición MCP y una vez por cada petición a la API que hace la herramienta.
Paginación
Las listas devuelven una página cada vez. Pide la página siguiente con ?cursor=.
- Búsqueda en el Mercado (
/api/marks): 24 por página. Pasa elnextCursorde la respuesta; es null en la última página. - Versiones de un Mark: pasa el valor
nextde la respuesta; es null en la última página. - Diseños de una marca: 100 por página, del más reciente al más antiguo. Pasa el
iddel último diseño que recibiste. - Subidas: 60 por página, de la más reciente a la más antigua. Pasa el
idde la última subida. - Marcas, espacios de trabajo, miembros y registro de auditoría: 100 por página. Pasa el
iddel último elemento (userIdpara los miembros). Las marcas se listan desde/api/personalitiescomo{ items }.
Las claves, los permisos y la rotación están en Claves de API y permisos. Si falta un endpoint que necesitas, avísanos.

