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

# Endpoints do SSO

> Referência de todos os endpoints expostos pelo serviço de autenticação EasyGoal.

## GET /auth/login

Inicia o fluxo de autenticação. Exibe o formulário de login e, após autenticação, redireciona para `redirect_to`.

**Query Parameters:**

| Parâmetro     | Tipo     | Obrigatório | Descrição                                                                                                        |
| ------------- | -------- | ----------- | ---------------------------------------------------------------------------------------------------------------- |
| `redirect_to` | `string` | Sim         | URL de callback para onde redirecionar após login. Deve estar cadastrada no Supabase → Auth → URL Configuration. |

**Respostas:**

| Status | Descrição                                                                |
| ------ | ------------------------------------------------------------------------ |
| `200`  | Renderiza o formulário de login                                          |
| `302`  | Redireciona para `/auth/welcome` → `redirect_to` após login bem-sucedido |

***

## GET /auth/check

Verifica se o usuário possui um `eg_session` cookie válido. Usado por apps server-side para validar autenticação sem redirecionar.

**Não aceita parâmetros.** Lê o cookie `eg_session` da requisição.

**Resposta 200 — autenticado:**

```json theme={null}
{
  "authenticated": true,
  "session": {
    "sub": "uuid-do-usuario",
    "email": "usuario@email.com",
    "name": "João Silva",
    "is_producer": false,
    "is_beta": true,
    "plan_slug": "easy-standard"
  }
}
```

**Resposta 200 — não autenticado:**

```json theme={null}
{ "authenticated": false, "reason": "missing_session" }
```

ou

```json theme={null}
{ "authenticated": false, "reason": "invalid_session" }
```

<Note>
  Este endpoint é para verificação server-side (ex: middleware de proteção de rotas, auth provider da documentação). Não redireciona o usuário.
</Note>

***

## POST /auth/verify

Valida um `eg_token` temporário emitido para apps externos e retorna um `eg_session` JWT. Deve ser chamado **server-side** no callback route do app externo.

**Headers:**

```
Authorization: Bearer {api_key}
Content-Type: application/json
```

**Body:**

```json theme={null}
{ "token": "<eg_token>" }
```

**Resposta 200:**

```json theme={null}
{
  "user": {
    "sub": "uuid",
    "email": "usuario@email.com",
    "name": "João Silva",
    "is_producer": false,
    "scopes": ["read:email", "read:profile"]
  },
  "eg_session": "<jwt-assinado>"
}
```

**Respostas de erro:**

| Status | Erro              | Descrição                                  |
| ------ | ----------------- | ------------------------------------------ |
| `400`  | `token ausente`   | Body sem campo `token`                     |
| `401`  | `invalid_api_key` | API key inválida ou ausente                |
| `401`  | `invalid_token`   | `eg_token` expirado ou assinatura inválida |

***

## GET /api/me

Retorna o perfil do usuário autenticado via Supabase token. Usado pelo `auth-provider` package para buscar dados do usuário após o callback.

**Headers:**

```
Authorization: Bearer {supabase_access_token}
```

**Resposta 200:**

```json theme={null}
{
  "id": "uuid-do-usuario",
  "email": "usuario@email.com",
  "name": "João Silva",
  "avatar_url": "https://...",
  "plan": "easy-standard"
}
```

| Status | Descrição                           |
| ------ | ----------------------------------- |
| `200`  | Perfil retornado                    |
| `401`  | Token ausente, inválido ou expirado |

***

## POST /api/webhook/payment

Recebe notificações de compra do app-front, verificadas com HMAC SHA256.

**Payload:**

```json theme={null}
{
  "event": "purchase.completed",
  "customer": {
    "email": "usuario@email.com",
    "name": "João Silva",
    "phone": "+5511999999999"
  },
  "product": {
    "id": "uuid-do-produto",
    "plan_slug": "easy-standard"
  },
  "company": {
    "name": "Empresa Ltda",
    "cnpj": "00.000.000/0001-00"
  },
  "signature": "<hmac-sha256-hex>"
}
```

`plan_slug` aceita: `easy-standard`, `easy-pro`, `easy-enterprise`

**Assinando no app-front:**

```ts theme={null}
import { createHmac } from 'crypto';

const body = { event, customer, product, company, timestamp };
const bodyString = JSON.stringify(body);
const signature = createHmac('sha256', process.env.SSO_WEBHOOK_SECRET!)
  .update(bodyString)
  .digest('hex');

await fetch(process.env.SSO_WEBHOOK_URL!, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ ...body, signature }),
});
```

<Warning>
  `WEBHOOK_SECRET` (SSO) e `SSO_WEBHOOK_SECRET` (app-front) devem ser idênticos.
</Warning>

**Respostas:**

| Status | Descrição                           |
| ------ | ----------------------------------- |
| `200`  | Webhook recebido e processado       |
| `400`  | Payload inválido                    |
| `401`  | Assinatura ausente ou inválida      |
| `500`  | Configuração incompleta no servidor |

***

## GET /api/plans/public

Retorna os planos disponíveis para compra. Endpoint público, sem autenticação.

**Resposta 200:**

```json theme={null}
[
  { "slug": "easy-standard",   "name": "Easy Standard",   "price": 9900 },
  { "slug": "easy-pro",        "name": "Easy Pro",        "price": 19900 },
  { "slug": "easy-enterprise", "name": "Easy Enterprise", "price": 49900 }
]
```
