> ## Documentation Index
> Fetch the complete documentation index at: https://docs.westhetics.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Do CRM ao contrato assinado

> O fluxo inteiro pela API: a ficha da paciente, a anamnese, o contrato e os termos, o envio para assinatura e o PDF assinado, com os eventos de cada passo.

O lead fechou no CRM. Daqui até o contrato assinado, a Westhetics faz o trabalho jurídico e o seu sistema acompanha pelos eventos. O app precisa dos escopos **Pacientes · Ler e escrever**, **Anamneses · Ler e escrever**, **Catálogo · Ler** e **Documentos e assinaturas · Ler e escrever**.

```mermaid theme={null}
sequenceDiagram
  participant CRM
  participant API as Westhetics
  participant P as Paciente
  CRM->>API: POST /v1/patients
  CRM->>API: POST /v1/anamneses (channel: link)
  API-->>CRM: link da anamnese
  CRM->>P: WhatsApp da clínica com o link
  P->>API: responde a anamnese
  API-->>CRM: webhook anamnesis.completed
  CRM->>API: POST /v1/appointments
  API-->>CRM: contrato e termos gerados
  CRM->>API: POST /v1/appointments/:id/signature-request
  API->>P: link de assinatura
  P->>API: assina
  API-->>CRM: webhook signature_request.completed
  CRM->>API: GET /v1/documents/:id/file
```

**1. Ache ou crie a ficha**

Procure primeiro: a busca aceita nome, e-mail, CPF, RG e WhatsApp.

```bash theme={null}
curl -G https://api.westhetics.io/v1/patients \
  -H "Authorization: Bearer $WESTHETICS_API_KEY" \
  --data-urlencode "search=39053344705" \
  --data-urlencode "status=active"
```

Não achou, crie. Se outra pessoa da clínica criou a ficha no meio do caminho, o `409` traz o id da que já existe: use esse.

```javascript theme={null}
async function findOrCreatePatient(input) {
  const res = await fetch('https://api.westhetics.io/v1/patients', {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${process.env.WESTHETICS_API_KEY}`,
      'Content-Type': 'application/json',
      'Idempotency-Key': input.operationId,
    },
    body: JSON.stringify({
      name: input.name,
      whatsapp: input.whatsapp,
      email: input.email,
      birthDate: input.birthDate,
      docNumber: input.cpf,
    }),
  })
  const body = await res.json()
  if (res.status === 201) return body.data.id
  if (res.status === 409 && body.error.existing) return body.error.existing.id
  throw new Error(`${body.error.code}: ${body.error.message}`)
}
```

Evento: `patient.created`.

**2. Mande a anamnese**

Com `channel: "link"`, a Westhetics não manda nada: a resposta traz o endereço para você mandar pelo WhatsApp da clínica. Com `email`, ela manda o e-mail com o link.

```bash theme={null}
curl https://api.westhetics.io/v1/anamneses \
  -H "Authorization: Bearer $WESTHETICS_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ "patientId": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "channel": "link" }'
```

A paciente só tem uma anamnese aberta por vez: se já houver, a resposta é `409` com o id dela. O link vale 7 dias. O passo a passo do WhatsApp está em [a anamnese pelo seu WhatsApp](https://docs.westhetics.io/guias/anamnese-pelo-seu-whatsapp.md).

Eventos: `anamnesis.sent` agora e `anamnesis.completed` quando ela enviar as respostas.

**3. Escolha procedimentos e prestador**

O contrato usa o catálogo da clínica: os procedimentos (com valor e condição de pagamento) e o prestador responsável (com conselho e registro).

```bash theme={null}
curl -G https://api.westhetics.io/v1/procedures \
  -H "Authorization: Bearer $WESTHETICS_API_KEY" \
  --data-urlencode "search=preenchimento"

curl https://api.westhetics.io/v1/practitioners \
  -H "Authorization: Bearer $WESTHETICS_API_KEY"
```

`GET /v1/templates` lista os termos de consentimento da clínica, com os procedimentos a que cada um está ligado.

**4. Gere o contrato e os termos**

Uma chamada cria o atendimento e gera os documentos. Sem `templateIds`, entram os termos ligados aos procedimentos escolhidos. Sem `totalAmountCents`, o valor é a soma dos procedimentos.

```bash theme={null}
curl https://api.westhetics.io/v1/appointments \
  -H "Authorization: Bearer $WESTHETICS_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "patientId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
    "procedureIds": ["b8e2c1d0-1a2b-4c3d-8e9f-0a1b2c3d4e5f"],
    "practitionerId": "7c1d2e3f-4a5b-4c6d-9e8f-1a2b3c4d5e6f",
    "imageConsent": "yes",
    "procedureDate": "2026-10-22",
    "procedureTime": "14:30"
  }'
```

Faltou dado para o contrato (CPF, endereço, responsável da menor, anamnese respondida), a resposta é `422` com o que falta em cada campo. Complete a ficha com `PATCH /v1/patients/{id}` e gere de novo. Se a recepção estiver gerando documentos para a mesma paciente no painel naquele momento, a resposta é `409`: a API não mexe no rascunho de uma pessoa.

`imageConsent` é a resposta da paciente neste atendimento e vale só para esta clínica: ao gerar, ela atualiza o cadastro da paciente na clínica da chave, e o webhook recebe `patient.updated` com `changedFields: ["imageConsent"]` quando o valor muda.

Evento: `appointment.documents_generated`.

**5. Mande para assinatura**

```bash theme={null}
curl https://api.westhetics.io/v1/appointments/3c9d1e2f-4a5b-6c7d-8e9f-0a1b2c3d4e5f/signature-request \
  -H "Authorization: Bearer $WESTHETICS_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ "channels": "whatsapp" }'
```

A resposta é o atendimento, com `sendsAt`: o envio sai nesse momento, 10 segundos depois, como no painel. A menor de idade recebe pelo responsável. Os canais pedem o contato na ficha: sem WhatsApp, `422` em `whatsapp`.

Eventos, na ordem em que costumam chegar: `signature_request.sent`, `signature_request.viewed`, `signature_request.signed` (um por assinante) e `signature_request.completed`.

**6. Guarde o PDF assinado**

Quando chegar `signature_request.completed`, `data.documentIds` diz quais documentos foram assinados. Peça o arquivo de cada um: a resposta é um endereço assinado que vale 5 minutos.

```bash theme={null}
curl https://api.westhetics.io/v1/documents/d4e5f6a7-b8c9-4123-8ef4-567890123456/file \
  -H "Authorization: Bearer $WESTHETICS_API_KEY"
```

Baixe na hora e guarde no seu sistema. O PDF é protegido contra cópia e edição; o assinado é o da Autentique, como saiu de lá, com a assinatura digital válida. Se o arquivo assinado da Autentique ainda não chegou, a resposta é `409`: tente de novo em alguns minutos.

O documento da **anamnese** traz as respostas da paciente: o app só baixa com a permissão **Ler as respostas da anamnese** (`anamneses:answers`); sem ela, `403`. O documento mostra `isRestricted: true` quando é esse o caso.

## O que pode dar errado

| Situação | Resposta | O que fazer |
| - | - | - |
| CPF já cadastrado | `409` com `existing.id` | use a ficha que existe |
| Anamnese já aberta | `409` | espere a resposta ou cancele com `POST /v1/anamneses/{id}/cancel` |
| Falta dado para o contrato | `422` com cada campo | complete a ficha e gere de novo |
| Rascunho aberto no painel | `409` | combine com a recepção; tente depois |
| Já enviado para assinatura | `409` | reenvie com `POST …/signature-request/resend` |
| Gerador de PDF fora | `503` | tente de novo em alguns minutos, com a mesma `Idempotency-Key` |
| Repetiu antes de a primeira terminar | `409` "Esta chave está em uso…" | espere alguns segundos e repita a mesma chamada |
| PDF assinado ainda não chegou | `409` | tente de novo em alguns minutos, depois de `signature_request.completed` |
| PDF da anamnese sem a permissão | `403` | peça à gestora a permissão "Ler as respostas da anamnese" |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.