CRM Oficina Martech
ReferênciaContatos

Criar ou atualizar contato

POST /contacts — cria ou atualiza um contato (upsert) por email ou telefone, com UTMs, click ids e campos personalizados.

POST/contactsBeta

Escopo necessário: contacts:write

Cria um contato ou atualiza um existente (upsert). A organização é resolvida a partir da própria API key — não envie organization_id.

Resolução de duplicata: o contato é localizado primeiro por email e, se não houver, por telefone. O match de telefone considera variantes do 9º dígito (Brasil) e formas equivalentes de México/Argentina, então um número salvo sem o 9 (+556792275634) casa com a forma canônica (+5567992275634). Se nenhum casar, um novo contato é criado. É obrigatório informar pelo menos email ou phone.

Endpoint

POST https://crm.oficinamartech.com/api/v1/contacts

Corpo da requisição

CampoTipoObrigatórioDescrição
emailstring (email)△Email do contato. Usado como primeira chave de match (case-insensitive).
phonestring△Telefone em qualquer formato; normalizado para E.164. Segunda chave de match.
namestring (até 200)❌Nome do contato.
sourcestring (até 120)❌Origem do contato. Gravada apenas na criação. Default: api.
utmobject❌{ source, medium, campaign, term, content } — todos string opcionais.
fbclidstring❌Facebook click id.
gclidstring❌Google click id.
srcstring❌Parâmetro de origem (src).
sckstring❌Parâmetro de subtracking (sck).
landing_page_urlstring (até 2048)❌URL da landing page do toque.
referrerstring (até 2048)❌Referrer do toque.
custom_fieldsobject (mapa chave→valor)❌Campos personalizados. Cada chave deve existir como campo de contato ativo da organização.

△ = pelo menos um de email ou phone é obrigatório.

Semântica de atualização

  • Os campos enviados sobrescrevem os valores atuais do contato.
  • custom_fields é mesclado por chave: só as chaves enviadas mudam; as demais permanecem intactas.
  • source não é sobrescrito em updates (só é gravado na criação, salvo se você enviá-lo explicitamente).

Campos personalizados

As chaves de custom_fields precisam corresponder a campos personalizados de contato cadastrados em Configurações → Campos personalizados (ativos). Chaves desconhecidas retornam 400. Para campos do tipo select/multiselect, os valores devem estar entre as opções cadastradas.

Rastreamento (atribuição)

Quando você envia UTMs, fbclid, gclid, src, sck, landing_page_url ou referrer, a API grava um toque de atribuição (contact_touch_event, append-only) associado ao contato. Cada chamada com sinal de rastreamento gera um novo toque.

Resposta

201 Created (novo contato) ou 200 OK (contato atualizado):

{
  "data": {
    "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
    "organization_id": "...",
    "name": "Maria Silva",
    "email": "maria@example.com",
    "phone": "+5511999999999",
    "phone_e164": "+5511999999999",
    "source": "api",
    "custom_fields": { "plano": "Pro" },
    "created_at": "2026-06-13T12:00:00.000Z",
    "updated_at": "2026-06-13T12:00:00.000Z"
  },
  "created": true,
  "touch_event_recorded": true
}
CampoTipoDescrição
dataobjectO contato criado/atualizado.
createdbooleantrue se criou; false se atualizou um contato existente.
touch_event_recordedbooleantrue se um toque de atribuição foi gravado nesta chamada.

Exemplos

curl -X POST "https://crm.oficinamartech.com/api/v1/contacts" \
  -H "Authorization: Bearer $OFM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Maria Silva",
    "email": "maria@example.com",
    "phone": "+55 11 99999-9999",
    "utm": { "source": "google", "medium": "cpc", "campaign": "black-friday" },
    "fbclid": "IwAR123",
    "custom_fields": { "plano": "Pro" }
  }'

Códigos de erro específicos

StatuscodeCausa
400—JSON inválido, ou nem email nem phone informados
400invalid_phonephone não pôde ser normalizado para E.164
400unknown_custom_fieldsChave de custom_fields não cadastrada na organização
400invalid_custom_field_valuesValor fora das opções de um campo select/multiselect
401missing_api_keyHeader Authorization ausente
401invalid_api_keyChave malformada, inexistente ou hash não confere
401revoked_api_keyChave revogada
401expired_api_keyChave expirada
403missing_scopeChave sem o escopo contacts:write
409duplicate_contactEmail ou telefone já pertence a outro contato da organização
500—Erro interno

Veja Códigos de erro para o formato completo.

Notas

  • O match por email é case-insensitive.
  • O telefone é normalizado para E.164 (default Brasil +55); o valor normalizado é gravado em phone e phone_e164.
  • A organização vem da API key — uma chave só consegue gravar contatos na própria organização.
  • Cada chamada é registrada na aba Atividades do contato, com o payload enviado visível em JSON. Esse histórico de envios via API é permanente (não expira).

On this page