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

# Autenticação

> Endpoints para login seguro e autenticação de consumidores

A autenticação na API Widget vincula o consumidor ao programa de fidelidade da BonifiQ, gerando um `SecureToken` necessário para acessar endpoints **autenticados** (saldo, resgate, cashback, afiliados, etc.).

<Info>
  **Modelo de autenticação: você é o consumidor.** Diferente de uma API de backend tradicional — onde você autentica com credenciais da sua aplicação e pode consultar/interagir com qualquer cliente — na API Widget o `SecureToken` representa **um consumidor específico**. Todas as chamadas feitas com esse token só acessam os dados dele (saldo, histórico, recompensas). O escopo é sempre limitado ao consumidor autenticado.
</Info>

Existem duas formas de autenticar:

* **Token por e-mail (Challenge)** — método universal, funciona em qualquer plataforma
* **Via plataforma (Wake ou VTEX)** — autenticação transparente usando a sessão existente do consumidor

<Note>
  Endpoints marcados como **Público** não exigem `SecureToken`. Apenas o header `X-BQ-Tenant` é necessário.
</Note>

## Status de Autenticação dos Endpoints

| Endpoint                                     | Status  |
| -------------------------------------------- | ------- |
| `POST /pub/widget/account/challenge`         | Público |
| `POST /pub/widget/account/validatechallenge` | Público |
| `POST /pub/widget/account/login`             | Público |
| `POST /pub/widget/vendors/vtex/securelogin`  | Público |
| `POST /pub/widget/vendors/fbits/securelogin` | Público |

***

## Autenticação via Token por E-mail (Challenge)

Método universal de autenticação em **duas etapas**: o consumidor informa o e-mail, recebe um código de verificação de 6 dígitos, e valida o código para obter o `SecureToken`.

**Ideal para:** lojas próprias, apps mobile, plataformas sem integração nativa, ou qualquer cenário onde você quer uma autenticação independente de plataforma de e-commerce.

### Etapa 1: Solicitar Código de Verificação

Envia um código de 6 dígitos para o e-mail do consumidor.

#### Requisição

`POST /pub/widget/account/challenge`

**Headers**

<ParamField header="X-Bq-Tenant" type="string" required>
  Identificador público da loja.
</ParamField>

**Body**

<ParamField body="email" type="string" required>
  E-mail do consumidor que receberá o código de verificação.
</ParamField>

#### Exemplo de Request

```bash theme={null}
curl -X POST "https://api.bonifiq.com.br/pub/widget/account/challenge" \
  -H "X-Bq-Tenant: {tenant_key}" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "joao@email.com"
  }'
```

#### Resposta

<ResponseField name="HasError" type="boolean">
  Indica se houve erro na requisição.
</ResponseField>

<ResponseField name="Message" type="string">
  Mensagem de erro, se aplicável.
</ResponseField>

```json theme={null}
{
  "HasError": false,
  "Message": null,
  "Item": null
}
```

<Note>
  Uma resposta sem erro indica que o código foi enviado ao e-mail. O consumidor deve verificar a caixa de entrada (e spam).
</Note>

<Warning>
  O código de verificação expira em **10 minutos**. Se expirar, solicite um novo código refazendo esta etapa.
</Warning>

***

### Etapa 2: Validar Código e Obter SecureToken

Valida o código de 6 dígitos informado pelo consumidor e retorna o `SecureToken`.

#### Requisição

`POST /pub/widget/account/validatechallenge`

**Headers**

<ParamField header="X-Bq-Tenant" type="string" required>
  Identificador público da loja.
</ParamField>

**Body**

<ParamField body="email" type="string" required>
  E-mail do consumidor (o mesmo usado na etapa 1).
</ParamField>

<ParamField body="code" type="string" required>
  Código de verificação de 6 dígitos recebido pelo consumidor no e-mail.
</ParamField>

#### Exemplo de Request

```bash theme={null}
curl -X POST "https://api.bonifiq.com.br/pub/widget/account/validatechallenge" \
  -H "X-Bq-Tenant: {tenant_key}" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "joao@email.com",
    "code": "482910"
  }'
```

#### Resposta

<ResponseField name="HasError" type="boolean">
  Indica se houve erro na requisição.
</ResponseField>

<ResponseField name="Message" type="string">
  Mensagem de erro, se aplicável.
</ResponseField>

<ResponseField name="Item" type="object">
  <Expandable title="Propriedades">
    <ResponseField name="Email" type="string">
      E-mail do consumidor.
    </ResponseField>

    <ResponseField name="Name" type="string">
      Nome completo do consumidor.
    </ResponseField>

    <ResponseField name="UserId" type="string">
      Identificador do consumidor.
    </ResponseField>

    <ResponseField name="SecureToken" type="string">
      Token de segurança para uso nas requisições autenticadas. Válido por 60 minutos.
    </ResponseField>
  </Expandable>
</ResponseField>

```json theme={null}
{
  "HasError": false,
  "Message": null,
  "Item": {
    "Email": "joao@email.com",
    "Name": "João Silva",
    "UserId": "joao@email.com",
    "SecureToken": "742b9b93-c1dc-4ec1-8f92-6b3a1838c613"
  }
}
```

#### Cenários de Erro

| Cenário                   | `HasError` | `Message`                                |
| ------------------------- | :--------: | ---------------------------------------- |
| Código inválido           |   `true`   | Código de verificação inválido           |
| Código expirado (>10 min) |   `true`   | Código expirado. Solicite um novo código |
| E-mail não encontrado     |   `true`   | Consumidor não encontrado                |

***

## Autenticação via Plataformas (Wake e VTEX)

Autenticação transparente que usa a sessão que o consumidor **já tem** na plataforma de e-commerce. Não exige interação do usuário — acontece em background.

**Ideal para:** lojas que rodam em **VTEX** ou **Wake** onde o consumidor já está logado na plataforma.

**Como funciona:** A API da BonifiQ consulta a plataforma usando os tokens de sessão do consumidor para validar a identidade. Se o consumidor estiver logado, o login seguro é bem-sucedido e retorna o `SecureToken`.

***

### Login Seguro VTEX

Autentica um consumidor que já está logado na plataforma VTEX, utilizando os tokens de sessão da VTEX.

#### Requisição

`POST /pub/widget/vendors/vtex/securelogin`

**Headers**

<ParamField header="X-Bq-Tenant" type="string" required>
  Identificador público da loja.
</ParamField>

**Body**

<ParamField body="sessionToken" type="string" required>
  Token de sessão gerado pela VTEX após o login do consumidor.
</ParamField>

<ParamField body="segmentToken" type="string" required>
  Token de segmento gerado pela VTEX.
</ParamField>

<Note>
  Na VTEX, os tokens `sessionToken` e `segmentToken` são gerados automaticamente quando o consumidor faz login. Eles podem ser obtidos via [Session Manager da VTEX](https://developers.vtex.com/docs/guides/api-authentication-using-user-tokens) ou através dos cookies de sessão.
</Note>

#### Exemplo de Request

```bash theme={null}
curl -X POST "https://api.bonifiq.com.br/pub/widget/vendors/vtex/securelogin" \
  -H "X-Bq-Tenant: {tenant_key}" \
  -H "Content-Type: application/json" \
  -d '{
    "sessionToken": "<session_token>",
    "segmentToken": "<segment_token>"
  }'
```

#### Resposta

<ResponseField name="HasError" type="boolean">
  Indica se houve erro na requisição.
</ResponseField>

<ResponseField name="Message" type="string">
  Mensagem de erro, se aplicável.
</ResponseField>

<ResponseField name="Item" type="object">
  <Expandable title="Propriedades">
    <ResponseField name="Email" type="string">
      E-mail do consumidor.
    </ResponseField>

    <ResponseField name="Name" type="string">
      Nome completo do consumidor.
    </ResponseField>

    <ResponseField name="UserId" type="string">
      Identificador do consumidor na VTEX.
    </ResponseField>

    <ResponseField name="SecureToken" type="string">
      Token de segurança para uso nas requisições autenticadas. Válido por 60 minutos.
    </ResponseField>
  </Expandable>
</ResponseField>

```json theme={null}
{
  "HasError": false,
  "Message": null,
  "Item": {
    "Email": "joao@email.com",
    "Name": "João Silva",
    "UserId": "joao@email.com",
    "SecureToken": "742b9b93-c1dc-4ec1-8f92-6b3a1838c613"
  }
}
```

#### Cenários de Erro

| Cenário                       | `HasError` | `Message`                              |
| ----------------------------- | :--------: | -------------------------------------- |
| Consumidor não logado na VTEX |   `true`   | Sessão inválida ou expirada            |
| Tokens de sessão inválidos    |   `true`   | Não foi possível validar a sessão VTEX |

***

### Login Seguro Wake

Autentica um consumidor que já está logado na plataforma Wake.

#### Requisição

`POST /pub/widget/vendors/fbits/securelogin`

**Headers**

<ParamField header="X-Bq-Tenant" type="string" required>
  Identificador público da loja.
</ParamField>

**Body**

<ParamField body="CustomerToken" type="string" required>
  Token de sessão do consumidor na plataforma Wake.
</ParamField>

<Note>
  Na Wake, o `CustomerToken` é gerado automaticamente quando o consumidor faz login na loja. Ele pode ser obtido através da API de sessão da Wake ou dos cookies de autenticação.
</Note>

#### Exemplo de Request

```bash theme={null}
curl -X POST "https://api.bonifiq.com.br/pub/widget/vendors/fbits/securelogin" \
  -H "X-Bq-Tenant: {tenant_key}" \
  -H "Content-Type: application/json" \
  -d '{
    "CustomerToken": "token-de-sessao-wake..."
  }'
```

#### Resposta

<ResponseField name="HasError" type="boolean">
  Indica se houve erro na requisição.
</ResponseField>

<ResponseField name="Message" type="string">
  Mensagem de erro, se aplicável.
</ResponseField>

<ResponseField name="Item" type="object">
  <Expandable title="Propriedades">
    <ResponseField name="Email" type="string">
      E-mail do consumidor.
    </ResponseField>

    <ResponseField name="Name" type="string">
      Nome completo do consumidor.
    </ResponseField>

    <ResponseField name="UserId" type="string">
      Identificador do consumidor na Wake.
    </ResponseField>

    <ResponseField name="SecureToken" type="string">
      Token de segurança para uso nas requisições autenticadas. Válido por 60 minutos.
    </ResponseField>
  </Expandable>
</ResponseField>

```json theme={null}
{
  "HasError": false,
  "Message": null,
  "Item": {
    "Email": "maria@email.com",
    "Name": "Maria Souza",
    "UserId": "maria@email.com",
    "SecureToken": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
  }
}
```

#### Cenários de Erro

| Cenário                       | `HasError` | `Message`                              |
| ----------------------------- | :--------: | -------------------------------------- |
| Consumidor não logado na Wake |   `true`   | Sessão inválida ou expirada            |
| Token de sessão inválido      |   `true`   | Não foi possível validar a sessão Wake |

***

## Login com E-mail e Senha

Autentica um consumidor diretamente com credenciais da BonifiQ. Método alternativo para integrações que utilizam cadastro próprio no programa de fidelidade.

### Requisição

`POST /pub/widget/account/login`

**Headers**

<ParamField header="X-Bq-Tenant" type="string" required>
  Identificador público da loja.
</ParamField>

**Body**

<ParamField body="email" type="string" required>
  E-mail do consumidor.
</ParamField>

<ParamField body="password" type="string" required>
  Senha do consumidor.
</ParamField>

### Exemplo de Request

```bash theme={null}
curl -X POST "https://api.bonifiq.com.br/pub/widget/account/login" \
  -H "X-Bq-Tenant: {tenant_key}" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "joao@email.com",
    "password": "senha123"
  }'
```

### Resposta

<ResponseField name="HasError" type="boolean">
  Indica se houve erro na requisição.
</ResponseField>

<ResponseField name="Message" type="string">
  Mensagem de erro, se aplicável.
</ResponseField>

<ResponseField name="Item" type="object">
  <Expandable title="Propriedades">
    <ResponseField name="Email" type="string">
      E-mail do consumidor.
    </ResponseField>

    <ResponseField name="Name" type="string">
      Nome completo do consumidor.
    </ResponseField>

    <ResponseField name="UserId" type="string">
      Identificador do consumidor.
    </ResponseField>

    <ResponseField name="SecureToken" type="string">
      Token de segurança para uso nas requisições autenticadas. Válido por 60 minutos.
    </ResponseField>
  </Expandable>
</ResponseField>

```json theme={null}
{
  "HasError": false,
  "Message": null,
  "Item": {
    "Email": "joao@email.com",
    "Name": "João Silva",
    "UserId": "joao@email.com",
    "SecureToken": "742b9b93-c1dc-4ec1-8f92-6b3a1838c613"
  }
}
```

### Cenários de Erro

| Cenário                   | `HasError` | `Message`                  |
| ------------------------- | :--------: | -------------------------- |
| Credenciais inválidas     |   `true`   | E-mail ou senha incorretos |
| Consumidor não encontrado |   `true`   | Consumidor não encontrado  |

***

## Renovação do Token

<Warning>
  O `SecureToken` tem validade de **60 minutos**. Após a expiração, é necessário realizar um novo login para obter um novo token.
</Warning>

**Recomendação de implementação:**

1. **Intercepte erros de autenticação** — se qualquer chamada autenticada retornar status 401 ou `HasError: true` com mensagem de token expirado, refaça o login automaticamente
2. **Renovação proativa** — armazene o timestamp de quando o token foi gerado e renove antes dos 60 minutos (ex: aos 55 minutos)
3. **Transparência para o usuário** — a renovação deve ser silenciosa, sem exigir interação do consumidor

```javascript theme={null}
// Exemplo de interceptor para renovação automática (Axios)
bonifiqApi.interceptors.response.use(
  response => response,
  async error => {
    if (error.response?.status === 401) {
      // Refazer login silenciosamente
      const newToken = await refreshSecureLogin();
      bonifiqApi.defaults.headers['X-BQ-SecureToken'] = newToken;
      // Repetir a requisição original
      error.config.headers['X-BQ-SecureToken'] = newToken;
      return bonifiqApi.request(error.config);
    }
    return Promise.reject(error);
  }
);
```
