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

# Створення Link Session

> Створіть URL для прив'язки соціальних мереж для User Profile без надсилання приватного ключа.

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

Створіть URL для прив'язки соціальних мереж для User Profile. Надішліть повернутий `url`
вашому користувачу, і він відкриє його, щоб підключити свої соціальні акаунти.

Це рекомендований спосіб створення URL для підключення. Потрібні лише ваш API Key і
`Profile-Key` — немає приватного ключа для надсилання й нічого підписувати. На відміну від
URL для підключення, створеного раніше, link session зберігається, тож ви можете перевірити,
чи його використовували, і відкликати його до завершення строку дії.

Повернутий `url` авторизує вашого користувача в його профілі, тож ставтеся до нього як до
пароля й надсилайте кожен лише одному користувачу. Див.
[Надсилання URL зв'язування](/docs/apis/profiles/social-linking-overview#sending-the-linking-url).

<Note>
  URL дійсний **5 хвилин** за замовчуванням. Використовуйте `expiresIn`, щоб установити
  інше вікно, до 2880 хвилин (48 годин).
</Note>

<Info>
  [Генерація URL для підключення](/docs/apis/profiles/generate-jwt) виконує ту саму операцію і
  продовжує працювати без змін. Вона приймає застарілі параметри `privateKey`, `base64` і
  `verify` та ігнорує їх. `domain` не ігнорується на жодному з ендпоінтів — він залишається
  необов'язковим і досі валідується. Нові інтеграції мають використовувати цей ендпоінт.

  Одна відмінність у відповіді: `generateJWT` повертає `token` на верхньому рівні для
  зворотної сумісності, а цей ендпоінт не повертає його **поруч** із `url` — токен у `url`
  живе всередині нього. Якщо ви мігруєте і ваш код читає `token`, читайте натомість `url`.
  ([Режим connect](#connect-mode) для вбудованого віджета — єдина форма, яка повертає голий
  `token`, оскільки вона не повертає URL, у якому токен міг би жити.)
</Info>

## Header Parameters

<HeaderAPI profileKeyRequired={true} />

<Note>
  `Profile-Key` на цьому ендпоінті — заголовок; body-параметра `profileKey` немає. Якщо він
  відсутній, ви отримаєте `code: 188`, повідомлення якого перелічує `privateKey`,
  `profileKey` та інші застарілі назви полів, оскільки воно спільне з
  [Генерацією URL для підключення](/docs/apis/profiles/generate-jwt). Читайте його як «заголовок
  Profile-Key відсутній або неправильний»; жодна з інших назв у ньому не є параметром цього
  ендпоінта.
</Note>

<ParamField header="X-Twitter-OAuth1-Api-Key" type="string">
  Ваш X API Key (Consumer Key) з X Developer Portal. Якщо вказано, URL для підключення
  використовуватиме ваш власний X Developer App для OAuth-прив'язки.
</ParamField>

<ParamField header="X-Twitter-OAuth1-Api-Secret" type="string">
  Ваш X API Secret (Consumer Secret) з X Developer Portal. Обов'язково, коли надано
  `X-Twitter-OAuth1-Api-Key`.
</ParamField>

<h2 id="body-parameters">
  Body Parameters
</h2>

<ParamField body="mode" type="string" default="grid">
  Яку поверхню зв'язування обслуговує ця сесія.

  * `grid` — хостована сторінка зв'язування, що показує кожну мережу, яку ви дозволяєте. Це
    значення за замовчуванням, тож запит, який пропускає `mode`, створює саме таку сесію.
  * `connect` — одна мережа за раз, відкрита з вашої власної панелі керування. Див.
    [Режим connect](#connect-mode) нижче та [прямий режим](/docs/multiple-users/connect-direct-mode).

  Ніколи не виводиться автоматично: передача `origin` чи `network` не переводить вас у режим
  connect, тож сесія grid не може випадково стати обмеженою. Будь-яке інше значення повертає
  `code: 188` із `details`, що називає ці два.
</ParamField>

<ParamField body="expiresIn" type="number" default={5}>
  Тривалість дії посилання в хвилинах. Діапазон: від 1 до 2880 хвилин.

  Потребує Max Pack.

  Див. [Строк дії посилання](/docs/apis/profiles/social-linking-overview#jwt-expires-in) для отримання додаткової інформації.
</ParamField>

<ParamField body="logout" type="boolean" default={false}>
  Автоматично завершувати поточну сесію. Не рекомендується використовувати у продакшені,
  оскільки це впливає на продуктивність.

  Див. [Automatic Logout of a Profile Session](/docs/multiple-users/api-integration-business#automatic-logout-of-a-profile-session).
</ParamField>

<ParamField body="redirect" type="string">
  URL для перенаправлення при натисканні кнопки "Done" (Готово) або зображення логотипа.
  Додайте query-параметр `origin=true`, щоб перенаправити вікно opener.
</ParamField>

<ParamField body="allowedSocial" type="array">
  Соціальні мережі, які відображатимуться на сторінці прив'язки. Перевизначає мережі,
  налаштовані на сторінці [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">
  Лише режим connect. Єдина соціальна мережа, яку підключає ця сесія, — саме це робить її
  сесією **прямого режиму**. Пропустіть його для сесії, яку ваша власна панель керування веде
  через кілька мереж.

  Одне зі значень `bluesky`, `facebook`, `gmb`, `instagram`, `instagramApi`, `linkedin`,
  `pinterest`, `reddit`, `snapchat`, `telegram`, `threads`, `tiktok`, `twitter`, `whatsapp`,
  `x`, `youtube`. Будь-що інше повертає `code: 508` — включно з `fbg`, який тут не є ціллю
  зв'язування.

  Не можна поєднувати з `allowedSocial` (`code: 507`): сесія однієї мережі вже сама собі
  allowlist. Мережа, яку ваш акаунт не ввімкнув, повертає `code: 509` — це інша відповідь, ніж
  508, бо її можна виправити на вашій сторінці
  [Social Networks](/docs/multiple-users/manage-user-profiles#set-social-networks-access).

  У режимі grid ігнорується.
</ParamField>

<ParamField body="instagramLinkMethod" type="string">
  Перевизначити, який потік прив'язки Instagram використовується для цього посилання.
  Допустимі значення:

  * `instagram`: Direct Instagram Login, Facebook Page не потрібна.
  * `facebook`: прив'язка Instagram через підключену Facebook Page.

  Якщо не вказано, сторінка прив'язки використовує ваше загальне для облікового запису
  налаштування [Instagram Login](/docs/multiple-users/manage-user-profiles#instagram-login).
</ParamField>

<ParamField body="origin" type="string">
  Точний origin сторінки, яка відкрила вікно зв'язування, щоб їй можна було повідомити, коли
  зв'язування завершиться.

  Коли задано, сторінка зв'язування надсилає події на цей origin через `window.postMessage`,
  поки ваш користувач підключає кожен акаунт, і ваша сторінка може реагувати без опитування.
  Події надсилаються лише на це точне значення, тож воно має збігатися з origin вашої сторінки
  символ у символ, включно зі схемою та будь-яким портом.

  Приймаються три форми: origin `https` (`https://app.example.com`), `http://localhost:3000`
  для локальної розробки та нативна власна схема (`myapp://connected`). Будь-що інше —
  звичайний origin `http://`, окрім localhost, або щось, що взагалі не є origin, — на
  посиланнях, які створює цей ендпоінт, ігнорується: посилання все одно працює, воно просто не
  надсилає подій. Параметр необов'язковий, тож його пропуск теж не є помилкою.

  З цих трьох лише перші дві форми отримують події. Власна схема — це ціль повернення для
  мобільного застосунку, і вона **не може їх отримувати**, бо немає вікна браузера, куди
  надсилати; нативні застосунки натомість опитують
  [Отримання Link Session](/docs/apis/profiles/get-link-session).

  Див. [Події завершення зв'язування](/docs/multiple-users/link-completion-events).

  **У режимі connect `origin` обов'язковий, і він перевіряється.** Описана вище поблажливість —
  поведінка режиму grid. З `mode: "connect"` його пропуск повертає `code: 505`, а значення, яке
  не є однією з трьох прийнятних форм, повертає `code: 506`, чиї `details` повторюють форму,
  яку ви надіслали.
</ParamField>

<ParamField body="domain" type="string">
  Необов'язковий. Ваш домен для підключення, якщо ваш акаунт має більше ніж один. Якщо не
  вказано, використовується власний домен вашого акаунта. Домен, не зареєстрований на ваш
  акаунт, відхиляється.
</ParamField>

<ParamField body="email" type="object">
  Надіслати Connect Accounts email з посиланням, щоб ваш користувач міг безпосередньо
  перейти до своєї сторінки прив'язки. Потребує адреси `to`.

  Потребує Max Pack. Відповідь повідомляє результат у полі `emailSent`. Якщо email не вдалося надіслати, ви все одно отримуєте посилання: відповідь містить `emailSent: false` і об'єкт `emailError`, тож ви можете передати посилання користувачу іншим способом.

  Див. [Connect Accounts Email](/docs/apis/profiles/social-linking-overview#connect-accounts-email).
</ParamField>

<h2 id="connect-mode">
  Режим connect
</h2>

`mode: "connect"` створює сесію для поверхні зв'язування, яку ви хостите самостійно, а не для
хостованої сторінки зв'язування. Яку з двох форм connect ви отримаєте, залежить від одного —
чи передаєте ви `network`:

| Ви надсилаєте | Ви отримуєте назад | Що ви з цим робите |
| - | - | - |
| `mode: "connect"` і `network` | `url`, що вказує на сторінку підключення однієї мережі | відкриваєте його у спливаючому вікні — це [прямий режим](/docs/multiple-users/connect-direct-mode) |
| `mode: "connect"` без `network` | `token` і жодного URL | передаєте його своєму власному фронтенду |

<Note>
  **Відповідь несе секрет рівно один раз.** Відповідь має або `url`, або `token` — ніколи обидва
  й ніколи два URL. Токен у сесії прямого режиму живе всередині `url`, так само як у режимі
  grid; сесія без URL, який міг би його нести, повертає натомість голий `token`. Усе інше
  однакове в усіх трьох режимах: `sessionId`, `expiresAt`, `emailSent` і `title`, коли User
  Profile його має.
</Note>

### Що вимагає режим connect

Жодна з цих двох речей не є окремим полем тіла — перша є правом акаунта, а друга — параметром
[`origin`](#body-parameters) вище, який режим connect робить обов'язковим.

**[Max Pack](/docs/additional/maxpack).** Без нього виклик повертає `code: 504`, який перевіряється до
параметрів режиму connect, тож виправлення `origin` чи `network` не змінить відповіді. Зверніться
до підтримки, якщо вам потрібно ввімкнути режим connect на акаунті без Max Pack.

**`origin`, на кожній сесії.** Немає allowlist і кроку реєстрації — ви надсилаєте його з кожним
викликом, і він зберігається на сесії, тож нове середовище не потребує жодних налаштувань на
нашому боці. Приймаються три форми:

* origin `https` — `https://app.example.com`
* нативна власна схема — `myapp://connected`
* `http://localhost` або `http://localhost:3000`, для локальної розробки

Лише origin: без шляху, query чи фрагмента і без облікових даних у ньому. Його пропуск повертає
`code: 505`, а будь-що, що не є однією з трьох форм, повертає `code: 506`.

<Warning>
  `email` не можна використовувати із сесією без `network`, бо немає посилання, яке можна
  вкласти в лист — ця форма повертає токен для вашого власного фронтенду. Виклик повертає
  `code: 510`. Додайте `network` для сесії прямого режиму, яка таки має URL, або пропустіть
  `email`.
</Warning>

Кожен названий вище код є в довіднику
[Помилки 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 with no emailError means no email was requested.
      "title": "Acme Client"  // The User Profile's title. Omitted when the profile has none.
  }
  ```

  ```json 200: Email Failed to Send theme={"system"}
  {
      "status": "success",
      "sessionId": "c7a2434e72e91bde27579efde0fd6dd0b74ceee29a471fd368407f273708c2e8",
      "url": "https://profile.ayrshare.com?session=ayr_ls_kJ8mQ2vX9pLnR4tYwZ6aBcD1eFgH3iJkLmN0oPqRsTu&domain=YOUR_DOMAIN",  // Still valid. Send it to your user yourself.
      "expiresAt": "2026-09-02T08:03:26.838Z",
      "emailSent": false,
      "emailError": {  // Only present when an email was requested and could not be sent.
          "code": 333,
          "message": "Email failed to send. Please confirm a valid email was provided."
      },
      "title": "Acme Client"
  }
  ```

  ```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>


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