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

# Afiliação

> Regras de negócio, endpoints e fluxos do programa de afiliados via Nexus API.

O programa de afiliação permite que produtores adicionem usuários como afiliados de seus produtos. Afiliados recebem comissões sobre vendas realizadas por meio de seus links de divulgação.

## Endpoints

Todos os endpoints abaixo estão sob o prefixo `/api/v1/products/{product_hash}/affiliates`. Exigem autenticação via `X-Api-Client-Token` + `Authorization: Bearer <user_token>`, e o produto deve pertencer ao client autenticado.

| Método | Caminho | Ação |
| - | - | - |
| `GET` | `/affiliates` | Listar afiliados do produto |
| `POST` | `/affiliates` | Adicionar um afiliado |
| `PUT` | `/affiliates/{affiliation_code}` | Atualizar uma afiliação |
| `DELETE` | `/affiliates/{affiliation_code}` | Remover uma afiliação |
| `POST` | `/affiliates/batch` | Adicionar afiliados em lote (até 5.000) |
| `POST` | `/affiliates/batch-delete` | Remover afiliados em lote (até 5.000) |
| `PATCH` | `/affiliates/batch` | Atualizar comissão em lote (até 5.000) |
| `PATCH` | `/affiliates/commission` | Atualizar comissão de todos os afiliados |
| `POST` | `/affiliates/deactivate-all` | Desativar todos os afiliados |
| `GET` | `/affiliates/batch/{batchId}` | Consultar status de operação em lote |

***

## Adicionar afiliado individual

**Rota:** `POST /api/v1/products/{product_hash}/affiliates`

<ParamField body="user_id" type="string" required>
  Código (hash) do usuário a ser afiliado. Deve existir na base e pertencer ao mesmo client da API.
</ParamField>

<ParamField body="commission_percentage" type="number">
  Percentual de comissão individual. Min: 1, Max: 80. Se não informado, usa o padrão do produto.
</ParamField>

<Info>
  Os campos `status`, `is_active` e `origin` são preenchidos automaticamente pelo sistema. Toda afiliação criada via Nexus recebe `status = "approved"`, `is_active = true` e `origin = "nexus"`.
</Info>

### Response (200)

<ResponseField name="code" type="string">
  Hash identificador do afiliado (PID).
</ResponseField>

<ResponseField name="commission_percentage" type="number">
  Percentual de comissão configurado.
</ResponseField>

<ResponseField name="status" type="string">
  Status da afiliação.
</ResponseField>

<ResponseField name="created_at" type="string">
  Data de criação (`YYYY-MM-DD HH:mm:ss`).
</ResponseField>

***

## Atualizar afiliação

**Rota:** `PUT /api/v1/products/{product_hash}/affiliates/{affiliation_code}`

Somente o dono do produto pode atualizar afiliações. O campo `user_id` é preenchido automaticamente a partir da afiliação na rota — não é necessário enviá-lo no body.

<ParamField body="commission_percentage" type="number">
  Novo percentual de comissão. Min: 1, Max: 80.
</ParamField>

***

## Adicionar em lote

**Rota:** `POST /api/v1/products/{product_hash}/affiliates/batch`

Operação assíncrona — retorna `202` com o UUID da operação.

<ParamField body="affiliates" type="array" required>
  Lista de afiliados. Min: 1, Max: 5.000 itens.
</ParamField>

<ParamField body="affiliates[].user_id" type="string" required>
  Código (hash) do usuário a ser afiliado.
</ParamField>

<ParamField body="affiliates[].commission_percentage" type="number">
  Percentual de comissão. Min: 1, Max: 80.
</ParamField>

Consulte o progresso via `GET /affiliates/batch/{batchId}` usando o UUID retornado.

***

## Remover em lote

**Rota:** `POST /api/v1/products/{product_hash}/affiliates/batch-delete`

<ParamField body="user_ids" type="array" required>
  Lista de códigos (hashes) de usuários a remover. Min: 1, Max: 5.000.
</ParamField>

***

## Atualizar comissão em lote

**Rota:** `PATCH /api/v1/products/{product_hash}/affiliates/batch`

<ParamField body="affiliates" type="array" required>
  Lista de afiliados. Min: 1, Max: 5.000 itens.
</ParamField>

<ParamField body="affiliates[].user_id" type="string" required>
  Código (hash) do usuário afiliado.
</ParamField>

<ParamField body="affiliates[].commission_percentage" type="number" required>
  Novo percentual de comissão. Min: 1, Max: 80.
</ParamField>

***

## Atualizar comissão de todos

**Rota:** `PATCH /api/v1/products/{product_hash}/affiliates/commission`

<ParamField body="commission_percentage" type="number" required>
  Novo percentual aplicado a todos os afiliados. Min: 1, Max: 80.
</ParamField>

***

## Desativar todos

**Rota:** `POST /api/v1/products/{product_hash}/affiliates/deactivate-all`

Não recebe campos no body. Desativa todos os afiliados do produto.

***

## Consultar status de operação em lote

**Rota:** `GET /api/v1/products/{product_hash}/affiliates/batch/{batchId}`

Retorna o status da operação em lote identificada pelo `batchId` (UUID retornado nas operações batch). Inclui contadores de itens processados, com sucesso e com falha.

***

## Regras de validação

### Criação individual (`POST /affiliates`)

<Steps>
  <Step title="Produto permite afiliação">
    O campo `allow_affiliation` do produto deve ser `true`.
  </Step>

  <Step title="Produtor não pode ser afiliado">
    O `user_id` informado não pode ser o dono do produto.
  </Step>

  <Step title="Usuário pertence ao client">
    O código informado em `user_id` deve corresponder a um usuário vinculado ao mesmo client API autenticado.
  </Step>

  <Step title="Comissão entre 1% e 80%">
    Se `commission_percentage` for informado, deve estar nesse intervalo.
  </Step>

  <Step title="Status automático">
    O sistema define `status = "approved"`, `is_active = true` e `origin = "nexus"`. O client não controla esses campos.
  </Step>
</Steps>

### Operações em lote

As operações batch são processadas de forma assíncrona. Além da validação de formato (array de 1 a 5.000 itens), o processamento aplica regras adicionais **por item**:

* Produtor não pode ser adicionado como afiliado do próprio produto
* Usuário deve existir no sistema e não pode estar excluído
* Não pode haver afiliação ativa existente para o mesmo usuário naquele produto
* Coprodutores do produto são bloqueados
* Se houver afiliação pendente anterior para o mesmo usuário, ela é removida antes de criar a nova
* A afiliação é criada com status `approved` e origin `nexus`

***

## Status possíveis

| Valor | Descrição |
| - | - |
| `approved` | Afiliação ativa, pode gerar comissões. Via Nexus, toda afiliação é criada com esse status. |
| `pending` | Aguardando aprovação do produtor. Ocorre quando o afiliado solicita afiliação e o produto não tem aprovação automática. |
| `reproved` | Recusado pelo produtor. Permite que o usuário solicite afiliação novamente. |
| `pending_compliance` | Aguardando validação interna de compliance. |

***

## Configurações do produto

Os campos abaixo são gerenciados via `POST/PUT /api/v1/products/{product_hash}` e afetam o comportamento da afiliação.

<ParamField body="allow_affiliation" type="boolean">
  Liga/desliga o programa de afiliados. Quando `false`, os campos `affiliate_percentage`, `affiliation_description`, `affiliation_terms`, `first_click_percentage` e `last_click_percentage` são zerados automaticamente.
</ParamField>

<ParamField body="has_auto_affiliation" type="boolean">
  Se ativo, solicitações de afiliação são aprovadas automaticamente (sem fila de pendentes).
</ParamField>

<ParamField body="affiliate_commission_type" type="string">
  Tipo de atribuição de comissão: `first` (primeiro clique), `last` (último clique) ou `multi` (dividido entre primeiro e último). Default no Nexus: `multi`.
</ParamField>

<ParamField body="affiliate_percentage" type="number">
  Percentual padrão de comissão. Obrigatório quando `allow_affiliation = true`. Min: 1, Max: 80.
</ParamField>

<ParamField body="first_click_percentage" type="number">
  Percentual atribuído ao primeiro clique no modo `multi`. A soma com `last_click_percentage` deve ser 100%. Se apenas um for informado, o outro é calculado automaticamente.
</ParamField>

<ParamField body="last_click_percentage" type="number">
  Percentual atribuído ao último clique no modo `multi`.
</ParamField>

<ParamField body="affiliation_description" type="string">
  Descrição do programa de afiliação. Obrigatória quando `allow_affiliation = true`. Min: 50, Max: 1.000 caracteres.
</ParamField>

<ParamField body="affiliation_terms" type="string">
  Termos de afiliação exibidos ao afiliado. Obrigatório quando `allow_affiliation = true`. Min: 50, Max: 1.000 caracteres.
</ParamField>

***

## Configurações da oferta

Os campos abaixo são gerenciados via `POST/PUT /api/v1/products/{product_hash}/offers/{offer_code}`.

<ParamField body="allow_affiliates" type="boolean">
  Permite ou bloqueia afiliados naquela oferta específica.
</ParamField>

<ParamField body="affiliates_percentage" type="number">
  Percentual de comissão específico da oferta. Sobrescreve o `affiliate_percentage` do produto. Obrigatório quando `allow_affiliates = true`. Min: 1, Max: 80.
</ParamField>

<ParamField body="auto_affiliation" type="boolean">
  Auto-afiliação na oferta.
</ParamField>

<ParamField body="affiliates_subscription_percentage" type="number">
  Percentual de comissão para renovações de assinatura (apenas ofertas recorrentes). Min: 1, Max: 80.
</ParamField>

<ParamField body="custom_commission" type="boolean">
  Habilita comissão diferenciada para renovações. Quando `true`, `affiliates_subscription_percentage` passa a ser obrigatório.
</ParamField>

<ParamField body="commission_only_first_installment" type="boolean">
  Se ativo, a comissão é paga somente na primeira parcela (apenas ofertas recorrentes).
</ParamField>

***

## Fluxos

### Adicionar afiliado individual

```mermaid theme={null}
sequenceDiagram
    participant Client as Client API
    participant Nexus as Nexus
    participant Backend as Backend

    Client->>Nexus: POST /affiliates {user_id, commission_percentage}
    Nexus->>Nexus: Valida (produto permite, user pertence ao client, não é o produtor)
    Nexus->>Nexus: Resolve code → ID interno
    Nexus->>Backend: Proxy com status=approved, is_active=true
    Backend-->>Nexus: Afiliação criada + webhook disparado
    Nexus-->>Client: {code, commission_percentage, status, created_at}
```

### Adicionar em lote

```mermaid theme={null}
sequenceDiagram
    participant Client as Client API
    participant Nexus as Nexus
    participant Backend as Backend

    Client->>Nexus: POST /affiliates/batch {affiliates: [{user_id, commission_percentage}]}
    Nexus->>Nexus: Valida formato (1-5.000 itens, codes válidos)
    Nexus->>Nexus: Resolve codes → IDs internos
    Nexus->>Backend: Proxy (processamento assíncrono em fila)
    Backend-->>Nexus: 202 {uuid}
    Nexus-->>Client: 202 {uuid}
    Note over Client,Backend: Para cada item: valida, cria com approved, gera log

    Client->>Nexus: GET /affiliates/batch/{uuid}
    Nexus->>Backend: Proxy
    Backend-->>Nexus: Status da operação
    Nexus-->>Client: {status, total_items, processed, failed}
```

### Atualizar afiliação

O client envia `PUT /affiliates/{affiliation_code}`. Exige que o usuário autenticado seja o dono do produto (gate `update-affiliate`). Permite alterar `commission_percentage` e outros campos. O backend gera log de auditoria com o estado antes e depois da alteração.

### Remover afiliação

O client envia `DELETE /affiliates/{affiliation_code}`. A afiliação é removida via soft delete. O backend gera log de auditoria registrando a remoção.

### Operações em massa

`PATCH /affiliates/batch` atualiza `commission_percentage` para uma lista de afiliados. `PATCH /affiliates/commission` aplica um único percentual a todos. `POST /affiliates/deactivate-all` desativa todos os afiliados do produto. `POST /affiliates/batch-delete` remove uma lista por `user_ids`. Todas as operações batch retornam `202` e são processadas em fila.

### Autorização

<Warning>
  O endpoint `PUT /affiliates/{affiliation_code}` exige que o usuário autenticado seja o **dono do produto** (`product.user_id === user.id`). Qualquer outro usuário receberá `403 Forbidden`.
</Warning>

Todos os endpoints de afiliação exigem que o produto pertença ao client autenticado (middleware de propriedade).

***

## Restrições resumidas

<AccordionGroup>
  <Accordion title="Validação de campos">
    * `allow_affiliation` do produto deve ser `true`
    * Produtor nunca pode ser afiliado do próprio produto
    * `user_id` deve ser o código (hash) do usuário, não o ID interno
    * Comissão sempre entre **1% e 80%**
    * Operações batch: máximo **5.000 itens** por chamada
  </Accordion>

  <Accordion title="Comportamento automático">
    * Toda afiliação via Nexus recebe `status = approved` e `origin = nexus`
    * Quando `allow_affiliation` é desligado no produto, os campos de afiliação são zerados
    * No modo `multi`, se apenas `first_click_percentage` ou `last_click_percentage` for informado, o outro é calculado automaticamente para somar 100%
  </Accordion>

  <Accordion title="Processamento em lote">
    * Coprodutores e afiliações duplicadas são bloqueados por item
    * Afiliações pendentes anteriores são removidas antes de criar a nova
    * Operações batch retornam `202` e são processadas em fila
  </Accordion>
</AccordionGroup>


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