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

# Criar upsell

> Cria um upsell do tipo simple, redirect, custom ou iframe em uma ação

Cria um upsell na ação. O campo `type` define o comportamento na tela de obrigado e qual configuração adicional é obrigatória. Máximo de **10 upsells por ação**.

## Path params

<ParamField path="id" type="string" required>
  ID da ação (UUID).
</ParamField>

## Body — campos comuns

<ParamField body="type" type="string" default="simple">
  `simple`, `redirect`, `custom` ou `iframe`. Omitido = `simple`.
</ParamField>

<ParamField body="title" type="string" required>
  Título (1–255 caracteres).
</ParamField>

<ParamField body="description" type="string | null">
  Descrição (máx. 1000).
</ParamField>

<ParamField body="display_order" type="number" default="0">
  Posição no funil (menor = exibido primeiro).
</ParamField>

<ParamField body="is_active" type="boolean" default="true">
  Se o upsell entra no funil.
</ParamField>

## Body — por tipo

### `simple`

<ParamField body="simple" type="object" required>
  <Expandable title="simple">
    <ParamField body="button_text" type="string" required>Texto do botão (1–100).</ParamField>
    <ParamField body="button_url" type="string" required>URL http(s) de destino do botão (máx. 500).</ParamField>
  </Expandable>
</ParamField>

### `redirect`

<ParamField body="redirect" type="object" required>
  <Expandable title="redirect">
    <ParamField body="to" type="string" required>URL http(s) de destino.</ParamField>
    <ParamField body="timeout" type="number" default="2000">Milissegundos antes do redirecionamento automático (0–30000). `0` redireciona imediatamente.</ParamField>
  </Expandable>
</ParamField>

### `custom`

<ParamField body="custom" type="object" required>
  <Expandable title="custom">
    <ParamField body="type" type="string" required>`card` (dentro da tela final) ou `fullscreen` (tela inteira).</ParamField>

    <ParamField body="content" type="string" required>
      HTML (1–50.000 caracteres). **Sanitizado no servidor**: tags de conteúdo, `<style>`, atributos `class`/`style` e imagens http(s) são mantidos; `<script>`, `<iframe>`, event handlers e URLs `javascript:`/`data:` são removidos. A resposta retorna a versão sanitizada.
    </ParamField>

    <ParamField body="url.placeholder" type="string" required>
      Marcador no formato `{{NOME}}` (maiúsculas, números e `_`), ex.: `{{UPSELL_URL}}`. Precisa aparecer no `content`.
    </ParamField>

    <ParamField body="url.value" type="string" required>
      URL http(s) que substituirá o placeholder na renderização.
    </ParamField>
  </Expandable>
</ParamField>

### `iframe`

<ParamField body="iframe" type="object" required>
  <Expandable title="iframe">
    <ParamField body="type" type="string" required>`card` ou `fullscreen`.</ParamField>
    <ParamField body="url" type="string" required>URL http(s) carregada no iframe.</ParamField>
  </Expandable>
</ParamField>

## Erros

| HTTP  | Código                            | Quando ocorre                                                                        |
| ----- | --------------------------------- | ------------------------------------------------------------------------------------ |
| `404` | `RAFFLE_NOT_FOUND`                | Ação inexistente ou de outra conta                                                   |
| `400` | `UPSELL_LIMIT_REACHED`            | Já existem 10 upsells na ação                                                        |
| `400` | `UPSELL_SIMPLE_FIELDS_REQUIRED`   | tipo `simple` sem o objeto `simple` completo                                         |
| `400` | `UPSELL_REDIRECT_CONFIG_REQUIRED` | `redirect` sem o objeto `redirect`                                                   |
| `400` | `UPSELL_CUSTOM_CONFIG_REQUIRED`   | `custom` sem o objeto `custom`                                                       |
| `400` | `UPSELL_IFRAME_CONFIG_REQUIRED`   | `iframe` sem o objeto `iframe`                                                       |
| `400` | `UPSELL_CONFIG_TYPE_MISMATCH`     | Objeto de configuração não corresponde ao `type`                                     |
| `400` | `UPSELL_CUSTOM_CONTENT_EMPTY`     | HTML vazio após sanitização                                                          |
| `400` | `UPSELL_PLACEHOLDER_NOT_FOUND`    | Placeholder não aparece no `content`                                                 |
| `422` | `VALIDATION`                      | Formato inválido (URL, timeout fora de 0–30000, placeholder fora de `{{NOME}}` etc.) |

<RequestExample>
  ```bash redirect theme={null}
  curl -u "pb_xxx:sk_xxx" -X POST \
    -H "Content-Type: application/json" \
    -d '{
      "type": "redirect",
      "title": "Oferta relâmpago",
      "redirect": { "to": "https://upsell.cliente.digital", "timeout": 2000 }
    }' \
    "https://api.sortify.com.br/v1/raffles/{id}/upsells"
  ```

  ```bash custom theme={null}
  curl -u "pb_xxx:sk_xxx" -X POST \
    -H "Content-Type: application/json" \
    -d '{
      "type": "custom",
      "title": "Você ganhou!",
      "custom": {
        "type": "card",
        "content": "<h1>Você ganhou!</h1><a href=\"{{UPSELL_URL}}\">Entre agora!</a>",
        "url": { "placeholder": "{{UPSELL_URL}}", "value": "https://upsell.cliente.digital/" }
      }
    }' \
    "https://api.sortify.com.br/v1/raffles/{id}/upsells"
  ```

  ```bash iframe theme={null}
  curl -u "pb_xxx:sk_xxx" -X POST \
    -H "Content-Type: application/json" \
    -d '{
      "type": "iframe",
      "title": "Oferta parceira",
      "iframe": { "type": "fullscreen", "url": "https://upsell.cliente.digital/" }
    }' \
    "https://api.sortify.com.br/v1/raffles/{id}/upsells"
  ```

  ```bash simple theme={null}
  curl -u "pb_xxx:sk_xxx" -X POST \
    -H "Content-Type: application/json" \
    -d '{
      "title": "Leve mais números",
      "simple": {
        "button_text": "Quero participar",
        "button_url": "https://loja.cliente.digital/oferta"
      }
    }' \
    "https://api.sortify.com.br/v1/raffles/{id}/upsells"
  ```
</RequestExample>

<ResponseExample>
  ```json 201 theme={null}
  {
    "success": true,
    "message": "Upsell criado com sucesso",
    "data": {
      "id": "7c1d2e3f-4a5b-6c7d-8e9f-0a1b2c3d4e5f",
      "type": "redirect",
      "title": "Oferta relâmpago",
      "description": null,
      "display_order": 0,
      "redirect": { "to": "https://upsell.cliente.digital", "timeout": 2000 },
      "is_active": true,
      "created_at": "2026-07-06T12:00:00.000Z",
      "updated_at": "2026-07-06T12:00:00.000Z"
    }
  }
  ```
</ResponseExample>
