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

# Eventos de conclusão de vinculação

> Seja avisado quando seu usuário conecta uma conta, em vez de fazer polling por isso.

export const PlansAvailable = ({plans = [], maxPackRequired}) => {
  let displayPlans = plans;
  if (plans && plans.length === 1) {
    const lowerCasePlan = plans[0].toLowerCase();
    if (lowerCasePlan === "business") {
      displayPlans = ["Launch", "Business", "Enterprise"];
    } else if (lowerCasePlan === "premium") {
      displayPlans = ["Premium", "Launch", "Business", "Enterprise"];
    }
  }
  return <Note>
Available on {displayPlans.length === 1 ? "the " : ""}
{displayPlans.join(", ").replace(/\b\w/g, l => l.toUpperCase())}{" "}
{displayPlans.length > 1 ? "plans" : "plan"}.

{maxPackRequired && <span onClick={() => window.open('https://www.ayrshare.com/docs/additional/maxpack', '_self')} className="flex items-center mt-2 cursor-pointer">
 <span className="px-1.5 py-0.5 rounded text-sm" style={{
    backgroundColor: '#C264B6',
    color: 'white',
    fontSize: '12px'
  }}>
   Max Pack required
 </span>
</span>}
</Note>;
};

<PlansAvailable plans={["business"]} maxPackRequired={false} />

Quando você abre uma página de vinculação em um popup, sua própria página pode ouvir o que acontece nele:
seu usuário conectou o Reddit, ele desistiu, a conexão falhou. Você recebe um evento por
desfecho, então sua UI atualiza no momento em que acontece, e não em um timer.

Defina [`origin`](/docs/apis/profiles/create-link-session) ao criar o link, abra a
`url` retornada em um popup e ouça. Nada mais é necessário, e nada muda para
links criados sem `origin` — eles se comportam exatamente como sempre se comportaram.

<Note>
  **Usando o [widget incorporado](/docs/multiple-users/connect-widget)? Isto já está pronto para você.**
  O script recebe esses eventos e os entrega a `connect.on("success", …)` com o
  prefixo `connect:` removido — nenhum listener de `message`, nenhuma verificação de origem, nenhum polling de
  `popup.closed` para escrever. Esta página é o protocolo de transmissão por baixo, e o que você usa quando **você** é dono da
  janela: modo direto, ou um popup que você mesmo abre.
</Note>

<Note>
  Os eventos são enviados apenas para o `origin` exato que você definiu no link, e apenas para a janela
  que abriu o popup. Ainda assim, sempre verifique `event.origin` no seu listener: qualquer página pode
  enviar uma mensagem à sua janela, e a origem é a única parte de uma mensagem que não pode
  ser falsificada.
</Note>

## Os eventos

Cada mensagem enviada à sua página é um objeto no formato
`{ source: "ayrshare", version: 1, event, ... }`, e carrega `network` sempre que o evento é
sobre uma. Dois eventos não são: um `connect:closed` vindo da página de vinculação hospedada, onde ele significa que seu
usuário pressionou Done e não que uma conexão terminou, e o `connect:ready` do widget (veja
abaixo). Os desfechos que o seu próprio código sintetiza — um popup bloqueado, ou uma janela que seu usuário fechou — não
vêm de nós e carregam apenas o que você lhes der.

<Note>
  O [widget incorporado](/docs/multiple-users/connect-widget) difere em um evento. Seu `ready` anuncia
  que um slot está de pé, e não algo sobre uma rede, então ele não carrega `network` — enquanto o
  `ready` do popup nomeia a rede para a qual foi aberto. Se você trata as duas superfícies em um
  único listener, leia `network` defensivamente em `ready`.

  O widget também adiciona um motivo de `cancelled` que esta superfície nunca envia: `superseded`, quando uma segunda
  chamada de `popup()` substitui uma tentativa ainda em andamento. Aqui há uma janela e um desfecho, então
  não há nada a substituir.
</Note>

| Evento              | Campos extras                        | Enviado quando                                                                                                                                                                                                                  |
| ------------------- | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `connect:ready`     |                                      | A página carregou e o link foi verificado.                                                                                                                                                                                      |
| `connect:started`   |                                      | Seu usuário foi enviado à rede social.                                                                                                                                                                                          |
| `connect:selection` | `step`                               | Um seletor ou formulário está na tela — seu usuário tem algo a fazer.                                                                                                                                                           |
| `connect:success`   | `refId`, `displayName`               | A conta está conectada **e salva**. `refId` é o User Profile ao qual ela foi conectada. `displayName` é o nome da conta, e é omitido quando ainda não temos um.                                                                 |
| `connect:error`     | `message`, e `code` quando existe um | A conexão falhou. `code` corresponde à [referência de erros](/docs/errors/overview); ele está ausente quando a falha não tem código catalogado, e em qualquer desfecho que o seu próprio snippet sintetiza, como um popup bloqueado. |
| `connect:cancelled` | `reason`                             | Seu usuário desistiu. `reason` é `popupClosed`, `scopesDenied` ou `userCancelled`.                                                                                                                                              |
| `connect:closed`    |                                      | O popup está prestes a se fechar sozinho. Não carrega `network` quando vem da página de vinculação hospedada, onde significa que seu usuário pressionou Done e não que uma conexão terminou.                                    |

Exatamente um entre `connect:success`, `connect:error` ou `connect:cancelled` chega por
conexão. `connect:closed` não é um deles — ele vem depois, para dizer que o popup fechou
de propósito.

`connect:success` é enviado somente depois que a conta foi salva, então um
[`GET /user`](/docs/apis/user/profile-details) logo em seguida já mostra a conta conectada.

<Note>
  O popup permanece aberto após `connect:error` para que seu usuário possa ler o que deu errado. Ele
  se fecha sozinho após `connect:success` e `connect:cancelled`. Adicione `&autoClose=false` à
  URL para mantê-lo aberto em todos os casos enquanto você estiver depurando.
</Note>

## Ouvindo

Duas coisas que este snippet faz e que são fáceis de deixar de fora. Ele verifica `event.origin` e
observa um popup que seu usuário fechou manualmente — uma janela fechada não pode enviar nada, então
polling é a única forma de perceber.

```javascript theme={"system"}
function connectAccount(url) {
  // Derive the origin from the URL you were given rather than hard-coding one:
  // if your account uses its own linking domain, the popup runs on that.
  const popupOrigin = new URL(url).origin;

  const popup = window.open(url, "ayrshare-connect", "width=600,height=800");
  if (!popup) {
    handleOutcome({ event: "connect:error", message: "The popup was blocked." });
    return;
  }

  // Declared before anything can call `cleanup`: a message arriving early would
  // otherwise hit `poll` in its temporal dead zone and throw.
  let poll;

  const cleanup = () => {
    clearInterval(poll);
    window.removeEventListener("message", onMessage);
  };

  const onMessage = event => {
    // Both checks, not just the origin: another tab or frame on the same origin
    // could otherwise post a message your handler would believe.
    if (event.origin !== popupOrigin || event.source !== popup) return;
    const message = event.data;
    if (!message || message.source !== "ayrshare") return;

    if (["connect:success", "connect:error", "connect:cancelled"].includes(message.event)) {
      // `finally`, so your own handler throwing cannot leave the poll running —
      // it would later see the closed popup and report `cancelled` on top of the
      // outcome you already had. Cleanup also matters after `connect:error`,
      // where the popup stays open so your user can read it.
      try {
        handleOutcome(message);
      } finally {
        cleanup();
      }
    }
  };
  window.addEventListener("message", onMessage);

  // A hand-closed popup sends nothing, so watch for it. Wait a moment before
  // deciding: the popup closes itself right after sending, and the message can
  // still be in flight when you first see the window go.
  let closedAt = null;
  poll = setInterval(() => {
    if (!popup.closed) return;
    if (closedAt === null) {
      closedAt = Date.now();
      return;
    }
    if (Date.now() - closedAt < 750) return;

    cleanup();
    handleOutcome({ event: "connect:cancelled", reason: "popupClosed" });
  }, 500);
}
```

## Erros

`connect:error` carrega os mesmos códigos que o resto da API, então um código que você vê aqui significa
o que ele significa em todos os outros lugares. O único específico desta superfície:

| Code  | Significado                                                                                                                                                                                                             |
| ----- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `513` | O link foi aberto como uma janela de conexão de rede única, mas não foi criado para uma. Só é alcançável se você mesmo construir essa URL — a `url` que este endpoint retorna sempre corresponde ao link que ele criou. |

Qualquer outra coisa é uma falha da própria rede social, reportada com o código que essa
falha já tem — por exemplo `322` para um problema de autorização do Instagram, o que
inclui uma conta que ainda é Pessoal em vez de Profissional.

### Um link morto chega de forma diferente

Um link **expirado**, **revogado** ou **desconhecido** é recusado antes de a página poder saber
para onde enviar eventos, então ele não pode enviar nenhum. Seu usuário vê o motivo e o código na
tela, e sua página ouve `connect:cancelled` quando ele fecha a janela.

Para distingui-los, faça polling em [Consultar uma Link Session](/docs/apis/profiles/get-link-session): ela reporta
`expired` e `revoked` de forma autoritativa, e retorna `502` para um link que não existe.

## Se você prefere não gerenciar um popup

Duas opções, e só a segunda abre mão dos eventos.

**Deixe o widget ser dono da janela.** O [widget incorporado](/docs/multiple-users/connect-widget) a abre e
observa por você e entrega todos os eventos acima aos seus handlers. Você ainda recebe `success` no
momento em que uma conta é salva; você só não escreve o encanamento. Seus frames também significam que a maioria das redes
nunca abre popup algum até o login da própria rede.

**Faça polling em vez disso.** Se um popup genuinamente não está disponível — um app renderizado no servidor, ou um app mobile
abrindo o link no navegador do sistema — faça polling em
[Consultar uma Link Session](/docs/apis/profiles/get-link-session). Ela reporta `completedAt` e
`completedNetworks` assim que uma conta é salva, que é o mesmo momento em que `connect:success`
teria sido enviado. O Telegram sempre termina desta forma, já que ele conclui fora do fluxo, sem
nenhum callback de navegador.
