Ir al contenido
Todos los artículos
Configuración

Referencia para desarrolladores: API REST y MCP

La referencia completa de la API de Sellio: autenticación por clave, descubrimiento de campos, endpoints REST, formato de error, rate limit y el servidor MCP para agentes de IA.

Integra Sellio por HTTP o conecta tu agente de IA vía MCP. En ambos caminos es la misma clave, el mismo alcance de tenant y el mismo rate limit. Descubre los campos de cualquier objeto y empieza a leer y escribir registros en minutos.

💡 También hay un portal público de desarrolladores en www.selliocrm.com/developers con esta misma referencia, los webhooks de salida, el OpenAPI para descargar y una colección Postman.

Autenticación

Cada solicitud lleva una API key en el encabezado Authorization: Bearer. Es ella la que identifica al tenant dueño, así que todo queda limitado a él automáticamente. Nunca expongas la clave en el navegador; úsala solo en el servidor. Generas y revocas claves en Configuración → API y desarrolladores.

curl -H "Authorization: Bearer sk_live_..." \
  https://www.selliocrm.com/api/v1/objects

Alcance de las claves

Al generar una clave en Configuración → API y desarrolladores eliges su alcance. Dale a cada integración solo el acceso que necesita. Los límites valen igual en REST y en MCP, porque las dos superficies usan la misma clave y el mismo control.

  • Solo lectura: la clave lee datos, pero no crea, edita ni elimina. Bloquea POST, PATCH y DELETE en REST y las herramientas create_record, update_record y delete_record en MCP. Los intentos de escritura o eliminación reciben 403 con { "error": "errors.apiKeyReadOnly" }.
  • Limitada a objetos: elige los objetos a los que la clave puede acceder. Cualquier objeto fuera de la lista responde 403 con { "error": "errors.apiKeyObjectDenied" }. La lista de objetos (GET /api/v1/objects y la herramienta list_objects) ya viene filtrada al alcance, y las actividades (/api/v1/activities) cuentan como el objeto activity: la clave solo las alcanza si activity está en el alcance.
  • Permitir eliminación: por defecto una clave NUNCA elimina, ni con escritura habilitada. Al generar la clave puedes activar la eliminación para habilitar DELETE /api/v1/{objeto}/{id} y la herramienta delete_record del MCP. Sin ese alcance, la eliminación responde 403 con { "error": "errors.apiKeyDeleteDenied" }. La eliminación es suave: los registros van a la papelera y pueden restaurarse.

Una clave sin alcance definido (el valor por defecto) tiene acceso total de lectura y escritura a todos los objetos, como antes. Las claves creadas antes de este cambio siguen con acceso total hasta que generes una nueva clave con alcance.

OAuth y apps conectadas

Cuando un sistema de TERCEROS necesita integrar en nombre del usuario (sin que el cliente pegue una clave de admin), usa el flujo OAuth 2.0 Authorization Code con PKCE. El usuario ve una pantalla de consentimiento con los alcances pedidos, aprueba, y la app recibe un access token que solo puede hacer lo consentido. Las apps son curadas: el desarrollador registra y publica la app para obtener client_id y client_secret.

  • Redirige al usuario a GET /api/oauth/authorize con client_id, redirect_uri (coincidencia exacta con la allowlist de la app), scope, state y PKCE (code_challenge con code_challenge_method=S256). El PKCE es obligatorio.
  • El usuario conectado aprueba en la pantalla de consentimiento y el CRM redirige de vuelta con code y el mismo state.
  • En tu servidor, intercambia el code en POST /api/oauth/token (grant_type=authorization_code, con code_verifier, client_id, client_secret y redirect_uri) por un access token (Bearer, cerca de 1 hora) y un refresh token.
  • Llama a la API v1 y al servidor MCP con Authorization: Bearer at_..., acotado al consentimiento. Renueva con grant_type=refresh_token; el refresh se rota (el anterior muere al usarse) y su reuso revoca la familia. Revoca en POST /api/oauth/revoke.
# 1) Consentimiento (el usuario aprueba → redirect_uri?code=...&state=...)
GET https://www.selliocrm.com/api/oauth/authorize?response_type=code&client_id=app_...&redirect_uri=https://tu-app/callback&scope=records:read%20activities:read&state=abc&code_challenge=...&code_challenge_method=S256

# 2) Intercambia el code por tokens (server-side)
curl -X POST https://www.selliocrm.com/api/oauth/token \
  -d grant_type=authorization_code -d code=<authcode> -d code_verifier=<verifier> \
  -d client_id=app_... -d client_secret=secret_... -d redirect_uri=https://tu-app/callback

# → { "access_token": "at_...", "token_type": "Bearer", "expires_in": 3600,
#     "refresh_token": "rt_...", "scope": "records:read activities:read" }

Alcances OAuth: records:read y records:write (todos los objetos); records:read:contact y records:write:opportunity (por objeto); activities:read y activities:write; objects:read (descubrimiento). Mapean a la misma imposición de lectura, escritura y por objeto que las claves.

Widgets embebidos (iframe)

Tu app puede embeber su propia pantalla (widget) en el detalle de un registro o en el panel. El widget corre en un iframe sandboxed, servido desde un origen tuyo que esté en la allowlist de la app, y pide el permiso widgets:embed. El admin del tenant elige dónde aparece cada widget en Apps → Instaladas.

El host envía al widget solo contexto de UI por postMessage (sellio:widget:context, version 1): recordId, objectApiName, locale, theme e installId. Ningún dato de negocio, token o secreto viaja en ese mensaje. Para leer o escribir datos, el widget usa la API OAuth con su propio token (los permisos concedidos al instalar). El widget solo puede responder sellio:widget:ready (recibir el contexto de nuevo) y sellio:widget:resize con { height } (ajustar su altura, con tope); cualquier otro mensaje se ignora.

Seguridad: el iframe es sandboxed y cross-origin, así que el widget no accede al DOM ni a las cookies del host. El host valida el origen exacto en cada postMessage y el embedUrl siempre se verifica contra la allowlist de la app. En tu widget, acepta mensajes solo cuando event.origin sea el origen del host.

window.addEventListener('message', (event) => {
  if (event.origin !== 'https://www.selliocrm.com') return; // solo el host
  const msg = event.data;
  if (!msg || msg.version !== 1) return;
  if (msg.type === 'sellio:widget:context') {
    const { recordId, objectApiName, locale, theme } = msg.payload;
    // datos: usa la API OAuth con TU token (nunca llega por postMessage)
  }
});
parent.postMessage({ type: 'sellio:widget:ready', version: 1 }, 'https://www.selliocrm.com');

Descubrimiento de campos

Antes de crear o actualizar un registro, descubre los campos del objeto: qué existe, qué es obligatorio y qué valores acepta un select. Sin adivinar y sin inspeccionar un registro existente.

En REST, recibes el objeto y sus campos, con required, options (del select) y targetObject (del lookup):

GET https://www.selliocrm.com/api/v1/objects/contact

# → {
#   "apiName": "contact",
#   "label": "Contacto",
#   "fields": [
#     { "apiName": "name",  "label": "Nombre", "type": "text",  "required": true },
#     { "apiName": "email", "label": "Correo", "type": "email", "required": false },
#     { "apiName": "source", "label": "Origen", "type": "select", "required": true,
#       "options": [ { "value": "site", "label": "Sitio" },
#                    { "value": "referido", "label": "Referido" } ] },
#     { "apiName": "company", "label": "Empresa", "type": "lookup",
#       "required": false, "targetObject": "company" }
#   ]
# }

En MCP, la herramienta describe_object devuelve los mismos campos al agente:

{ "method": "tools/call",
  "params": { "name": "describe_object", "arguments": { "object": "contact" } } }

API REST v1

Registros de cualquier objeto, enviando y recibiendo JSON. {objeto} es el apiName (por ejemplo contact, lead, opportunity) y {id} es el uuid del registro.

  • GET /api/v1/objects: lista los objetos del tenant.
  • GET /api/v1/objects/{objeto}: campos del objeto (descubrimiento).
  • GET /api/v1/{objeto}: lista y busca registros.
  • GET /api/v1/{objeto}/{id}: un registro.
  • POST /api/v1/{objeto}: crea un registro.
  • POST /api/v1/{objeto}/bulk: crea en lote (hasta 500; éxito parcial por ítem).
  • PATCH /api/v1/{objeto}/{id}: actualiza campos (parcial).
  • PATCH /api/v1/{objeto}/bulk: actualiza en lote ({ updates: [{ id, ...campos }] }).
  • DELETE /api/v1/{objeto}/{id}: elimina (suave, va a la papelera; requiere el alcance de eliminación en la clave).

Parámetros del listado (GET): limit (de 1 a 500, predeterminado 50), offset (desplazamiento de paginación, predeterminado 0; el total sin paginación viene en el campo total), search (búsqueda por nombre, ignora acento y mayúsculas), order (campo con :asc o :desc para ordenar) y filter. Filtros ricos: repite filter=campo:operador:valor para combinar varios con Y lógico (no hay OR; hasta 12 por llamada). Operadores: eq, neq, contains, gt, lt, gte, lte, empty, not_empty (empty y not_empty no llevan valor). La forma antigua filter=campo:valor (sin operador) sigue siendo igualdad exacta.

# Listar (limit, offset, search, filter, order)
curl -H "Authorization: Bearer sk_live_..." \
  "https://www.selliocrm.com/api/v1/opportunity?limit=20&order=updated_at:desc&filter=stage:won"

# Filtros ricos (Y lógico: amount >= 1000 Y stage = won)
curl -H "Authorization: Bearer sk_live_..." \
  "https://www.selliocrm.com/api/v1/opportunity?filter=amount:gte:1000&filter=stage:eq:won"

# Un registro
curl -H "Authorization: Bearer sk_live_..." \
  https://www.selliocrm.com/api/v1/contact/8f3c...

# Crear
curl -X POST -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{"name":"Ana Souza","email":"ana@acme.com","source":"site"}' \
  https://www.selliocrm.com/api/v1/contact

# Crear en lote (éxito parcial por ítem)
curl -X POST -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{"records":[{"name":"Ana"},{"name":"Bruno"}]}' \
  https://www.selliocrm.com/api/v1/contact/bulk
# → { "results": [ { "index": 0, "ok": true, "id": "..." } ], "created": 1, "failed": 0 }

# Actualizar (parcial)
curl -X PATCH -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{"source":"referido"}' \
  https://www.selliocrm.com/api/v1/contact/8f3c...

# Eliminar (suave, va a la papelera; requiere el alcance de eliminación en la clave)
curl -X DELETE -H "Authorization: Bearer sk_live_..." \
  https://www.selliocrm.com/api/v1/contact/8f3c...

Formato de error

Los errores devuelven JSON en la forma { "error": "mensaje" } con el estado HTTP correspondiente:

{ "error": "campo obligatorio: source" }   # HTTP 400
  • 200 y 201: éxito (201 al crear).
  • 400: validación o regla de negocio.
  • 401: clave ausente o inválida.
  • 403: sin permiso (RBAC) para el objeto, o bloqueado por el alcance de la clave (solo lectura, objeto fuera del alcance, o eliminación no habilitada).
  • 404: objeto o registro no encontrado (incluye DELETE/PATCH de un id inexistente).
  • 429: rate limit excedido (ver el encabezado Retry-After).

Servidor MCP (agentes de IA)

Sellio expone un servidor MCP (Model Context Protocol) nativo para que tu agente de IA lea y escriba en el CRM con seguridad. Es la misma API key, el mismo rate limit, las mismas validaciones y el mismo RBAC. La URL del servidor es https://www.selliocrm.com/api/mcp.

  • list_objects: lista los objetos del tenant.
  • describe_object: campos de un objeto (obligatorios, tipos, opciones).
  • list_records: lista y busca registros.
  • get_record: un registro por id.
  • create_record: crea un registro.
  • update_record: actualiza campos.
  • delete_record: elimina (suave, va a la papelera); requiere el alcance de eliminación en la clave.

Los clientes que soportan MCP remoto por HTTP usan la URL con el encabezado Authorization: Bearer. En clientes sin HTTP remoto nativo, usa el puente mcp-remote:

{
  "mcpServers": {
    "sellio-crm": {
      "command": "npx",
      "args": [
        "-y", "mcp-remote",
        "https://www.selliocrm.com/api/mcp",
        "--header", "Authorization: Bearer sk_live_..."
      ]
    }
  }
}

Rate limit

Cada clave tiene un límite por minuto (predeterminado 120, configurable). Las respuestas incluyen los encabezados X-RateLimit-Limit, X-RateLimit-Remaining y X-RateLimit-Reset. Al excederlo, la API responde 429 con Retry-After.

Modelo de objetos

Cada tenant tiene objetos estándar (Contacto, Empresa, Lead, Oportunidad y otros) y objetos personalizados creados en el no-code. Descúbrelos todos con GET /api/v1/objects y los campos de cada uno con GET /api/v1/objects/{objeto} o con describe_object. El esquema siempre es el de tu tenant.

💡 Genera tu clave en Configuración → API y desarrolladores y haz tu primera llamada en minutos. Eliminar registros está disponible por la API REST y por MCP, pero es una eliminación suave (va a la papelera, reversible) y solo funciona con claves que tengan el alcance de eliminación activado, desactivado por defecto.

Abrir este artículo dentro del sistema

¿Lo leíste y quieres verlo funcionando?

La cuenta es gratis y el manual entero está disponible dentro del sistema, con un asistente que responde con este mismo contenido.

Crear cuenta gratis
Referencia para desarrolladores: API REST y MCP · Sellio