> ## Knowledge Base Index
> Fetch the complete knowledge base index at: https://help.fotostudio.io/sitemap.xml
> Use this file to discover available pages before exploring further.
> Pure-Markdown content can be obtained by appending a '.md' suffix to the content URLs listed in the sitemap (without the trailing slash).

# Webhooks de saída

Os webhooks permitem-te conectar o Fotostudio a ferramentas externas como **Make**, **Zapier**, **n8n** ou o teu próprio backend. A cada evento importante (novo contacto, fatura paga, contrato assinado...), o Fotostudio envia automaticamente os dados para o URL da tua escolha.

---

## Configurar um webhook

Vai a **Módulos → Webhooks de saída** e clica em **Novo webhook**.

Preenche os seguintes campos:

| Campo | Descrição |
| ---- |
| **Etiqueta** | Um nome para te orientares (ex: "Make – faturas") |
| **URL de destino** | O URL HTTPS fornecido pela tua ferramenta (Make, Zapier...) |
| **Eventos** | Os eventos a escutar (podes marcar vários) |

Um **segredo** é gerado automaticamente na criação. Copia-o imediatamente: não será exibido novamente. Serve para verificar que as chamadas vêm mesmo do Fotostudio.

---

## Eventos disponíveis

| Evento | Acionado quando... |
| ---- |
| `contact.created` | Um novo contacto é criado |
| `contact.updated` | Um contacto é modificado (coordenadas, infos...) |
| `project.created` | Uma nova sessão é criada |
| `project.status_changed` | O status de uma sessão muda |
| `project.confirmed` | Uma sessão é confirmada |
| `invoice.created` | Uma fatura é criada |
| `invoice.paid` | Uma fatura é marcada como paga |
| `payment.created` | Um pagamento é registado |
| `estimate.accepted` | Um orçamento é aceite pelo cliente |
| `estimate.refused` | Um orçamento é recusado pelo cliente |
| `contract.signed` | Um contrato é assinado |

---

## Formato dos dados enviados

Cada chamada é um `POST` em JSON com a seguinte estrutura:

```json
{
  "event": "invoice.paid",
  "timestamp": "2026-06-12T10:30:00Z",
  "data": {
    ...
  }
}
```

### Cabeçalhos HTTP

| Header | Valor |
| ---- |
| `Content-Type` | `application/json` |
| `X-FS-Event` | Nome do evento (ex: `invoice.paid`) |
| `X-FS-Signature` | `sha256=<hmac>` (assinatura HMAC-SHA256 do body) |
| `X-FS-Delivery-Id` | Identificador único da entrega |

### Verificar a assinatura

A assinatura em `X-FS-Signature` é calculada assim:

```
HMAC-SHA256(secret, body_json)
```

Em Node.js por exemplo:

```js
const crypto = require('crypto')
const sig = 'sha256=' + crypto.createHmac('sha256', SECRET).update(rawBody).digest('hex')
if (sig !== req.headers['x-fs-signature']) throw new Error('Assinatura inválida')
```

---

## Detalhe dos dados por evento

### `contact.created` / `contact.updated`

```json
{
  "id": 123,
  "firstname": "Maria",
  "lastname": "Santos",
  "email": "maria@example.com",
  "phone": "+351 912 345 678",
  "company": "Studio Foto",
  "street": "Rua Augusta 12",
  "zipcode": "1100-053",
  "city": "Lisboa",
  "country": "Portugal",
  "created_at": "2026-01-15T09:00:00Z",
  "url": "https://www.fotostudio.io/app/contacts/123"
}
```

### `project.created` / `project.status_changed` / `project.confirmed`

```json
{
  "id": 456,
  "name": "Casamento Santos",
  "start_time": "2026-07-20T14:00:00Z",
  "end_time": "2026-07-20T18:00:00Z",
  "project_type": "Casamento",
  "status": "Confirmado",
  "validated": true,
  "location": "Palácio da Pena",
  "contact_id": 123,
  "created_at": "2026-01-15T09:00:00Z",
  "url": "https://www.fotostudio.io/app/projects/456"
}
```

### `invoice.created` / `invoice.paid`

```json
{
  "id": 789,
  "numero": "F2026-042",
  "title": "Casamento Santos",
  "invoice_date": "2026-06-01",
  "total_price": 1500.00,
  "amount_to_pay": 750.00,
  "paid": false,
  "draft": false,
  "contact_id": 123,
  "project_id": 456,
  "created_at": "2026-06-01T10:00:00Z",
  "url": "https://www.fotostudio.io/app/invoices/789"
}
```

> `amount_to_pay` é o saldo restante a pagar (total - pagamentos já recebidos).

### `payment.created`

```json
{
  "id": 101,
  "amount": 750.00,
  "payment_date": "2026-06-10",
  "payment_type": "Transferência",
  "invoice_id": 789,
  "contact_id": 123,
  "created_at": "2026-06-10T14:00:00Z"
}
```

### `estimate.accepted` / `estimate.refused`

```json
{
  "id": 202,
  "numero": "D2026-018",
  "title": "Casamento Santos",
  "total_price": 1500.00,
  "accepted": true,
  "refused": false,
  "accepted_at": "2026-06-05T16:00:00Z",
  "contact_id": 123,
  "project_id": 456,
  "created_at": "2026-05-20T09:00:00Z",
  "url": "https://www.fotostudio.io/app/estimates/202"
}
```

### `contract.signed`

```json
{
  "id": 303,
  "title": "Contrato Casamento Santos",
  "signed_at": "2026-06-08T11:30:00Z",
  "project_id": 456,
  "contact_id": 123,
  "created_at": "2026-05-25T10:00:00Z",
  "url": "https://www.fotostudio.io/app/contracts/303"
}
```

---

## Histórico das entregas

Na ficha de cada webhook, o separador **Logs** exibe o histórico das chamadas com:

* a data e hora
* o evento acionado
* o status (sucesso / falha)
* o código HTTP de resposta
* a mensagem de erro em caso de falha

Em caso de falha, o Fotostudio **tenta novamente automaticamente até 3 vezes** com um atraso exponencial. Também podes relançar manualmente uma chamada a partir dos logs.

---

## Usar com Make

1. No Make, cria um novo cenário e adiciona um módulo **Webhooks → Custom webhook**
2. Copia o URL gerado pelo Make
3. No Fotostudio, cria um webhook com este URL e seleciona os eventos desejados
4. Aciona um evento de teste a partir do Fotostudio (cria um contacto, por exemplo