Referencia de la API

Esta página documenta la superficie viva de /api/v1/**, incluidas las rutas del companion de escritorio y los endpoints heredados que siguen siendo accesibles pero no deben usarse en integraciones nuevas.

URL base

| Entorno | URL |

| ---------- | --------------------------------- |

| Producción | https://www.devspeak.dev/api/v1 |

El documento OpenAPI legible por máquinas se sirve en [/openapi.json](/openapi.json).

Autenticación

| Familia de rutas | Mecanismo de autenticación | Notas |

| --------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------- | -------------------------------------------------------------------------- |

| GET /api/v1/health | Ninguno | Health check público |

| GET /api/v1/me, GET /api/v1/auth/confirm, GET /api/v1/history, POST /api/v1/translate, POST /api/v1/optimize, POST /api/v1/refine | x-api-key o token de ID Bearer | translate, optimize y refine también validan scopes |

| POST /api/v1/auth/session-key | token de ID Bearer | Intercambia una sesión iniciada por una API key temporal dsk_sess_ |

| POST, GET, DELETE /api/v1/user/config/providers/* | token de ID Bearer o session key | También exige la feature customProvider |

| POST /api/v1/desktop/session | token de ID Bearer o session key | Crea un token de sesión para escritorio |

| Resto de /api/v1/desktop/* | Bearer de sesión de escritorio | Requiere una sesión de escritorio (/metadata y /download son públicos) |

Un token de ID Bearer es el token de corta duración que se emite al iniciar sesión en DevSpeak con Google, GitHub o AgentID. Envíalo como Authorization: Bearer .

Scopes de API key

| Scope | Significado |

| ----------------- | --------------------------------------------------------------------------------------- |

| optimize:write | Requerido por POST /api/v1/translate, POST /api/v1/optimize y POST /api/v1/refine |

| translate:write | Reservado para uso futuro |

| history:read | Reservado para uso futuro |

| notes:write | Requerido por POST /api/v1/notes/:noteId/patch |

Scopes de sesión de escritorio

| Scope | Significado |

| ------------------------ | ------------------------------------------------------------ |

| desktop:projects:read | Leer proyectos registrados del cliente de escritorio |

| desktop:projects:write | Crear proyectos, reconciliar manifiestos e inyectar contexto |

| desktop:notes:read | Listar notas |

| desktop:notes:write | Editar una nota |

| desktop:sync:read | Consultar el feed heredado de eventos de sincronización |

Límites de tasa

| Alcance | Límite | Ventana |

| ----------------------------------------------------------------- | ----------------- | ----------------------- |

| Por API key | 100 solicitudes | 1 minuto |

| Global por IP | 180 solicitudes | 15 minutos |

| Creación de sesiones de escritorio y rutas de escritura intensiva | strictLimiter | Aplicado en el servidor |

Las respuestas pueden incluir:

``text

RateLimit-Limit: 100

RateLimit-Remaining: 97

RateLimit-Reset: 1711296060

`

Inventario de endpoints

Rutas principales

| Método | Ruta | Auth | Estado | Resumen |

| -------- | --------------------------------------- | ------------------------- | --------- | ------------------------------------------------------------ |

| GET | /api/v1/health | Ninguna | Soportado | Health check público |

| GET | /api/v1/me | API key o token de ID | Soportado | Identidad, tier, features, cuotas y uso |

| GET | /api/v1/me/entitlements | API key o token de ID | Soportado | Token de entitlements firmado para caché en el cliente |

| GET | /api/v1/auth/confirm | API key o token de ID | Soportado | Valida una session key activa o una sesión iniciada |

| POST | /api/v1/auth/session-key | token de ID | Soportado | Crea una API key efímera con los scopes solicitados |

| POST | /api/v1/auth/session-renew | Session key | Soportado | Intercambia la session key actual por una sucesora |

| POST | /api/v1/auth/session-revoke | Session key | Soportado | Revoca la session key presentada |

| GET | /api/v1/history | API key o token de ID | Soportado | Historial paginado de traducciones |

| POST | /api/v1/translate | API key o token de ID | Soportado | Pipeline completo de traducción de la etapa 2 |

| POST | /api/v1/optimize | API key o token de ID | Soportado | Optimización léxica estilo DeepL Write de la etapa 1 |

| POST | /api/v1/optimize/summarize | API key o token de ID | Soportado | Condensa entradas demasiado largas (hasta 15,000 caracteres) |

| POST | /api/v1/refine | API key o token de ID | Soportado | Refinamiento iterativo de la etapa 3 |

| POST | /api/v1/detect-language | API key o token de ID | Soportado | Detecta el idioma de una entrada |

| POST | /api/v1/notes/:noteId/patch | API key o token de ID | Soportado | Edición quirúrgica de una nota; requiere notes:write |

| GET | /api/v1/user/config/providers/current | token de ID o session key | Soportado | Obtiene la configuración activa del proveedor personalizado |

| POST | /api/v1/user/config/providers/test | token de ID o session key | Soportado | Valida un borrador del proveedor sin guardarlo |

| POST | /api/v1/user/config/providers | token de ID o session key | Soportado | Guarda una configuración de proveedor personalizado |

| DELETE | /api/v1/user/config/providers/current | token de ID o session key | Soportado | Elimina la configuración activa del proveedor |

Rutas del companion de escritorio

| Método | Ruta | Auth | Estado | Resumen |

| ------- | -------------------------------- | ------------------------- | --------- | ---------------------------------------------------------------------------------------------- |

| GET | /api/v1/desktop/appcast.xml | Ninguna | Soportado | Feed de actualizaciones Sparkle de la app de macOS |

| GET | /api/v1/desktop/metadata | Ninguna | Soportado | Metadatos de la build de escritorio actual |

| GET | /api/v1/desktop/download | Ninguna | Soportado | URL firmada de descarga de la build de escritorio actual |

| POST | /api/v1/desktop/session | token de ID o session key | Soportado | Crea o renueva un token de sesión de escritorio |

| GET | /api/v1/desktop/projects | Sesión de escritorio | Soportado | Lista proyectos registrados en escritorio |

| POST | /api/v1/desktop/projects | Sesión de escritorio | Soportado | Crea o actualiza un proyecto de escritorio |

| POST | /api/v1/desktop/projects/sync | Sesión de escritorio | Soportado | Reconciliación de un manifiesto SHA-256 contra el estado del servidor |

| GET | /api/v1/desktop/sync | Sesión de escritorio | Legado | Consulta eventos de sync. El inventario lo marca como huérfano; no lo uses en clientes nuevos. |

| POST | /api/v1/desktop/context/inject | Sesión de escritorio | Soportado | Construye un workspaceContext compacto a partir de chunks locales |

| GET | /api/v1/desktop/notes | Sesión de escritorio | Soportado | Lista las notas del usuario |

| PATCH | /api/v1/desktop/notes/:noteId | Sesión de escritorio | Soportado | Edita una nota |

Esquemas principales de petición y respuesta

GET /api/v1/health

No requiere autenticación.

`json

{

"success": true,

"data": {

"status": "ok",

"version": "v1",

"timestamp": "2026-04-13T12:00:00.000Z"

}

}

`

GET /api/v1/me

Devuelve el contexto efectivo del plan y del uso para el caller autenticado.

`json

{

"success": true,

"data": {

"userId": "abc123",

"tier": "DEVELOPER",

"features": ["apiAccess", "iterativeRefinement", "customProvider"],

"limits": {

"managedTokensPerMonth": 10000000,

"maxApiKeys": 3

},

"usage": {

"refinementCount": 12,

"currentPeriod": "2026-04"

},

"quotas": {

"managedTokens": 10000000,

"apiKeys": 3,

"managedTokensUnlimited": false,

"apiKeysUnlimited": false

}

}

}

`

GET /api/v1/auth/confirm

Confirma que la API key o la sesión iniciada (token de ID Bearer) suministrada sigue asociada a un usuario activo.

`json

{

"success": true,

"data": {

"userId": "abc123",

"confirmed": true

}

}

`

POST /api/v1/auth/session-key

Requiere un token de ID Bearer.

Cuerpo de la petición

| Campo | Tipo | Requerido | Notas |

| ------------------ | ---------- | --------- | ----------------------------- |

| scopes | string[] | No | El valor predeterminado es [ |

| "optimize:write"] |

| label | string | No | Máximo 100 caracteres |

Respuesta

`json

{

"success": true,

"data": {

"key": "dsk_sess_a1b2c3d4e5f6...",

"expiresAt": "2026-04-14T12:00:00.000Z",

"scopes": ["optimize:write"]

}

}

`

GET /api/v1/history

Parámetros de consulta

| Parámetro | Tipo | Requerido | Predeterminado | Notas |

| --------- | -------- | --------- | -------------- | ----------------------------------- |

| limit | number | No | 50 | Ajustado al rango 1..200 |

| offset | number | No | 0 | Offset de paginación basado en cero |

Respuesta

`json

{

"success": true,

"data": {

"items": [

{

"id": "translation_123",

"inputText": "We need a login page that works with Google.",

"output": "## Technical Specification...",

"audience": "Senior Dev",

"context": "Backend",

"format": "Technical Spec",

"tone": 75,

"wordCount": 847,

"latencyMs": 3200,

"model": "",

"provider": "",

"createdAt": "2026-04-13T12:00:00.000Z"

}

],

"total": 1,

"offset": 0,

"limit": 50

}

}

`

POST /api/v1/translate

Generación completa de la etapa 2. Requiere optimize:write y la feature apiAccess.

Cuerpo de la petición

| Campo | Tipo | Requerido | Notas |

| -------------------- | --------- | --------- | -------------------------------------------------------------------------------------------------------------------------------------------- |

| input | string | Sí | 10..10000 caracteres |

| audience | enum | Sí | Junior Dev, Senior Dev, Tech Lead, SRE, Data Engineer |

| context | enum | Sí | Backend, Frontend, Mobile, Data/ML, DevOps |

| format | enum | Sí | Technical Spec, Jira Tickets, API Design, RFC, Data Model, Prompt, Optimize |

| tone | integer | Sí | 0..100 |

| customInstructions | string | No | Máximo 10000 caracteres |

| workspaceContext | string | No | Máximo 150000 caracteres |

| translationId | string | No | Máximo 200 caracteres, ^[A-Za-z0-9_-]+$ |

| webSearch | boolean | No | Fundamentación RAG con recuperación web en tiempo real. Por defecto false |

| responseFormat | enum | No | markdown (por defecto) o xml para un documento legible por máquina |

| managedModel | string | No | Fija un modelo gestionado. Se rechaza si no está en la lista permitida del servidor. Omítelo para que el router LLM elija según la solicitud |

`bash

curl -X POST https://www.devspeak.dev/api/v1/translate \

-H "Content-Type: application/json" \

-H "x-api-key: $DEVSPEAK_API_KEY" \

-d '{

"input": "We need a login page that works with Google and saves user data",

"audience": "Senior Dev",

"context": "Backend",

"format": "Technical Spec",

"tone": 75,

"customInstructions": "Call out persistence, observability, and rollout concerns."

}'

`

Envelope de respuesta

`json

{

"success": true,

"data": {

"output": "## Technical Specification: User Authentication System\n\n### 1. Overview\n...",

"metadata": {

"wordCount": 847,

"latencyMs": 3200,

"model": "",

"provider": "",

"credentialSource": "managed",

"endpointHost": null

}

}

}

`

POST /api/v1/optimize

Optimización léxica de la etapa 1. Requiere optimize:write. Este endpoint es determinista y libre de contexto de tarea: solo acepta el texto de entrada, la audiencia, el contexto y un managedModel opcional. A diferencia de /api/v1/translate, no genera un documento técnico formateado y no acepta campos de la etapa 2 como format, tone, customInstructions, adjuntos o contextProjectId — los campos no soportados se registran y descartan en lugar de rechazarse. Las instrucciones personalizadas a nivel de cuenta almacenadas en tu perfil siguen aplicándose. Los resultados nunca se persisten en el historial de traducciones.

Cuerpo de la petición

| Campo | Tipo | Requerido | Notas |

| -------------- | -------- | --------- | ---------------------------------------------------------------------------- |

| input | string | Sí | 10..10000 caracteres |

| audience | enum | Sí | Mismo enum que /translate |

| context | enum | Sí | Mismo enum que /translate |

| managedModel | string | No | Modelo gestionado permitido (opcional). Omítelo para que el router LLM elija |

`bash

curl -X POST https://www.devspeak.dev/api/v1/optimize \

-H "Content-Type: application/json" \

-H "x-api-key: $DEVSPEAK_API_KEY" \

-d '{

"input": "pls make this spec more professional and clearer",

"audience": "Senior Dev",

"context": "Backend"

}'

`

El envelope de respuesta coincide con /api/v1/translate y devuelve el texto optimizado en data.output.

POST /api/v1/refine

Refinamiento de la etapa 3. Requiere optimize:write y la feature iterativeRefinement.

Cuerpo de la petición

| Campo | Tipo | Requerido | Notas |

| ------------------ | --------- | --------- | ----------------------------------------------------------------------------- |

| originalInput | string | No | El servidor usa "" por defecto; máximo 10000 caracteres |

| previousOutput | string | Sí | 1..50000 caracteres |

| feedback | string | Sí | 1..5000 caracteres |

| audience | enum | Sí | Mismo enum que /translate |

| context | enum | Sí | Mismo enum que /translate |

| format | enum | Sí | Mismo enum que /translate |

| tone | integer | Sí | 0..100 |

| workspaceContext | string | No | Máximo 150000 caracteres |

| translationId | string | No | Máximo 200 caracteres |

| webSearch | boolean | No | Fundamentación RAG. Por defecto false |

| responseFormat | enum | No | markdown (por defecto) o xml |

| managedModel | string | No | Modelo gestionado de la lista permitida. Omítelo para que el router LLM elija |

`bash

curl -X POST https://www.devspeak.dev/api/v1/refine \

-H "Content-Type: application/json" \

-H "x-api-key: $DEVSPEAK_API_KEY" \

-d '{

"originalInput": "We need a login page that works with Google and saves user data",

"previousOutput": "## Technical Specification...",

"feedback": "Add a section on rate limiting and explicit error codes.",

"audience": "Senior Dev",

"context": "Backend",

"format": "Technical Spec",

"tone": 75

}'

`

Las respuestas exitosas usan el mismo envelope que /translate, con metadata.isOutOfScope cuando el feedback de refinamiento se rechaza por ser ajeno al documento.

Rutas de configuración de proveedor

Estas rutas aceptan token de ID Bearer o una session key y requieren la feature customProvider.

GET /api/v1/user/config/providers/current

Devuelve la configuración actual del proveedor o null si no hay ninguna configurada.

Cuando no existe un proveedor personalizado guardado, la ruta responde con:

`json

{

"success": true,

"data": null,

"configured": false

}

`

`json

{

"success": true,

"data": {

"providerType": "gemini",

"providerName": "Gemini",

"apiEndpoint": null,

"metadata": {

"model": "gemini-3-flash-preview",

"label": "Gemini",

"keyPreview": "AIza...1234",

"endpointHost": null

},

"enabled": true,

"updatedAt": "2026-04-13T12:00:00.000Z",

"lastValidatedAt": "2026-04-13T12:00:00.000Z",

"status": "active",

"validationMessage": null

}

}

`

POST /api/v1/user/config/providers/test

POST /api/v1/user/config/providers

Ambos endpoints aceptan el mismo esquema de borrador:

| Campo | Tipo | Requerido | Notas |

| ----------------- | --------- | ----------- | ---------------------------------------------------- |

| providerType | enum | Sí | gemini, openai, anthropic, openai-compatible |

| providerName | string | Sí | 1..100 caracteres |

| apiKey | string | Condicional | Obligatorio salvo que isExistingKey sea true |

| isExistingKey | boolean | No | Reutiliza la clave cifrada ya guardada |

| baseURL | string | Condicional | Obligatorio para openai-compatible |

| modelIdentifier | string | No | 1..120 caracteres |

/test valida un borrador sin persistirlo. /providers valida y guarda la configuración. Ambos responden con el mismo envelope de configuración mostrado arriba.

DELETE /api/v1/user/config/providers/current

Elimina la configuración activa del proveedor.

`json

{

"success": true,

"data": null

}

`

Rutas del companion de escritorio

POST /api/v1/desktop/session

Crea un token de sesión de escritorio a partir de una petición autenticada con un token de ID Bearer o con una session key.

Cuerpo de la petición

| Campo | Tipo | Requerido | Notas |

| ------------- | -------- | --------- | -------------------------------------------------------- |

| deviceId | string | Sí | 1..128, ^[A-Za-z0-9._:-]+$ |

| deviceLabel | string | Sí | 1..120 caracteres |

| runtime | enum | No | electron, tauri, unknown; predeterminado unknown |

Respuesta

`json

{

"success": true,

"data": {

"token": "desktop-session-token",

"expiresInSeconds": 900,

"scopes": [

"desktop:projects:read",

"desktop:projects:write",

"desktop:notes:read",

"desktop:notes:write",

"desktop:sync:read"

],

"device": {

"deviceId": "desktop-device-1",

"deviceLabel": "MacBook Pro",

"platform": "desktop-app",

"runtime": "electron",

"lastSeenAt": "2026-04-10T12:00:00.000Z"

}

}

}

`

GET /api/v1/desktop/projects

Devuelve un array de proyectos registrados para la sesión de escritorio autenticada.

`json

{

"success": true,

"data": [

{

"projectId": "project-1",

"name": "Monorepo",

"rootPath": "/Users/dev/projects/monorepo",

"createdAt": "2026-04-10T11:00:00.000Z",

"updatedAt": "2026-04-10T12:00:00.000Z",

"lastSyncedAt": "2026-04-10T12:00:00.000Z",

"lastSyncedByDeviceId": "desktop-device-1"

}

]

}

`

POST /api/v1/desktop/projects

Cuerpo de la petición

| Campo | Tipo | Requerido | Notas |

| ----------- | -------- | --------- | ------------------------------------------------ |

| projectId | string | Sí | 1..128, formato de identificador de escritorio |

| name | string | Sí | 1..128 caracteres |

| rootPath | string | Sí | 1..2048, bloquea traversal de rutas |

Devuelve el proyecto actualizado y emite un evento de sync en el servidor.

`json

{

"success": true,

"data": {

"projectId": "project-1",

"name": "Monorepo",

"rootPath": "/Users/dev/projects/monorepo",

"createdAt": "2026-04-10T11:00:00.000Z",

"updatedAt": "2026-04-10T12:00:00.000Z",

"lastSyncedAt": "2026-04-10T12:00:00.000Z",

"lastSyncedByDeviceId": "desktop-device-1"

}

}

`

POST /api/v1/desktop/projects/sync

Endpoint de reconciliación de manifiestos.

Cuerpo de la petición

| Campo | Tipo | Requerido | Notas |

| ----------- | -------- | --------- | --------------------------- |

| projectId | string | Sí | Identificador de escritorio |

| files | array | Sí | Máximo 10000 entradas |

Cada elemento de files[] admite:

| Campo | Tipo | Requerido | Notas |

| ------------ | --------- | --------- | -------------------------------------- |

| path | string | Sí | Máximo 1024; traversal bloqueado |

| hash | string | Sí | SHA-256 en minúsculas de 64 caracteres |

| sizeBytes | integer | No | 0..50000000 |

| modifiedAt | string | No | Fecha ISO 8601 |

Las respuestas devuelven un delta con listas de subida, borrado y archivos sin cambios.

`json

{

"success": true,

"data": {

"manifestId": "user-123-project-1-1713000000000",

"toUpload": ["app/main.py", "app/routes/orders.py"],

"toDelete": ["app/deprecated.py"],

"unchanged": ["pyproject.toml"],

"totalFiles": 3

}

}

`

POST /api/v1/desktop/context/inject

Construye un workspaceContext compacto a partir de chunks de archivos locales.

Cuerpo de la petición

| Campo | Tipo | Requerido | Notas |

| ----------- | -------- | --------- | --------------------------------------------- |

| projectId | string | Sí | Identificador de escritorio |

| label | string | No | Máximo 200 caracteres |

| query | string | No | Máximo 32000 caracteres — ver ranking abajo |

| chunks | array | Sí | 1..200 elementos |

Envía en query el texto de entrada de la traducción pendiente. Los chunks se

ordenan según su relevancia — por ruta, nombre de archivo y símbolos extraídos —

para que los archivos relevantes sobrevivan al límite de 150,000 caracteres de

contexto. Si se omite, el ensamblado usa el orden en que se enviaron los chunks,

lo que descarta en silencio los últimos en llegar.

Cada elemento de chunks[] admite:

| Campo | Tipo | Requerido | Notas |

| --------- | ---------- | --------- | ------------------------ |

| path | string | Sí | Máximo 1024 caracteres |

| content | string | Sí | Máximo 8192 caracteres |

| symbols | string[] | No | Máximo 100 entradas |

`json

{

"success": true,

"data": {

"contextId": "ctx-project-1-1713000000000",

"contextText": "# Project Context: project-1\n# Source files: 2\n...",

"tokenEstimate": 742,

"chunkCount": 2,

"includedCount": 2

}

}

`

includedCount indica cuántos chunks entraron en el límite. Un valor menor que

chunkCount significa que se descartó contexto.

GET /api/v1/desktop/sync

Endpoint heredado de polling de sincronización. No lo uses para integraciones nuevas.

Parámetros de consulta

| Parámetro | Tipo | Requerido | Notas |

| ----------- | -------- | --------- | --------------------------------- |

| projectId | string | Sí | Identificador de escritorio |

| after | string | No | Cursor ISO 8601 |

| limit | number | No | Predeterminado 50, máximo 100 |

El inventario marca esta ruta como huérfana. Sigue disponible por compatibilidad, pero los clientes de escritorio nuevos deben usar POST /api/v1/desktop/projects/sync.

`json

{

"success": true,

"data": {

"items": [

{

"eventId": "event-1",

"eventType": "translation.upserted",

"userId": "user-123",

"occurredAt": "2026-04-10T12:30:00.000Z",

"source": "api-v1",

"projectId": "project-1",

"entityType": "translation",

"entityId": "translation-1",

"payload": {

"translationId": "translation-1"

}

}

],

"nextCursor": "2026-04-10T12:30:00.000Z",

"serverTime": "2026-04-10T12:30:05.000Z"

}

}

`

Rutas heredadas y en desuso

POST /api/v1/optimize-input

Devuelve 308 Permanent Redirect hacia /api/v1/optimize. El sunset actual en el inventario es 2026-10-01.

POST /api/v1/user/config/keys

Ruta heredada de BYOK. Duplica el flujo de configuración de proveedores y está protegida por el mismo entitlement customProvider. No construyas integraciones nuevas sobre este endpoint.

Envelope común de errores

`json

{

"success": false,

"error": "Mensaje de error legible para humanos",

"error_code": "ERR_VALIDATION_FAILED",

"details": []

}

`

| Estado | Significado |

| ------ | -------------------------------------------- |

| 400 | Fallo de validación |

| 401 | Credenciales ausentes, inválidas o expiradas |

| 403 | Faltan scopes, acceso a features o cuota |

| 422 | Fallo en la validación del proveedor |

| 429 | Límite de tasa excedido |

| 500 | Error interno del servidor |

| 504 | Timeout del upstream |

Notas sobre la CLI y el render de rutas

  • La guía de la CLI en [/docs/cli-guide](/docs/cli-guide) está sincronizada con el mismo inventario.
  • El runtime de documentación resuelve /docs/api-reference y /docs/cli-guide` mediante registros MDX explícitos, de modo que estas páginas renderizan igual en local, staging y producción.