ObjectOS
Referencia

REST API

La superficie HTTP que expone ObjectOS — generada a partir de tus metadatos, delimitada por permisos y descrita con OpenAPI.

REST API

Cada objeto que declaras obtiene automáticamente un conjunto completo de endpoints REST. Cada acción se convierte en un POST. Cada flujo se convierte en un POST a /flows/.... No hay que escribir ni desplegar una capa de API aparte.

URL base: https://<your-host>/api/v1. La especificación OpenAPI está disponible en vivo en /api/v1/openapi.json.

Autenticación

ObjectOS utiliza Better Auth. Todas las rutas bajo /api/v1 requieren una sesión autenticada, salvo que estén marcadas explícitamente como públicas (consulta Formularios públicos). Los métodos de autenticación se configuran en apps/<app>/auth.config.ts — normalmente una cookie de sesión o un token bearer obtenido de /api/v1/auth/sign-in.

Los permisos se comprueban por ruta y por registro. Las rutas anotadas a continuación con una clave de permiso (p. ej. ai:chat) invocan requirePermission(...); el acceso a nivel de registro lo aplica RBAC + seguridad a nivel de fila + seguridad a nivel de campo dentro del motor de datos.

Discovery

RutaMétodoPropósito
/api/v1GETDescubrimiento de servicios — lista todas las rutas registradas, la versión y el modo de delimitación
/api/v1/discoveryGETAlias explícito del documento de descubrimiento anterior
/api/v1/openapi.jsonGETEspecificación OpenAPI 3.0 de cada endpoint del runtime en ejecución
/api/v1/searchGETBúsqueda de texto completo en los campos indexables de todos los objetos

Restringir la superficie de la API

Los endpoints autogenerados se gobiernan por objeto, de modo que puedes retirar un objeto de la API o hacerlo de solo lectura sin escribir código de rutas:

  • apiEnabled (boolean, por defecto true): establécelo en false para omitir el objeto de la superficie REST por completo. Las solicitudes a sus rutas devuelven 404.
  • apiMethods (lista blanca opcional): cuando se establece, solo son accesibles las operaciones listadas; cualquier otra operación se rechaza en la capa REST. Valores permitidos: get, list, create, update, delete, upsert, bulk, aggregate, history, search, restore, purge, import, export.
// Un objeto de referencia de solo lectura, nunca escribible por la API:
defineObject({
  name: 'exchange_rate',
  apiMethods: ['get', 'list'],
  // ...fields
})

// Un objeto interno que la API nunca expone:
defineObject({
  name: 'sync_cursor',
  apiEnabled: false,
  // ...fields
})

Ambos se aplican ahora en la capa REST (ADR-0049): las versiones anteriores analizaban estas propiedades pero no las aplicaban.

Datos — /api/v1/data/*

CRUD + consultas avanzadas para cada objeto que declaras. :object es el name del objeto (snake_case).

RutaMétodoPropósito
/data/:objectGETListar / consultar — pasa where, orderBy, limit, offset, cursor, expand, select como parámetros de consulta
/data/:object/queryPOSTConsulta avanzada — cuerpo ObjectQL completo con groupBy + aggregations (consulta ObjectQL)
/data/:object/:idGETObtener un registro. Admite ?select= y ?expand=
/data/:objectPOSTCrear. Devuelve 201 con el nuevo registro
/data/:object/:idPATCHActualizar. Pasa la cabecera If-Match: <version> (o expectedVersion en el cuerpo) para concurrencia optimista — 409 CONCURRENT_UPDATE en caso de conflicto
/data/:object/:idDELETEEliminar. Misma regla de If-Match
/data/:object/importPOSTImportación masiva (CSV o JSON). Cuerpo: { format, csv? | rows?, mapping?, dryRun? }. Máximo 5.000 filas por solicitud
/data/:object/exportPOSTExportar registros como csv / xlsx / pdf / json
/data/:object/:id/sharesGET / POSTCompartición por registro — listar concesiones, conceder acceso
/data/:object/:id/shares/:shareIdDELETERevocar una compartición
/data/lead/:id/convertPOSTConversión de lead al estilo Salesforce (plantilla CRM). Cuerpo: { accountId?, contactId?, createOpportunity? }

Ejemplo rápido

GET /api/v1/data/support_ticket?where={"status":{"$eq":"open"}}&orderBy=-created_at&limit=20
Authorization: Bearer <token>
{
  "items": [ { "id": "...", "subject": "...", "status": "open" } ],
  "total": 137,
  "nextCursor": "eyJpZCI6IjAxSDA..."
}

AI — /api/v1/ai/*

Los endpoints sobre los que se apoyan el AI Builder y tus agentes.

RutaMétodoPermisoPropósito
/ai/modelsGETai:chatListar los modelos disponibles de los proveedores configurados
/ai/chatPOSTai:chatCompletado de chat de un solo paso (síncrono)
/ai/chat/streamPOSTai:chatChat en streaming (SSE)
/ai/completePOSTai:chatEndpoint de completado en bruto
/ai/conversationsGET / POSTai:chatListar / crear conversaciones persistentes
/ai/conversations/:idGET / DELETEai:chatLeer / eliminar una conversación
/ai/conversations/:id/messagesPOSTai:chatAñadir un mensaje del usuario y ejecutar el agente
/ai/pending-actionsGETai:readLa cola de aprobación HITL — mutaciones que la IA ha propuesto
/ai/pending-actions/:idGETai:readInspeccionar una mutación en cola
/ai/pending-actions/:id/approvePOSTai:approveAplicar la mutación
/ai/pending-actions/:id/rejectPOSTai:approveDescartarla

La separación entre ai:read y ai:approve es la primitiva de seguridad que hace que el AI Builder sea seguro para los usuarios finales.

Acciones — /api/v1/actions/*

Cada *.action.ts que declaras se convierte en un endpoint.

RutaMétodoPropósito
/actions/:actionPOSTInvocar la acción. El cuerpo es el esquema de entrada de la acción. Los permisos y la validación de entrada provienen de la declaración de la acción

Cada acción también se expone a la IA como una herramienta action_<name> — consulta Acciones.

Flujos — /api/v1/flows/*

RutaMétodoPropósito
/flows/:flow/startPOSTIniciar un flujo. El cuerpo es la entrada del flujo
/flows/:flow/runs/:runIdGETEstado + salida de los pasos de un flujo en ejecución / completado
/flows/:flow/runs/:runId/cancelPOSTCancelar una ejecución en curso

Metadatos — /api/v1/meta/*

Introspección de solo lectura de los metadatos del runtime en ejecución. Útil para herramientas y para la Console.

RutaMétodoPropósito
/metaGETTodos los tipos de metadatos (object, view, action, flow, agent, …)
/meta/:typeGETListar los elementos de un tipo. Filtra con ?package=<id>
/meta/:type/:nameGETObtener un elemento. ?layers=true devuelve la vista de diferencias de 3 estados (base / package / overlay)
/meta/:type/:name/referencesGETEncontrar todos los elementos de metadatos que hacen referencia a este
/meta/:type/:name/historyGETRegistro de auditoría de ese elemento
/meta/:type/:section/:nameGET / POSTLeer / insertar o actualizar un elemento de metadatos seccionado
/meta/:type/:section/:nameDELETEEliminar un elemento seccionado

Compartición y aprobaciones

RutaMétodoPropósito
/sharing/rulesGET / POST / DELETEGestionar reglas de compartición
/sharing/rules/:idOrName/evaluatePOSTEjecutar en seco una regla contra un contexto
/approvals/processesGET / POSTDefiniciones de procesos de aprobación
/approvals/requestsGET / POSTEnviar / listar solicitudes de aprobación
/approvals/requests/:id/approvePOSTDecisión: aprobar
/approvals/requests/:id/rejectPOSTDecisión: rechazar

Informes y búsqueda

RutaMétodoPropósito
/reportsGET / POST / PATCHCRUD de informes
/reports/:id/runPOSTEjecutar un informe — devuelve filas agregadas
/reports/:id/schedulePOSTProgramar entrega recurrente

Formularios públicos

Las únicas rutas que son no autenticadas, habilitadas de forma opcional mediante FormView.sharing.allowAnonymous.

RutaMétodoAutenticación
/forms/:slugGETpública — devuelve el esquema del formulario
/forms/:slug/submitPOSTpública — envía una respuesta

Utilidades

RutaMétodoPermisoPropósito
/email/sendPOSTemail:sendEnviar un correo electrónico a través del proveedor configurado

Envoltorio de errores

Toda respuesta distinta de 2xx sigue la misma forma:

{
  "error": {
    "code": "PERMISSION_DENIED",
    "message": "Missing ai:approve on conversation 01H…",
    "details": { "permission": "ai:approve", "subject": "01H…" }
  }
}

Códigos comunes: UNAUTHENTICATED, PERMISSION_DENIED, VALIDATION_ERROR, NOT_FOUND, CONCURRENT_UPDATE, RATE_LIMITED, INTERNAL.

Versionado

/api/v1 es la API estable. Los cambios incompatibles van a /api/v2 y ambas se sirven en paralelo durante una versión menor. La versión actual y el horizonte de obsolescencia están en GET /api/v1.

Véase también

On this page