> ## 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.

# Criar uma Link Session

> Crie uma URL de vinculação social para um user profile, sem enviar uma chave privada.

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>;
};

export const HeaderAPI = ({noProfileKey, profileKeyRequired}) => <>
    <ParamField header="Authorization" type="string" required>
      <a href="/docs/apis/overview#authorization">API Key</a> of the Primary Profile.
      <br />
      <br />
      Format: <code>Authorization: Bearer API_KEY</code>
    </ParamField>
    {!noProfileKey && (profileKeyRequired ? <ParamField header="Profile-Key" type="string" required>
          <a href="/docs/apis/overview#profile-key-format">Profile Key</a> of a User Profile.
          <br />
          <br />
          Format: <code>Profile-Key: PROFILE_KEY</code>
        </ParamField> : <ParamField header="Profile-Key" type="string">
          <a href="/docs/apis/overview#profile-key-format">Profile Key</a> of a User Profile.
          <br />
          <br />
          Format: <code>Profile-Key: PROFILE_KEY</code>
        </ParamField>)}
  </>;

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

Crie uma URL de vinculação social para um User Profile. Envie a `url` retornada ao seu usuário,
e ele a abre para conectar suas contas sociais.

Esta é a forma recomendada de criar uma URL de vinculação. Ela precisa apenas da sua API Key e de um
`Profile-Key` — não há chave privada a enviar e nada a assinar. Diferentemente de uma URL de
vinculação criada antes, uma link session é armazenada, então você pode verificar se ela foi usada
e revogá-la antes de expirar.

A `url` retornada autentica o seu usuário no perfil dele, então trate-a como uma senha e envie
cada uma a um único usuário. Consulte
[Enviar a URL de vinculação](/docs/apis/profiles/social-linking-overview#sending-the-linking-url).

<Note>
  A URL é válida por **5 minutos** por padrão. Use `expiresIn` para definir uma janela
  diferente, de até 2880 minutos (48 horas).
</Note>

<Info>
  [Gerar uma URL de vinculação](/docs/apis/profiles/generate-jwt) realiza a mesma operação e continua
  funcionando sem alteração. Ele aceita os parâmetros legados `privateKey`, `base64` e `verify`
  e os ignora. `domain` não é ignorado em nenhum dos dois endpoints - ele continua opcional e
  ainda é validado. Novas integrações devem usar este endpoint.

  Uma diferença na resposta: o `generateJWT` retorna um `token` de nível superior por
  compatibilidade retroativa, e este endpoint não retorna um **ao lado** de uma `url` — o token em uma
  `url` vive dentro dela. Se você está migrando e seu código lê `token`, leia `url` em vez disso.
  (O [modo connect](#connect-mode) para o widget incorporado é o único formato que retorna um `token`
  puro, porque ele não retorna URL alguma para o token viver dentro.)
</Info>

## Parâmetros do cabeçalho

<HeaderAPI profileKeyRequired={true} />

<Note>
  O `Profile-Key` é um cabeçalho neste endpoint — não há um parâmetro `profileKey` no
  corpo. Se ele estiver ausente, você recebe `code: 188`, cuja mensagem lista `privateKey`,
  `profileKey` e outros nomes de campos legados porque ela é compartilhada com
  [Gerar uma URL de vinculação](/docs/apis/profiles/generate-jwt). Leia-a como "o cabeçalho Profile-Key
  está ausente ou incorreto"; nenhum dos outros nomes citados nela é um parâmetro deste endpoint.
</Note>

<ParamField header="X-Twitter-OAuth1-Api-Key" type="string">
  Sua X API Key (Consumer Key) do X Developer Portal. Quando fornecida, a URL de
  vinculação usará seu próprio X Developer App para vinculação OAuth.
</ParamField>

<ParamField header="X-Twitter-OAuth1-Api-Secret" type="string">
  Seu X API Secret (Consumer Secret) do X Developer Portal. Obrigatório quando
  `X-Twitter-OAuth1-Api-Key` for fornecido.
</ParamField>

<h2 id="body-parameters">
  Parâmetros do corpo
</h2>

<ParamField body="mode" type="string" default="grid">
  Qual superfície de vinculação esta sessão alimenta.

  * `grid` — a página de vinculação hospedada, mostrando todas as redes que você permite. Este é o padrão, então uma
    requisição que omite `mode` cria uma.
  * `connect` — uma rede de cada vez, aberta a partir do seu próprio dashboard. Consulte
    [Modo Connect](#connect-mode) abaixo e [Modo direto](/docs/multiple-users/connect-direct-mode).

  Nunca é inferido: passar `origin` ou `network` não coloca você em modo connect, então uma sessão
  grid não pode virar uma sessão com gate por acidente. Qualquer outro valor retorna `code: 188` com
  `details` nomeando os dois.
</ParamField>

<ParamField body="expiresIn" type="number" default={5}>
  Longevidade do link em minutos. Intervalo: 1 a 2880 minutos.

  Requer o Max Pack.

  Consulte [Expiração do link](/docs/apis/profiles/social-linking-overview#jwt-expires-in) para mais informações.
</ParamField>

<ParamField body="logout" type="boolean" default={false}>
  Fazer logout automático da sessão atual. Recomendamos não usar em produção, pois
  afeta o desempenho.

  Consulte [Logout automático de uma sessão de profile](/docs/multiple-users/api-integration-business#automatic-logout-of-a-profile-session).
</ParamField>

<ParamField body="redirect" type="string">
  Uma URL para redirecionar quando o botão "Done" (Concluído) ou a imagem do logotipo forem
  clicados. Adicione o parâmetro de consulta `origin=true` para redirecionar a janela de origem.
</ParamField>

<ParamField body="allowedSocial" type="array">
  As redes sociais a serem exibidas na página de vinculação. Sobrescreve as redes configuradas
  na página [Social Networks](/docs/multiple-users/manage-user-profiles#set-social-networks-access).

  ```json Only display Facebook, X/Twitter, LinkedIn, and TikTok theme={"system"}
  {
    "allowedSocial": ["facebook", "twitter", "linkedin", "tiktok"]
  }
  ```
</ParamField>

<ParamField body="network" type="string">
  Apenas no modo connect. A única rede social que esta sessão conecta, que é o que a torna uma
  sessão em **modo direto**. Omita-o para uma sessão que o seu próprio dashboard conduz por várias
  redes.

  Um de `bluesky`, `facebook`, `gmb`, `instagram`, `instagramApi`, `linkedin`, `pinterest`,
  `reddit`, `snapchat`, `telegram`, `threads`, `tiktok`, `twitter`, `whatsapp`, `x`, `youtube`.
  Qualquer outra coisa retorna `code: 508` — incluindo `fbg`, que não é um alvo de vinculação aqui.

  Não pode ser combinado com `allowedSocial` (`code: 507`): uma sessão de rede única já é sua
  própria allowlist. Uma rede que sua conta não habilitou retorna `code: 509`, que é uma resposta
  diferente de 508 porque é corrigível na sua página
  [Social Networks](/docs/multiple-users/manage-user-profiles#set-social-networks-access).

  No modo grid ele é ignorado.
</ParamField>

<ParamField body="instagramLinkMethod" type="string">
  Sobrescreve qual fluxo de vinculação do Instagram é usado para este link. Valores válidos:

  * `instagram`: Instagram Login direto, sem necessidade de Página do Facebook.
  * `facebook`: Vincular o Instagram por meio de uma Página do Facebook conectada.

  Quando omitido, a página de vinculação usa sua configuração de
  [Instagram Login](/docs/multiple-users/manage-user-profiles#instagram-login) em nível de conta.
</ParamField>

<ParamField body="origin" type="string">
  A origem exata da página que abriu a janela de vinculação, para que ela possa ser avisada quando
  a vinculação termina.

  Quando definido, a página de vinculação envia eventos para essa origem com `window.postMessage` conforme
  seu usuário conecta cada conta, e sua página pode reagir sem polling. Os eventos são
  enviados somente para esse valor exato, então ele deve corresponder à origem da sua página caractere por
  caractere, incluindo o esquema e qualquer porta.

  Três formatos são aceitos: uma origem `https` (`https://app.example.com`),
  `http://localhost:3000` para desenvolvimento local, e um esquema personalizado nativo
  (`myapp://connected`). Qualquer outra coisa — uma origem `http://` simples que não seja localhost, ou
  algo que não é uma origem de forma alguma — é ignorada nos links que este endpoint cria:
  o link ainda funciona, ele simplesmente não envia eventos. Ele é opcional, então omiti-lo também não é um
  erro.

  Dos três, apenas os dois primeiros recebem eventos. Um esquema personalizado é um alvo de retorno para
  um app mobile e **não pode recebê-los**, porque não há janela de navegador para a qual enviar;
  apps nativos fazem polling em [Consultar uma Link Session](/docs/apis/profiles/get-link-session) em vez disso.

  Consulte [Eventos de conclusão de vinculação](/docs/multiple-users/link-completion-events).

  **No modo connect, `origin` é obrigatório, e é verificado.** A leniência acima é comportamento do
  modo grid. Com `mode: "connect"`, omiti-lo retorna `code: 505` e um valor que não é um
  dos três formatos aceitos retorna `code: 506`, cujo `details` repete o formato que você enviou.
</ParamField>

<ParamField body="domain" type="string">
  Opcional. Seu domínio de vinculação, quando sua conta tem mais de um. Quando omitido, o
  domínio da sua própria conta é usado. Um domínio não registrado na sua conta é rejeitado.
</ParamField>

<ParamField body="email" type="object">
  Envie um e-mail Connect Accounts carregando o link, para que seu usuário possa acessar
  diretamente sua página de vinculação. Requer um endereço `to`.

  Requer o Max Pack. A resposta informa o resultado em `emailSent`, e uma falha no envio
  retorna `code: 333` em vez de uma resposta de sucesso.

  Consulte [E-mail de conexão de contas](/docs/apis/profiles/social-linking-overview#connect-accounts-email).
</ParamField>

<h2 id="connect-mode">
  Modo Connect
</h2>

`mode: "connect"` cria uma sessão para uma superfície de vinculação que você mesmo hospeda, em vez de para a
página de vinculação hospedada. Qual dos dois formatos connect você recebe depende de uma coisa — se você
passa `network`:

| Você envia                           | Você recebe de volta                                         | O que fazer com isso                                                             |
| ------------------------------------ | ------------------------------------------------------------ | -------------------------------------------------------------------------------- |
| `mode: "connect"` e um `network`     | uma `url` apontando para uma página de conexão de rede única | abra-a em um popup — este é o [modo direto](/docs/multiple-users/connect-direct-mode) |
| `mode: "connect"` e nenhum `network` | um `token`, e nenhuma URL                                    | entregue-o ao seu próprio front-end                                              |

<Note>
  **A resposta carrega o segredo exatamente uma vez.** Uma resposta tem ou uma `url` ou um `token`,
  nunca os dois e nunca duas URLs. O token de uma sessão em modo direto vive dentro da `url`, da
  mesma forma que no modo grid; uma sessão sem URL para carregá-lo retorna o `token` puro
  em vez disso. Todo o resto é igual nos três modos: `sessionId`, `expiresAt`, `emailSent`
  e `title` quando o User Profile tem um.
</Note>

### O que o modo connect exige

Nenhum destes é um campo do corpo por si só — o primeiro é um direito da conta e o segundo é
o parâmetro [`origin`](#body-parameters) acima, que o modo connect torna obrigatório.

**O [Max Pack](/docs/additional/maxpack).** Sem ele a chamada retorna `code: 504`, verificado antes
dos parâmetros do modo connect, então corrigir `origin` ou `network` não mudará a resposta. Entre em contato com o suporte se você
precisar do modo connect habilitado em uma conta sem o Max Pack.

**Um `origin`, em cada sessão.** Não há allowlist nem etapa de registro — você o envia em
cada chamada e ele é armazenado na sessão, então um novo ambiente não precisa de configuração do nosso lado. Três
formatos são aceitos:

* uma origem `https` — `https://app.example.com`
* um esquema personalizado nativo — `myapp://connected`
* `http://localhost` ou `http://localhost:3000`, para desenvolvimento local

Apenas a origem: sem caminho, query ou fragmento, e sem credenciais nela. Omiti-la retorna `code: 505`,
e qualquer coisa que não seja um dos três formatos retorna `code: 506`.

<Warning>
  `email` não pode ser usado com uma sessão que não tem `network`, porque não há link para colocar no
  e-mail — esse formato retorna um token para o seu próprio front-end. A chamada retorna `code: 510`.
  Adicione um `network` para uma sessão em modo direto, que tem uma URL, ou omita `email`.
</Warning>

Cada código nomeado acima está na referência de [Erros de Link Session](/docs/errors/errors-ayrshare#link-session-errors).

<RequestExample>
  ```bash cURL theme={"system"}
  curl \
  -H "Authorization: Bearer API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Profile-Key: PROFILE_KEY' \
  -d '{"expiresIn": 60}' \
  -X POST https://api.ayrshare.com/api/profiles/link-sessions
  ```

  ```javascript JavaScript theme={"system"}
  const API_KEY = "API_KEY";
  const PROFILE_KEY = "PROFILE_KEY";

  fetch("https://api.ayrshare.com/api/profiles/link-sessions", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${API_KEY}`,
      "Profile-Key": PROFILE_KEY,
    },
    body: JSON.stringify({ expiresIn: 60 }),
  })
    .then((res) => res.json())
    .then((json) => console.log(json))
    .catch(console.error);
  ```

  ```python Python theme={"system"}
  import requests

  payload = {'expiresIn': 60}
  headers = {'Content-Type': 'application/json',
          'Authorization': 'Bearer API_KEY',
          'Profile-Key': 'PROFILE_KEY'}

  response = requests.post('https://api.ayrshare.com/api/profiles/link-sessions',
                           json=payload, headers=headers)
  print(response.json())
  ```

  ```php PHP theme={"system"}
  <?php
  require 'vendor/autoload.php';    // Composer auto-loader using Guzzle. See .../guzzlephp.org/en/stable/overview.html

  $client = new GuzzleHttp\Client();
  $res = $client->request(
      'POST',
      'https://api.ayrshare.com/api/profiles/link-sessions',
      [
          'headers' => [
              'Content-Type'  => 'application/json',
              'Authorization' => 'Bearer API_KEY',
              'Profile-Key'   => 'PROFILE_KEY'
          ],
          'json' => [
              'expiresIn' => 60,
          ]
      ]
  );

  echo json_encode(json_decode($res->getBody()), JSON_PRETTY_PRINT);
  ```

  ```csharp C# theme={"system"}
  using System;
  using System.Net.Http;
  using System.Text;
  using System.Threading.Tasks;
  using Newtonsoft.Json;

  namespace CreateLinkSession_csharp
  {
    class CreateLinkSession
    {
        static async Task Main(string[] args)
        {
            string API_KEY = "API_KEY";
            string PROFILE_KEY = "PROFILE_KEY";
            string url = "https://api.ayrshare.com/api/profiles/link-sessions";

            try
            {
                using (var client = new HttpClient())
                {
                    client.DefaultRequestHeaders.Add("Authorization", "Bearer " + API_KEY);
                    client.DefaultRequestHeaders.Add("Profile-Key", PROFILE_KEY);

                    var sendData = new { expiresIn = 60 };
                    string jsonData = JsonConvert.SerializeObject(sendData);
                    var content = new StringContent(jsonData, Encoding.UTF8, "application/json");

                    HttpResponseMessage response = await client.PostAsync(url, content);
                    response.EnsureSuccessStatusCode();

                    string responseBody = await response.Content.ReadAsStringAsync();
                    Console.WriteLine(responseBody);
                }
            }
            catch (HttpRequestException e)
            {
                Console.WriteLine($"HTTP request error: {e.Message}");
            }
        }
    }
  }
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={"system"}
  {
      "status": "success",
      "sessionId": "c7a2434e72e91bde27579efde0fd6dd0b74ceee29a471fd368407f273708c2e8",  // Identifier for this link. Use it with Get and Revoke a Link Session.
      "url": "https://profile.ayrshare.com?session=ayr_ls_kJ8mQ2vX9pLnR4tYwZ6aBcD1eFgH3iJkLmN0oPqRsTu&domain=YOUR_DOMAIN",  // Send this to your user exactly as returned. The token exists only in here.
      "expiresAt": "2026-09-02T08:03:26.838Z",  // When the link stops working, as an ISO 8601 timestamp.
      "emailSent": false,  // Whether the connect-accounts email was sent. false means none was requested; a send failure returns code: 333 instead.
      "title": "Acme Client"  // The User Profile's title. Omitted when the profile has none.
  }
  ```

  ```json 200: Direct Mode (mode: "connect" with a network) theme={"system"}
  {
      "status": "success",
      "sessionId": "c7a2434e72e91bde27579efde0fd6dd0b74ceee29a471fd368407f273708c2e8",
      "url": "https://profile.ayrshare.com/connect?session=ayr_ls_kJ8mQ2vX9pLnR4tYwZ6aBcD1eFgH3iJkLmN0oPqRsTu",  // Open this in a popup. One network, no domain parameter.
      "expiresAt": "2026-09-02T08:03:26.838Z",
      "emailSent": false,
      "title": "Acme Client"
  }
  ```

  ```json 200: Connect Mode Without a Network theme={"system"}
  {
      "status": "success",
      "sessionId": "c7a2434e72e91bde27579efde0fd6dd0b74ceee29a471fd368407f273708c2e8",
      "token": "ayr_ls_kJ8mQ2vX9pLnR4tYwZ6aBcD1eFgH3iJkLmN0oPqRsTu",  // No url: this shape returns the bare token instead. Treat it like a password.
      "expiresAt": "2026-09-02T08:03:26.838Z",
      "emailSent": false,  // Always false here - email needs a link to send, so it returns code: 510.
      "title": "Acme Client"
  }
  ```

  ```json 401: Connect Mode Requires the Max Pack theme={"system"}
  {
    "action": "link session",
    "status": "error",
    "code": 504,
    "message": "Connect mode requires the Max Pack. Activate it on your Account page: https://app.ayrshare.com/account"
  }
  ```

  ```json 400: Missing Profile-Key Header theme={"system"}
  {
    "action": "JWT",
    "status": "error",
    "code": 188,
    "message": "Missing or incorrect privateKey, profileKey, domain, email 'to', or expiresIn fields."
  }
  ```

  ```json 400: Domain Not Registered to Your Account theme={"system"}
  {
    "action": "JWT",
    "status": "error",
    "code": 189,
    "message": "Error generating JWT. Check the sent parameters.",
    "details": "Missing or incorrect domain."
  }
  ```

  ```json 403: expiresIn Requires the Max Pack theme={"system"}
  {
    "action": "JWT",
    "status": "error",
    "code": 340,
    "message": "Max Pack required. Go to your dashboard to add the Max Pack."
  }
  ```
</ResponseExample>
