Pular para o conteúdo
POST

/v1/signup

Autocadastro: criar a clínica do usuário autenticado (teste grátis do plano)

Primeiro o dono cria a conta (e-mail e senha) no provedor de identidade da plataforma; depois, com o token dessa conta, chama esta rota. Nome e e-mail do dono vêm do token — nunca do corpo.

Cria, numa chamada só: a clínica (status ONBOARDING), o vínculo do dono como Administrador e a assinatura do plano escolhido em teste grátis de 7 dias (trialEndsAt). Durante o teste nada é cobrado; ao fim, sem ativação, o painel fica em somente leitura (402 trial_expired nas escritas).

Idempotente: repetir a chamada (mesmo usuário) devolve 200 com o mesmo clinicId e created: false, sem duplicar nada; a primeira criação devolve 201. Duas chamadas simultâneas criam uma clínica só. Cada usuário cria no máximo uma clínica por esta rota.

Depois do cadastro, GET /v1/me já responde com a clínica nova (envie X-Clinic-Id se a pessoa também tiver acesso a outras clínicas).

Erros: 503 signup_disabled (cadastro ainda não aberto no ambiente), 403 signup_not_allowed (token de serviço ou equipe da plataforma), 400 (campo-isca preenchido), 409 signup_conflict (estado inconsistente — fale com o suporte), 422 unknown_plan / plan_requires_sales / invalid_cnpj / validation_error.

Dispara:clinic.created

Autenticação

Envie o token de acesso do usuário no cabeçalho Authorization. Integrações servidor a servidor usam o token de serviço com X-Clinic-Id e X-Agent-Key. Como autenticar

Authorization: Bearer <TOKEN>

Parâmetros

Corpo da requisição

application/json · obrigatório

  • clinicobjectObrigatório
  • namestringObrigatório
    clinic.name

    Entre 2 e 128 caracteres

  • cnpjstringOpcional
    clinic.cnpj

    Opcional. Os dígitos verificadores são conferidos (422 invalid_cnpj). · Padrão (regex): ^\d{2}\.?\d{3}\.?\d{3}/?\d{4}-?\d{2}$

  • phonestringObrigatório
    clinic.phone

    Telefone de contato da clínica. · Entre 8 e 32 caracteres · Padrão (regex): ^[0-9+()\s.-]+$

  • emailstring (e-mail)Obrigatório
    clinic.email

    E-mail de contato da clínica (pode ser diferente do e-mail de login). · Até 160 caracteres

  • zipstringOpcional
    clinic.zip

    Padrão (regex): ^\d{5}-?\d{3}$

  • streetstringObrigatório
    clinic.street

    Endereço (rua, número, bairro). · Entre 5 e 160 caracteres

  • citystringOpcional
    clinic.city

    Até 80 caracteres

  • statestringOpcional
    clinic.state

    Padrão (regex): ^[A-Za-z]{2}$

  • specialtystringObrigatório
    clinic.specialty

    Área de atuação principal. · Entre 2 e 64 caracteres

  • teamSizestringObrigatório
    clinic.teamSize

    Tamanho da equipe: solo (só eu), 2-5, 6-20, 20+. · Valores: solo, 2-5, 6-20, 20+

  • ownerobjectObrigatório
  • phonestringObrigatório
    owner.phone

    WhatsApp do dono da conta. · Entre 8 e 32 caracteres · Padrão (regex): ^[0-9+()\s.-]+$

  • jobTitlestringOpcional
    owner.jobTitle

    Cargo ou função. · Até 80 caracteres

  • marketingOptInbooleanObrigatório
    owner.marketingOptIn

    Aceita receber novidades e dicas por e-mail/WhatsApp.

  • planobjectObrigatório
  • idstringObrigatório
    plan.id

    Plano com preço publicado (GET /v1/billing/plans com selfSignup = true). Sob consulta → 422 plan_requires_sales. · Padrão (regex): ^[a-z0-9-]{1,32}$

  • cyclestringObrigatório
    plan.cycle

    Ciclo de cobrança escolhido no site (vale depois do teste). · Valores: mensal, anual

  • consentobjectObrigatório
  • acceptedbooleanObrigatório
    consent.accepted

    Aceite dos Termos de Uso e da Política de Privacidade (obrigatório). · Valores: true

  • termsVersionstringObrigatório
    consent.termsVersion

    Versão dos Termos de Uso exibida no aceite. · Entre 1 e 32 caracteres · Padrão (regex): ^[A-Za-z0-9._-]+$

  • privacyVersionstringObrigatório
    consent.privacyVersion

    Versão da Política de Privacidade exibida no aceite. · Entre 1 e 32 caracteres · Padrão (regex): ^[A-Za-z0-9._-]+$

  • websitestringOpcional

    Campo-isca anti-robô: o formulário deve mantê-lo oculto e vazio. Preenchido → 400. · Até 200 caracteres

Exemplo de requisição

Gerado do contrato. Troque os marcadores entre < > pelos seus valores.

const res = await fetch("https://myclinc.leadpoint.com.br/v1/signup", {  method: "POST",  headers: {    Authorization: "Bearer <TOKEN>",    "X-Agent-Key": "<agent_key>",    "Content-Type": "application/json",  },  body: JSON.stringify({    "clinic": {      "name": "Clínica Exemplo",      "phone": "(16) 99999-0000",      "email": "contato@exemplo.com",      "street": "<street>",      "specialty": "Fisioterapia",      "teamSize": "solo"    },    "owner": {      "phone": "(16) 99999-0000",      "marketingOptIn": true,      "jobTitle": "Fisioterapeuta"    },    "plan": {      "id": "profissional",      "cycle": "mensal"    },    "consent": {      "accepted": true,      "termsVersion": "2026-09",      "privacyVersion": "2026-09"    },    "website": "<website>"  }),})​if (!res.ok) {  const { error } = await res.json()  throw new Error(`${error.code}: ${error.message} (${error.requestId})`)}const { data } = await res.json()

Resposta

200OK — Sucesso.
JSON
{  "data": {    "clinicId": "clin_3f9a1c2b7d4e5f60a1b2",    "planId": "profissional",    "cycle": "mensal",    "trialEndsAt": "2026-09-18T14:00:00.000Z",    "created": true  },  "meta": {    "webhooks": [      {        "event": "appointment.cancelled",        "status": "sent"      }    ]  }}
201Created — Sucesso.
JSON
{  "data": {    "clinicId": "clin_3f9a1c2b7d4e5f60a1b2",    "planId": "profissional",    "cycle": "mensal",    "trialEndsAt": "2026-09-18T14:00:00.000Z",    "created": true  },  "meta": {    "webhooks": [      {        "event": "appointment.cancelled",        "status": "sent"      }    ]  }}

Exemplo gerado do esquema da resposta; valores entre < > são ilustrativos.

Códigos de erro

Corpo no formato padrão { error: { code, message, requestId } }. Veja todos os códigos.

400

Bad Request — Requisição malformada (JSON inválido, cursor inválido ou clínica ativa não informada).

401

Unauthorized — Token ausente, inválido ou expirado.

403

Forbidden — Autenticado, mas sem permissão (perfil ou clínica).

409

Conflict — Conflito de estado (duplicidade, transição inválida, conflito de agenda).

422

Unprocessable Entity — Dados semanticamente inválidos (erros por campo em details).

429

Too Many Requests — Limite de requisições excedido (veja Retry-After).

500

Internal Server Error — Erro interno (sem detalhes expostos).

503

Service Unavailable — Banco de dados indisponível ou não configurado.

Limites

Esta operação tem limite próprio: 5 requisições / 3600 s por IP. Sobre limites