> ## Documentation Index
> Fetch the complete documentation index at: https://developer.pagou.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Referência do SDK v3

> Use a API do SDK v3 da Pagou para montar campos hospedados de cartão, enviar pagamentos e tratar 3D Secure.

Use esta página quando precisar do contrato exato do SDK de navegador para Payment Element v3.

## Carregue o SDK

```html theme={null}
<script src="https://js.pagou.ai/payments/v3.js"></script>
```

O script expõe `window.Pagou`.

```js theme={null}
Pagou.setEnvironment("sandbox");
```

Ambientes suportados:

| Ambiente     | Uso                                            |
| ------------ | ---------------------------------------------- |
| `production` | Padrão. Usa endpoints de coleta de produção.   |
| `sandbox`    | Use com chaves públicas e transações de teste. |
| `local`      | Apenas desenvolvimento local.                  |

## Inicialize Elements

```js theme={null}
const elements = Pagou.elements({
  publicKey: "pk_test_sua_chave_publica",
  locale: "pt-BR",
  origin: window.location.origin,
});
```

Opções:

| Opção       | Obrigatória          | Descrição                                                                                |
| ----------- | -------------------- | ---------------------------------------------------------------------------------------- |
| `publicKey` | Sim, antes do submit | Chave pública da empresa. Use `pk_test_*` em sandbox e `pk_live_*` em produção.          |
| `locale`    | Não                  | Locale enviado ao campo hospedado de cartão. O padrão é `pt-BR`.                         |
| `origin`    | Não                  | Origem do checkout armazenada na sessão do Element. O padrão é `window.location.origin`. |

Você pode atualizar uma instância existente antes do submit:

```js theme={null}
elements.update({
  publicKey: "pk_live_sua_chave_publica",
  locale: "pt-BR",
});
```

## Crie e monte o campo de cartão

```html theme={null}
<div id="card-element"></div>
```

```js theme={null}
const card = elements.create("card", {
  theme: "default",
  locale: "pt-BR",
});

card.mount("#card-element");
```

`elements.create("card")` cria um campo hospedado de cartão. Se já existir um campo de cartão na mesma instância de `elements`, o SDK desmonta o campo anterior antes de criar o novo.

Opções do cartão:

| Opção            | Descrição                                                                              |
| ---------------- | -------------------------------------------------------------------------------------- |
| `theme`          | `default`, `night` ou `flat`.                                                          |
| `locale`         | Sobrescreve o locale de Elements para este campo.                                      |
| `style`          | Objeto de estilo enviado ao campo hospedado.                                           |
| `mountTimeoutMs` | Timeout de montagem em milissegundos. O padrão é `8000`.                               |
| `telemetry`      | Envia telemetria best-effort de falha de montagem quando suportado. O padrão é `true`. |

## Eventos do cartão

```js theme={null}
card.on("ready", () => {
  messageEl.textContent = "";
});

card.on("change", (event) => {
  submitButton.disabled = !event.valid;
  brandEl.textContent = event.brand ?? "";
  errorEl.textContent = Object.values(event.errors ?? {})[0] ?? "";
});

card.on("error", (event) => {
  errorEl.textContent = event.message;
});
```

Eventos suportados:

| Evento   | Payload                    | Uso                                                           |
| -------- | -------------------------- | ------------------------------------------------------------- |
| `ready`  | `{}`                       | O iframe hospedado carregou e concluiu o handshake com o SDK. |
| `change` | `{ valid, brand, errors }` | Habilite o submit apenas quando `valid` for `true`.           |
| `error`  | `{ code, message }`        | Exiba erros de inicialização, montagem ou campo de cartão.    |

Remova handlers durante o teardown do componente quando a mesma instância de cartão puder continuar viva:

```js theme={null}
card.off("change", handleCardChange);
```

## Envie um pagamento

`elements.submit(...)` é a ação principal do SDK. Ela cria uma sessão de Element, tokeniza o campo hospedado, chama seu callback `createTransaction`, conclui qualquer autenticação de cartão que o pagamento exija e resolve o resultado final.

```js theme={null}
const result = await elements.submit({
  createTransaction: async (tokenData) => {
    const response = await fetch("/api/pay", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        external_ref: "order_2001",
        amount: 2490,
        currency: "BRL",
        method: "credit_card",
        token: tokenData.token,
        installments: 1,
      }),
    });

    const payload = await response.json();
    return payload.data ?? payload;
  },
});
```

`createTransaction` recebe:

```json theme={null}
{
  "token": "pgct_token_from_browser",
  "brand": "visa",
  "last4": "4242",
  "exp_month": "12",
  "exp_year": "2029"
}
```

Envie apenas `token` ao seu back-end como credencial de pagamento. Trate `brand`, `last4`, `exp_month` e `exp_year` como metadados para exibição ou bookkeeping.

## Resultado do submit

```json theme={null}
{
  "status": "pending",
  "transaction": {
    "id": "018f1f2e-7b43-7c9a-8d3e-1a2b3c4d5e70",
    "status": "pending"
  }
}
```

Valores possíveis de `status` incluem:

| Status                | Significado                                                                                                                                                                                                |
| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Status da transaction | Quando nada mais é necessário, o SDK retorna o status da transaction vindo do seu back-end.                                                                                                                |
| `completed`           | Fallback quando a resposta do back-end não tem `status`.                                                                                                                                                   |
| `processing`          | O pagamento ainda está sendo resolvido. Aguarde webhook ou reconciliação.                                                                                                                                  |
| `requires_action`     | Ainda há ação necessária e o tratamento automático está desabilitado para a sessão do Element.                                                                                                             |
| `requires_reentry`    | Retornado por `resume()` quando um pagamento com 3DS pré-cobrança precisa que o cartão seja reinserido após um reload. Monte um novo `CardElement` e chame `resume()` de novo com o mesmo `transactionId`. |
| `succeeded`           | O pagamento foi aprovado.                                                                                                                                                                                  |
| `failed`              | O pagamento falhou, ou a autenticação de cartão exigida não pôde ser concluída.                                                                                                                            |
| `refused`             | A autenticação do cartão foi recusada.                                                                                                                                                                     |
| `canceled`            | Comprador fechou a janela de autenticação.                                                                                                                                                                 |
| `timed_out`           | A autenticação não finalizou dentro do timeout do SDK.                                                                                                                                                     |
| `error`               | Falha de tokenização, criação de sessão, callback ou fluxo do SDK.                                                                                                                                         |

Não libere o pedido usando apenas o status do navegador. Use webhook ou reconciliação no servidor como fonte final de verdade.

## 3D Secure

`elements.submit(...)` conclui a autenticação do cartão para você quando o pagamento exige, usando o
`buyer` e os `products` que o seu servidor já envia ao criar a transaction. Você não coleta nada a
mais no navegador. Veja [3D Secure](/pt/frontend/payment-element/three-d-secure).

Retorne o payload da transaction do seu back-end sem alterações. Se ele pedir alguma ação adicional,
o SDK detecta e continua o fluxo.

Se você já criou a transaction server-side e só precisa que o SDK conclua uma ação que ela reportou,
repasse essa ação diretamente:

```js theme={null}
const result = await Pagou.handleNextAction(transaction.next_action);
```

Ou passe a transaction para uma instância de Elements:

```js theme={null}
const result = await elements.submit({
  transaction,
  createTransaction: async () => transaction,
});
```

## Retomar após um reload

Se a página recarregar ou o comprador sair no meio do pagamento, retome a mesma transaction em vez de
iniciar uma nova tentativa de checkout. `resume()` recria a sessão de Element a partir da sua chave
pública, então funciona mesmo após um carregamento completo da página.

```js theme={null}
const result = await elements.resume({
  transactionId: "018f1f2e-7b43-7c9a-8d3e-1a2b3c4d5e70",
});
```

| Opção           | Obrigatório | Descrição                    |
| --------------- | ----------- | ---------------------------- |
| `transactionId` | Sim         | Id da transaction a retomar. |

`resume()` retorna o mesmo formato de resultado de `submit()`. Ele retoma uma ação pendente quando
ainda houver uma, retorna o status terminal quando o pagamento já finalizou e retorna `processing`
quando o desfecho ainda não chegou. Persista o id da transaction antes que o comprador possa sair da
página, para tê-lo na volta.

### Reinserção do cartão (auto-heal)

Um pagamento que aguardava autenticação de cartão (3DS pré-cobrança) estava vinculado à sessão de
Element que capturou o cartão; um reload inicia uma nova sessão e o desafio original não pode mais
rodar. `resume()` **se auto-corrige** por padrão — o element/SDK cuida de toda a recuperação, igual
para checkout hospedado e integradores diretos. Sua única responsabilidade: manter um `CardElement`
montado e chamar `resume()`.

```js theme={null}
const card = elements.create("card");
card.mount("#card-element");

const result = await elements.resume({ transactionId }); // resultado terminal
```

Num desafio pré-cobrança de sessão obsoleta, `resume()` pede que o comprador reinsira o cartão no
element montado, retokeniza sob a sessão atual, substitui o desafio obsoleto, roda o novo e resolve
num status terminal. Nenhuma nova transaction é criada.

| Opção              | Obrigatória | Descrição                                                                                                                                     |
| ------------------ | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `manualReentry`    | Não         | Desativa o auto-heal. `resume()` retorna `status: "requires_reentry"` para você rodar sua própria UX de recoleta e chamar `resume()` de novo. |
| `reentryTimeoutMs` | Não         | Somente auto-heal. Quanto tempo esperar o comprador reinserir o cartão. Padrão de 3 minutos.                                                  |

<Warning>
  Apenas o mesmo cartão pode substituir o pagamento — um cartão diferente é recusado. Sem card element
  montado, ou se o comprador não reinserir dentro do tempo limite, `resume()` resolve com um resultado
  terminal claro pedindo para iniciar uma nova tentativa. Nunca entra em loop nem trava.
</Warning>

## Modo do token

Passe `mode` em `submit` para declarar a intenção da chamada e escolher o tipo de token gerado:

| `mode`             | Token                | Quando usar                                     |
| ------------------ | -------------------- | ----------------------------------------------- |
| `payment` (padrão) | `pgct_` de uso único | Cobrança avulsa                                 |
| `upsell`           | `pgpm_` reutilizável | Compra inicial + upsell one-click               |
| `subscription`     | `pgct_` de uso único | Captura de cartão para iniciar uma subscription |

```js theme={null}
// Fluxo de upsell — mesmo cartão cobrado duas vezes (inicial + upsell)
const result = await elements.submit({
  mode: "upsell",
  createTransaction: async (tokenData) => createPaymentWithToken(tokenData.token),
});
```

```js theme={null}
// Fluxo de subscription
const result = await elements.submit({
  mode: "subscription",
  createTransaction: async (tokenData) => createSubscriptionWithToken(tokenData.token),
});
```

## Cleanup

Desmonte o campo de cartão ao sair da tela de checkout:

```js theme={null}
card.unmount();
```

Destrua a instância de Elements quando o fluxo de pagamento inteiro deixar de existir:

```js theme={null}
elements.destroy();
```

## Regras de produção

* Use `pk_test_*` apenas com `Pagou.setEnvironment("sandbox")`.
* Use `pk_live_*` com o ambiente padrão de produção.
* Nunca envie dados brutos de cartão ao seu back-end.
* Nunca registre tokens `pgct_*` ou `pgpm_*`, nem dados de cartão em logs.
* Desabilite submits duplicados enquanto `elements.submit(...)` estiver em execução.
* Persista o id da transaction para poder chamar `resume(...)` após um reload.
* Retorne o payload da transaction do back-end sem remover `id`, `status` ou `next_action`.
* Trate o status do navegador como provisório até webhook ou reconciliação confirmar o estado final do pagamento.
