Pular para o conteúdo principal

API de CRM

API REST para o parceiro manter os Contatos e os Negócios do Workfuse em dia a partir do sistema dele: criar, atualizar, ler, sincronizar contatos em lote, e enviar eventos que atualizam propriedades de Contato e de Negócio.

Os endpoints​

EndpointO que fazEstado
POST /crm/contactsCria um contato🟢 responde hoje
PATCH /crm/contacts/{contactId}Atualiza um contato🟢 responde hoje
GET /crm/contacts/{contactId}Lê um contato🟢 responde hoje
POST /crm/contacts/batch/upsertSincroniza em lote, assíncrono🟢 responde hoje
GET /crm/batches/{batchId}Consulta o resultado de um lote🟢 responde hoje
POST /crm/dealsCria um negócio🟢 responde hoje
PATCH /crm/deals/{dealId}Atualiza propriedades de um negócio🟢 responde hoje
GET /crm/deals/{dealId}Lê um negócio🟢 responde hoje
POST /crm/eventsEnvia evento, síncrono (201)🟢 responde hoje

Mais os webhooks, que é o que a sua aplicação recebe quando algo muda aqui.

Fundamentos​

  • Base URL: API_BASE/public/v1/crm — API_BASE é a URL da API do seu ambiente (em produção, https://api.workfuse.com). Todos os caminhos desta seção são relativos a ela.
  • Autenticação: API key no header Authorization: Bearer wf_..., com o módulo crm no escopo. A chave define a instituição — você não envia header de tenant. Veja Autenticação.
  • Formato: JSON em request e response. Datas são ISO 8601 em UTC.
  • Limites e processamento assíncrono: Limites e cotas.

Os dois objetos​

ObjetoO que é
ContatoA pessoa — candidato, aluno, responsável. Um cadastro só, que atravessa a jornada inteira
NegócioUma oportunidade sobre um Contato — uma inscrição, uma rematrícula

Esta API escreve Contato e Negócio diretamente, por POST/GET/PATCH em /contacts e em /deals; além disso, um evento também atualiza um Negócio já existente, pelo mapeamento que a instituição configura.

Duas regras do modelo que mudam como você integra:

  1. O Contato é único por instituição, e a API key já fixa a instituição. Não existe contato "da organização" — existe contato daquela instituição.
  2. O evento nunca cria Negócio. Ele atualiza o Negócio que já existe; quando não há nenhum, os mapeamentos de Negócio são ignorados e os de Contato seguem valendo. Para criar um Negócio, use POST /deals.

Propriedades​

Um campo é uma propriedade, e vive na bag properties. No Contato, todo campo vive nela: não há campo fora dela. No Negócio, contact, pipelineId, stageId, ownerId e externalId ficam fora, e properties leva só as customizadas.

{
"properties": {
"email": "ana.souza@exemplo.com",
"name": "Ana Souza",
"interesse_em_bolsa": "Sim"
}
}

Dois tipos, sem diferença de sintaxe:

TipoExemploQuem cria
Nativa (do Contato)name, email, phone, taxId, externalIdA plataforma
Customizadainteresse_em_bolsa, turno_preferidoA instituição, em Configurações → Propriedades

A chave de uma propriedade customizada é derivada do nome e é imutável. "Interesse em bolsa" vira interesse_em_bolsa: sem acento, minúscula, não-alfanumérico vira _. Você nunca escolhe a chave — ela é o contrato, e por isso não muda depois de criada.

Nome nativo nunca é sombreado. A plataforma recusa criar propriedade customizada com a chave de um campo nativo, então email dentro de properties significa sempre o e-mail do contato — nunca uma propriedade customizada de mesmo nome.

Tipos de propriedade​

TEXT · NUMBER · DATE · BOOLEAN · SELECT · MULTI_SELECT · REFERENCE · USER

MULTI_SELECT guarda uma lista, e é o único tipo em que escrever acrescenta em vez de substituir quando vem de um evento — detalhe em Eventos. REFERENCE e USER apontam para registros internos e não podem ser alvo de evento: uma string vinda de sistema de terceiro não é um id confiável.

Erros​

Toda resposta traz o header X-Request-Id: é ele que você manda no suporte.

Erro de regra de negócio (404, 409, 422) tem este formato:

{
"errorCode": "DEAL_OWNER_REQUIRED",
"message": "Informe o dono do negócio ou configure um dono padrão na instituição",
"details": {}
}
  • errorCode é estável: é por ele que você trata o erro. As tabelas de cada página listam os códigos.
  • message é em português, para gente ler. Não faça parse dela.
  • details é opcional e varia por código (keys, fields, property...). Trate todo campo como opcional ao fazer parse.

Dois erros chegam em outro formato:

  • Autenticação e escopo (401, 403): { "error": "...", "code": "API_KEY_INVALID" }. Os code são API_KEY_MISSING, API_KEY_INVALID e MODULE_NOT_IN_KEY_SCOPE. Com o CRM desligado para a organização, o 403 é { "error": "CAPABILITY_NOT_ENABLED", "code": "crm", "message": "..." }.
  • Corpo malformado (400): { "success": false, "error": { "name": "ZodError", ... } }. Não tem errorCode: leia o status.
HTTPQuando
202Aceito para processamento assíncrono — não é "pronto".
400Corpo malformado.
401API key ausente, inválida ou revogada.
403A chave não tem o módulo crm no escopo, ou a organização não tem o CRM habilitado.
404Registro não encontrado, ou de outra instituição.
409Conflito de identidade ou de externalId (ver Contatos e Negócios).
422Corpo bem formado, mas recusado pela regra de negócio.
429Limite de requisições excedido, quando os limites entrarem em vigor (hoje em prévia) — ver Limites e cotas.

Se você vem do HubSpot​

A API foi desenhada para ser familiar a quem já integrou com o HubSpot: mesma ergonomia (bag properties, upsert por propriedade de identidade, errorCode estável). O que muda é o vocabulário e o modelo — e a diferença importa na migração:

No HubSpotAquiCuidado
ContactContatoMesmo conceito, escopo diferente: lá a identidade é global por e-mail; aqui é por instituição
Company—Organization aqui é o tenant, não a empresa do contato. Não são a mesma coisa
DealNegócioMesmo conceito — POST/GET/PATCH /deals cria, lê e atualiza propriedades; evento só atualiza um já existente
firstname + lastnamenameUm campo só
hs_object_idid
Record ID do HubSpotnão é o externalIdO externalId é o id no seu sistema, não o id no CRM de origem
POST /events/v3/sendPOST /crm/eventsLá o evento vai para a timeline; aqui ele também atualiza propriedade
batch/upsert síncrono, 100 itensAssíncrono, 1.000 itensVocê recebe 202 e consulta o resultado em GET /batches/{batchId} ou assina o webhook

Comparação medida em developers.hubspot.com e knowledge.hubspot.com em 17/09/2026.

Nesta seção​

  • Contatos — criar, atualizar, ler e sincronizar em lote.
  • Negócios — criar, atualizar e ler negócios.
  • Eventos — enviar evento que atualiza propriedades de Contato e Negócio.
  • Webhooks — o que a sua aplicação recebe quando algo muda aqui.