Relm

CRM API-primero para agentes de IA: contactos, empresas, negocios, pipelines y automatizaciones a través de 41 herramientas MCP, OAuth 2.1 o clave bearer.

Documentación

Documentación de la API

Relm es API-first. Todo lo que puedes hacer en el panel de control, un agente puede hacerlo a través de REST o del servidor MCP nativo, con la misma clave bearer.

URL base y autenticación

La API se encuentra en https://api.relmcrm.com. Autentica cada solicitud con una clave bearer de ámbito de espacio de trabajo. Las claves se muestran una sola vez, se almacenan con hash SHA-256 y vienen en variantes live y test.

Authorization: Bearer relm_live_...

Genera claves en el panel de control. Las claves relm_test_ escriben en un conjunto de datos de prueba aislado que es gratuito e invisible para la facturación y el panel de control: úsalas libremente para desarrollar. El modo de prueba es un entorno aislado, no un almacenamiento: los registros de prueba se eliminan automáticamente 7 días después de su creación.

Inicio rápido

Crea tu primer contacto en una sola llamada:

curl https://api.relmcrm.com/v1/contacts \
  -H "Authorization: Bearer relm_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "email": "[email protected]", "first_name": "Ada", "last_name": "Lovelace" }'

Respuesta:

{
  "id": "con_x8f3k2m9q2",
  "object": "contact",
  "email": "[email protected]",
  "first_name": "Ada",
  "last_name": "Lovelace",
  "created_at": "2026-07-09T12:00:00.000Z"
}

SDK de TypeScript

¿Prefieres tipos en lugar de curl? El SDK oficial es un envoltorio sin dependencias sobre la misma API.

npm i relmcrm
import { Relm } from "relmcrm";

const relm = new Relm(process.env.RELM_KEY!);

const ada = await relm.contacts.create({ email: "[email protected]", first_name: "Ada" });
await relm.deals.create({ title: "Acme - annual", stage: "lead" });

// page through everything
for await (const c of relm.contacts.all()) console.log(c.id, c.email);

Las llamadas fallidas lanzan un RelmError que puedes leer para autocorregirte: e.status, e.validOptions, e.hint. Funciona en Node 18+, Bun, Deno y el navegador. En npm: npmjs.com/package/relmcrm.

Convenciones

  • IDs con prefijo - con_ contactos, cmp_ empresas, deal_ negocios, act_ actividades. Autodescriptivos y seguros para copiar y pegar.
  • Sobre (envelope) - los endpoints de listado devuelven { "object": "list", "data": [...], "has_more": true, "next_cursor": "..." }.
  • Paginación por cursor - pasa ?limit=100&cursor=.... Keyset sobre (created_at, id), estable bajo escrituras. limit por defecto es 25 y está limitado a 100 (los valores mayores se ajustan).
  • Búsqueda y filtros - los endpoints de listado aceptan ?q= para una coincidencia de subcadena sin distinción de mayúsculas (contactos: nombre, correo, teléfono, LinkedIn; empresas: nombre, dominio; negocios: título), además de filtros exactos como ?company_id=, ?stage=, ?pipeline= (alias ?pipeline_id=). Un filtro no reconocido se rechaza con 400 + valid_options, para que nunca obtengas resultados sin filtrar silenciosamente.
  • Idempotencia - envía un encabezado Idempotency-Key en una creación; un reintento devuelve el registro original en lugar de duplicarlo.
  • Concurrencia optimista - cada registro lleva un version; envía If-Match para protegerte contra actualizaciones perdidas. Una escritura obsoleta devuelve 412 version_conflict.
  • Modos - la clave decide test vs live; los datos nunca se cruzan.

Objetos principales

Contactos, empresas, negocios y actividades tienen CRUD completo en /v1/<object> con herramientas MCP correspondientes (relm_create, relm_list, relm_get, relm_update, relm_delete). Las superficies restantes tienen endpoints y herramientas de propósito específico.

ObjetoEndpointQué es
Contacto/v1/contactsPersonas. Correo opcional: los leads solo con teléfono o LinkedIn son válidos.
Empresa/v1/companiesCuentas. Los contactos y negocios se vinculan a ellas.
Negocio/v1/dealsOportunidades en un pipeline + etapa. Lleva un monto.
Actividad/v1/activitiesNotas, llamadas, correos, reuniones. Se puede retrofechar mediante occurred_at.
Pipeline/v1/pipelinesPipelines con nombre, cada uno con etapas ordenadas.
Automatización/v1/automationsReglas activadas por eventos "cuando X entonces Y".
Secuencia/v1/sequencesSecuencias de goteo de varios pasos con inscripción automática y condiciones de salida.
Plantilla/v1/templatesPlantillas de correo reutilizables referenciadas por automatizaciones y secuencias.
Webhook/v1/webhooksSuscribe un endpoint https a eventos. Firmado con HMAC, con reintentos y cola de mensajes fallidos.
Búsqueda/v1/searchBúsqueda entre objetos sobre contactos, empresas y negocios.
Esquema/v1/schemaRegistro en vivo y autodescriptivo de objetos + campos + enums.

Lee el esquema primero

Antes de escribir, un agente debe GET /v1/schema para aprender qué objetos, campos y valores de enum existen. Si luego envía un valor desconocido, el error le indica exactamente qué es válido:

POST /v1/contacts   { "type": "prospect" }

422 Unprocessable Entity   (application/problem+json)
{
  "type": "https://relmcrm.com/errors/unknown_value",
  "title": "Unknown Value",
  "status": 422,
  "detail": "'prospect' is not a valid contact type.",
  "code": "unknown_value",
  "field": "contact type",
  "valid_options": ["lead", "customer"]
}

Este es el contrato de "nunca confundirse": los agentes se autocorrigen a partir del error en lugar de fallar a ciegas o alucinar un campo. ¿Necesitas un nuevo valor? Créalo: relm_create_enum_value, relm_create_field, relm_create_type.

Escrituras por lotes

Importa muchos registros en un solo viaje de ida y vuelta con POST /v1/batch (o la herramienta MCP relm_batch). Cada operación se mide individualmente: el lote ahorra viajes de ida y vuelta, no cuota.

POST /v1/batch
{ "operations": [
  { "method": "create", "object": "contact", "data": { "email": "[email protected]" } },
  { "method": "create", "object": "deal",    "data": { "title": "Acme" } }
]}

Conéctate vía MCP

Relm incluye un servidor nativo de Model Context Protocol en https://api.relmcrm.com/mcp (HTTP Streamable, solicitud/respuesta). Cada operación de CRM es una herramienta MCP tipada. No se necesita clave para initialize o tools/list: el catálogo es público para que clientes y directorios puedan descubrirlo; tools/call requiere una credencial.

Dos formas de conectarte. Si tu cliente admite OAuth (la mayoría de los clientes de chat lo hacen), solo apúntalo a la URL del servidor y te guiará para iniciar sesión: el cliente se registra, tú apruebas en un navegador y nunca manejas un secreto. Si prefieres pegar una clave, o estás configurando un servidor o un trabajo de CI, usa una clave de API en un encabezado:

{
  "mcpServers": {
    "relm": {
      "type": "http",
      "url": "https://api.relmcrm.com/mcp",
      "headers": { "Authorization": "Bearer relm_live_..." }
    }
  }
}

Luego habla con él en lenguaje natural: "añade estos cinco leads y abre un negocio para cada uno en el pipeline de ventas". El agente llama a relm_describe_schema y luego agrupa las escrituras. Un solo POST de MCP puede llevar un array de llamadas a herramientas; cada una se mide por llamada.

OAuth 2.1

Para clientes que autorizan con OAuth, todo es descubrible: no hay nada que registrar manualmente:

  • Metadatos de recurso protegido: https://api.relmcrm.com/.well-known/oauth-protected-resource
  • Metadatos del servidor de autorización: https://api.relmcrm.com/.well-known/oauth-authorization-server
  • Registro dinámico de clientes: POST https://api.relmcrm.com/oauth/register (RFC 7591)
  • Código de autorización + PKCE (S256 requerido) y tokens de actualización con rotación. Ámbito: crm.

Un tools/call no autenticado devuelve 401 con un encabezado WWW-Authenticate que apunta a esos metadatos, que es como un cliente sabe que debe ofrecerte un botón de Conectar. Las concesiones de OAuth actúan sobre datos en vivo; el modo de prueba sigue siendo solo con clave de API.

Conéctate vía A2A

Relm también habla Agent2Agent en https://api.relmcrm.com/a2a (JSON-RPC 2.0). Envía un message/send cuya parte de datos sea {"tool":"relm_...","arguments":{...}}; Relm lo ejecuta de forma síncrona contra las mismas herramientas validadas y devuelve una Task terminal. La tarjeta de agente está en /.well-known/agent-card.json.

OpenAPI

Toda la superficie REST está descrita por una especificación OpenAPI 3.1 legible por máquina: impórtala en tu generador de clientes, Postman o una cadena de herramientas de agente.

Webhooks

Suscribe un endpoint https a eventos de CRM. Regístrate con POST /v1/webhooks (o relm_create_webhook): la respuesta devuelve un secret de firma una sola vez. Eventos: contact.created, contact.updated, deal.created, deal.updated, deal.stage_changed (o ["*"] para todos).

curl https://api.relmcrm.com/v1/webhooks \
  -H "Authorization: Bearer relm_live_..." -H "Content-Type: application/json" \
  -d '{ "url": "https://your.app/relm", "events": ["deal.stage_changed"] }'
# -> { "id": "wh_...", "secret": "whsec_...", ... }   (store the secret; shown once)

Cada entrega es un POST JSON con los encabezados Relm-Event, Relm-Delivery y Relm-Signature: t=<unix>,v1=<hmac>. Verifícalo recalculando HMAC-SHA256 de "<t>.<raw body>" con tu secreto:

import crypto from "node:crypto";
function verify(secret, rawBody, header) {
  const { t, v1 } = Object.fromEntries(header.split(",").map(p => p.split("=")));
  const expected = crypto.createHmac("sha256", secret).update(\`${t}.${rawBody}\`).digest("hex");
  return crypto.timingSafeEqual(Buffer.from(v1), Buffer.from(expected));
}

Los no-2xx o los tiempos de espera se reintentan con retroceso (1m, 5m, 30m, 2h, 6h) y se envían a la cola de mensajes fallidos después de 6 intentos. Inspecciona los intentos recientes en GET /v1/webhooks/{id}/deliveries. Las URL en modo en vivo deben ser https públicas (se rechazan hosts privados, de bucle local y de enlace local); las claves de modo de prueba pueden apuntar a localhost.

Errores

Cada error es problem+JSON RFC-9457. type es un URI estable (https://relmcrm.com/errors/<code>) que resuelve a una página de referencia breve, con un title legible, un code de máquina y, cuando es útil, valid_options y un suggestion.

EstadocodeSignificado
400bad_requestJSON malformado o parámetro incorrecto.
401unauthorizedClave de API faltante o inválida.
403plan_limit / forbiddenLímite del plan alcanzado (Free permite 2 automatizaciones / 1 secuencia) o acción no permitida para esta clave.
404not_foundNo existe tal registro en este espacio de trabajo/modo.
409conflict / idempotency_key_reusedDuplicado (p. ej., correo: devuelve el registro existente) o clave de idempotencia reutilizada.
412version_conflictEl registro cambió desde que lo leíste: vuelve a obtenerlo y a aplicarlo.
422unknown_value / unknown_field / validation_failed / invalid_referenceEntrada no procesable: consulta valid_options y suggestion.
429rate_limited / quota_exceeded / spend_cap_reachedReduce la velocidad, cuota mensual agotada o límite de gasto alcanzado.

Límites de velocidad y cuotas

Las solicitudes tienen límite de velocidad por espacio de trabajo por minuto y se cuentan contra una cuota mensual. Las respuestas llevan los encabezados X-RateLimit-* y X-Quota-*.

PlanSolicitudes mensualesPor encima del límite
Free1,000Se detiene en seco (429)
Pro - $29/mes100,000Exceso medido, $0.0001/solicitud
Scale - $249/mes2,000,000Exceso medido, $0.0001/solicitud

En los planes de pago puedes establecer un límite de gasto duro; en $0 se comporta como Free y se detiene en la cuota en lugar de facturar el exceso. El modo de prueba nunca cuenta.

¿Listo para construir?

Genera una clave gratuita y apunta tu agente hacia ella.

Empieza gratis →