Ir para o conteúdo
Todos os artigos
Configuração

Referência para desenvolvedores: API REST e MCP

A referência completa da API do Sellio: autenticação por chave, descoberta de campos, endpoints REST, formato de erro, rate limit e o servidor MCP para agentes de IA.

Integre o Sellio por HTTP ou conecte o seu agente de IA via MCP. Nos dois caminhos é a mesma chave, o mesmo escopo de tenant e o mesmo rate limit. Descubra os campos de qualquer objeto e comece a ler e escrever registros em minutos.

💡 Há também um portal público de desenvolvedores em www.selliocrm.com/developers com esta mesma referência, os webhooks de saída, o OpenAPI para baixar e uma coleção Postman.

Autenticação

Toda requisição leva uma API key no cabeçalho Authorization: Bearer. É ela que identifica o tenant dono, então tudo já fica escopado a ele automaticamente. Nunca exponha a chave no navegador; use-a somente no servidor. Você gera e revoga chaves em Configurações → API e desenvolvedores.

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

Escopo das chaves

Ao gerar uma chave em Configurações → API e desenvolvedores você escolhe o escopo dela. Dê a cada integração só o acesso de que ela precisa. Os limites valem igual no REST e no MCP, porque as duas superfícies usam a mesma chave e o mesmo controle.

  • Somente leitura: a chave lê dados, mas não cria, edita nem exclui. Bloqueia POST, PATCH e DELETE no REST e as ferramentas create_record, update_record e delete_record no MCP. Tentativas de escrita ou exclusão recebem 403 com { "error": "errors.apiKeyReadOnly" }.
  • Limitada a objetos: escolha os objetos que a chave pode acessar. Qualquer objeto fora da lista responde 403 com { "error": "errors.apiKeyObjectDenied" }. A lista de objetos (GET /api/v1/objects e a ferramenta list_objects) já vem filtrada ao escopo, e as atividades (/api/v1/activities) contam como o objeto activity: a chave só as acessa se activity estiver no escopo.
  • Permitir exclusão: por padrão uma chave NUNCA exclui, mesmo com escrita liberada. Ao gerar a chave você pode ligar a exclusão para habilitar DELETE /api/v1/{objeto}/{id} e a ferramenta delete_record do MCP. Sem esse escopo, a exclusão responde 403 com { "error": "errors.apiKeyDeleteDenied" }. A exclusão é suave: os registros vão para a lixeira e podem ser restaurados.

Uma chave sem escopo definido (o padrão) tem acesso total de leitura e escrita a todos os objetos, como antes. Chaves criadas antes desta mudança seguem com acesso total até você gerar uma nova chave com escopo.

OAuth e apps conectados

Quando um sistema de TERCEIRO precisa integrar em nome do usuário (sem que o cliente cole uma chave de admin), use o fluxo OAuth 2.0 Authorization Code com PKCE. O usuário vê uma tela de consentimento com os escopos pedidos, aprova, e o app recebe um access token que só pode fazer o que foi consentido. Os apps são curados: o desenvolvedor registra e publica o app para obter client_id e client_secret.

  • Redirecione o usuário para GET /api/oauth/authorize com client_id, redirect_uri (match exato da allowlist do app), scope, state e o PKCE (code_challenge com code_challenge_method=S256). O PKCE é obrigatório.
  • O usuário logado aprova na tela de consentimento e o CRM redireciona de volta com code e o mesmo state.
  • No seu servidor, troque o code em POST /api/oauth/token (grant_type=authorization_code, com code_verifier, client_id, client_secret e redirect_uri) por um access token (Bearer, cerca de 1 hora) e um refresh token.
  • Chame a API v1 e o servidor MCP com Authorization: Bearer at_..., escopado ao consentimento. Renove com grant_type=refresh_token; o refresh é rotacionado (o antigo morre ao usar) e reuso revoga a família. Revogue em POST /api/oauth/revoke.
# 1) Consentimento (o usuário aprova → redirect_uri?code=...&state=...)
GET https://www.selliocrm.com/api/oauth/authorize?response_type=code&client_id=app_...&redirect_uri=https://seu-app/callback&scope=records:read%20activities:read&state=abc&code_challenge=...&code_challenge_method=S256

# 2) Troque o 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://seu-app/callback

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

Escopos OAuth: records:read e records:write (todos os objetos); records:read:contact e records:write:opportunity (por objeto); activities:read e activities:write; objects:read (descoberta). Eles mapeiam para a mesma imposição de leitura, escrita e por objeto das chaves.

Widgets embutidos (iframe)

Seu app pode embutir uma tela própria (widget) no detalhe de um registro ou no painel. O widget roda num iframe sandboxed, servido a partir de uma origem sua que esteja na allowlist do app, e pede o escopo widgets:embed. O admin do tenant escolhe onde cada widget aparece em Apps → Instalados.

O host manda ao widget apenas contexto de UI por postMessage (sellio:widget:context, version 1): recordId, objectApiName, locale, theme e installId. Nenhum dado de negócio, token ou segredo trafega por essa mensagem. Para ler ou escrever dados, o widget usa a API OAuth com o próprio token (os escopos concedidos na instalação). O widget só pode responder sellio:widget:ready (receber o contexto de novo) e sellio:widget:resize com { height } (ajustar a altura, com teto); qualquer outra mensagem é ignorada.

Segurança: o iframe é sandboxed e cross-origin, então o widget não acessa o DOM nem os cookies do host. O host valida a origem exata em cada postMessage e o embedUrl é sempre checado contra a allowlist do app. No seu widget, aceite mensagens apenas quando event.origin for a origem do host.

window.addEventListener('message', (event) => {
  if (event.origin !== 'https://www.selliocrm.com') return; // só o host
  const msg = event.data;
  if (!msg || msg.version !== 1) return;
  if (msg.type === 'sellio:widget:context') {
    const { recordId, objectApiName, locale, theme } = msg.payload;
    // dados: use a API OAuth com o SEU token (nunca vêm por postMessage)
  }
});
parent.postMessage({ type: 'sellio:widget:ready', version: 1 }, 'https://www.selliocrm.com');

Descoberta de campos

Antes de criar ou atualizar um registro, descubra os campos do objeto: o que existe, o que é obrigatório e quais valores um select aceita. Você não precisa adivinhar nem inspecionar um registro que já existe.

No REST, você recebe o objeto e seus campos, com required, options (do select) e targetObject (do lookup):

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

# → {
#   "apiName": "contact",
#   "label": "Contato",
#   "fields": [
#     { "apiName": "name",  "label": "Nome",   "type": "text",  "required": true },
#     { "apiName": "email", "label": "E-mail", "type": "email", "required": false },
#     { "apiName": "source", "label": "Origem", "type": "select", "required": true,
#       "options": [ { "value": "site", "label": "Site" },
#                    { "value": "indicacao", "label": "Indicação" } ] },
#     { "apiName": "company", "label": "Empresa", "type": "lookup",
#       "required": false, "targetObject": "company" }
#   ]
# }

No MCP, a ferramenta describe_object devolve os mesmos campos para o agente:

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

API REST v1

Registros de qualquer objeto, enviando e recebendo JSON. O {objeto} é o apiName (por exemplo contact, lead, opportunity) e o {id} é o uuid do registro.

  • GET /api/v1/objects: lista os objetos do tenant.
  • GET /api/v1/objects/{objeto}: campos do objeto (descoberta).
  • GET /api/v1/{objeto}: lista e pesquisa registros.
  • GET /api/v1/{objeto}/{id}: um registro.
  • POST /api/v1/{objeto}: cria um registro.
  • POST /api/v1/{objeto}/bulk: cria em lote (até 500; sucesso parcial por item).
  • PATCH /api/v1/{objeto}/{id}: atualiza campos (parcial).
  • PATCH /api/v1/{objeto}/bulk: atualiza em lote ({ updates: [{ id, ...campos }] }).
  • DELETE /api/v1/{objeto}/{id}: exclui (suave, vai para a lixeira; exige o escopo de exclusão na chave).

Parâmetros da listagem (GET): limit (de 1 a 500, padrão 50), offset (deslocamento de paginação, padrão 0; o total sem paginação vem no campo total), search (busca por nome, ignora acento e caixa), order (campo com :asc ou :desc para ordenar) e filter. Filtros ricos: repita filter=campo:operador:valor para combinar vários com E lógico (não há OU; no máximo 12 por chamada). Operadores: eq, neq, contains, gt, lt, gte, lte, empty, not_empty (empty e not_empty não levam valor). A forma antiga filter=campo:valor (sem operador) continua sendo igualdade exata.

# 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 (E lógico: valor >= 1000 E etapa = won)
curl -H "Authorization: Bearer sk_live_..." \
  "https://www.selliocrm.com/api/v1/opportunity?filter=amount:gte:1000&filter=stage:eq:won"

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

# Criar
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

# Criar em lote (sucesso parcial por item)
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 }

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

# Excluir (suave, vai para a lixeira; exige o escopo de exclusão na chave)
curl -X DELETE -H "Authorization: Bearer sk_live_..." \
  https://www.selliocrm.com/api/v1/contact/8f3c...

Formato de erro

Erros retornam JSON no formato { "error": "mensagem" } com o status HTTP correspondente:

{ "error": "campo obrigatório: source" }   # HTTP 400
  • 200 e 201: sucesso (201 na criação).
  • 400: validação ou regra de negócio.
  • 401: chave ausente ou inválida.
  • 403: sem permissão (RBAC) para o objeto, ou bloqueado pelo escopo da chave (somente leitura, objeto fora do escopo, ou exclusão não habilitada).
  • 404: objeto ou registro não encontrado (inclui DELETE/PATCH de um id inexistente).
  • 429: rate limit excedido (veja o cabeçalho Retry-After).

Servidor MCP (agentes de IA)

O Sellio expõe um servidor MCP (Model Context Protocol) nativo para que o seu agente de IA leia e escreva no CRM com segurança. É a mesma API key, o mesmo rate limit, as mesmas validações e o mesmo RBAC. A URL do servidor é https://www.selliocrm.com/api/mcp.

  • list_objects: lista os objetos do tenant.
  • describe_object: campos de um objeto (obrigatórios, tipos, opções).
  • list_records: lista e pesquisa registros.
  • get_record: um registro pelo id.
  • create_record: cria um registro.
  • update_record: atualiza campos.
  • delete_record: exclui (suave, vai para a lixeira); exige o escopo de exclusão na chave.

Clientes que suportam MCP remoto por HTTP usam a URL com o cabeçalho Authorization: Bearer. Em clientes sem HTTP remoto nativo, use a ponte 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 chave tem um limite por minuto (padrão 120, configurável). As respostas trazem os cabeçalhos X-RateLimit-Limit, X-RateLimit-Remaining e X-RateLimit-Reset. Ao exceder, a API responde 429 com Retry-After.

Modelo de objetos

Cada tenant tem objetos padrão (Contato, Empresa, Lead, Oportunidade e outros) e objetos personalizados criados no no-code. Descubra todos com GET /api/v1/objects e os campos de cada um com GET /api/v1/objects/{objeto} ou com describe_object. O esquema é sempre o do seu tenant.

💡 Gere a sua chave em Configurações → API e desenvolvedores e faça a primeira chamada em minutos. Excluir registros está disponível pela API REST e pelo MCP, mas é uma exclusão suave (vai para a lixeira, reversível) e só funciona com chaves que tenham o escopo de exclusão ligado, desligado por padrão.

Abrir este artigo dentro do sistema

Leu e quer ver funcionando?

A conta é grátis e o manual inteiro está disponível dentro do sistema, com um assistente que responde pelo próprio conteúdo.

Criar conta grátis
Referência para desenvolvedores: API REST e MCP · Sellio