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

# Créer une Link Session

> Créez une URL de liaison sociale pour un profil d'utilisateur, sans envoyer de clé privée.

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

Créez une URL de liaison sociale pour un User Profile (profil d'utilisateur). Envoyez l'`url` retournée à votre
utilisateur, qui l'ouvre pour connecter ses comptes sociaux.

C'est la méthode recommandée pour créer une URL de liaison. Elle ne nécessite que votre clé API et une
`Profile-Key` — il n'y a aucune clé privée à envoyer et rien à signer. Contrairement à une URL de liaison
créée auparavant, une link session est stockée : vous pouvez donc vérifier si elle a été utilisée
et la révoquer avant son expiration.

L'`url` retournée connecte votre utilisateur à son profil : traitez-la comme un mot de passe et n'envoyez
chaque URL qu'à un seul utilisateur. Consultez
[Envoyer l'URL de liaison](/docs/apis/profiles/social-linking-overview#sending-the-linking-url).

<Note>
  L'URL est valide pendant **5 minutes** par défaut. Utilisez `expiresIn` pour définir une
  fenêtre différente, jusqu'à 2880 minutes (48 heures).
</Note>

<Info>
  [Générer une URL de liaison](/docs/apis/profiles/generate-jwt) réalise la même opération et continue de
  fonctionner sans changement. Il accepte les paramètres historiques `privateKey`, `base64` et `verify`
  et les ignore. `domain` n'est ignoré sur aucun des deux endpoints : il reste optionnel et est
  toujours validé. Les nouvelles intégrations devraient utiliser cet endpoint.

  Une différence dans la réponse : `generateJWT` renvoie un `token` de premier niveau pour la
  rétrocompatibilité, et cet endpoint n'en renvoie pas un **à côté** d'une `url` — le token d'une
  `url` vit à l'intérieur de celle-ci. Si vous migrez et que votre code lit `token`, lisez `url` à la place.
  (Le [mode connect](#connect-mode) pour le widget intégré est la seule forme qui retourne un
  `token` nu, car elle ne retourne aucune URL dans laquelle le token pourrait vivre.)
</Info>

## Paramètres d'en-tête

<HeaderAPI profileKeyRequired={true} />

<Note>
  La `Profile-Key` est un en-tête sur cet endpoint — il n'y a pas de paramètre de corps
  `profileKey`. Si elle est absente, vous obtenez `code: 188`, dont le message liste `privateKey`,
  `profileKey` et d'autres noms de champs historiques, car il est partagé avec
  [Générer une URL de liaison](/docs/apis/profiles/generate-jwt). Lisez-le comme « l'en-tête Profile-Key est
  absent ou incorrect » ; aucun des autres noms qu'il mentionne n'est un paramètre de cet endpoint.
</Note>

<ParamField header="X-Twitter-OAuth1-Api-Key" type="string">
  Votre clé API X (Consumer Key) provenant du X Developer Portal. Lorsqu'elle est fournie, l'URL de
  liaison utilisera votre propre application développeur X pour la liaison OAuth.
</ParamField>

<ParamField header="X-Twitter-OAuth1-Api-Secret" type="string">
  Votre secret API X (Consumer Secret) provenant du X Developer Portal. Requis lorsque
  `X-Twitter-OAuth1-Api-Key` est fourni.
</ParamField>

## Paramètres du corps

<ParamField body="mode" type="string" default="grid">
  La surface de liaison que cette session pilote.

  * `grid` — la page de liaison hébergée, affichant chaque réseau que vous permettez. C'est la
    valeur par défaut, donc une requête qui omet `mode` en crée une.
  * `connect` — un réseau à la fois, ouvert depuis votre propre tableau de bord. Consultez
    [Mode connect](#connect-mode) ci-dessous et le [mode direct](/docs/multiple-users/connect-direct-mode).

  Jamais inféré : passer `origin` ou `network` ne vous met pas en mode connect, donc une session
  grid ne peut pas devenir une session soumise à conditions par accident. Toute autre valeur retourne
  `code: 188` avec des `details` nommant les deux valeurs.
</ParamField>

<ParamField body="expiresIn" type="number" default={5}>
  Durée de vie du lien en minutes. Plage : 1 à 2880 minutes.

  Nécessite le Max Pack.

  Consultez [Expiration du lien](/docs/apis/profiles/social-linking-overview#jwt-expires-in) pour plus d'informations.
</ParamField>

<ParamField body="logout" type="boolean" default={false}>
  Déconnecte automatiquement la session en cours. Non recommandé en production, car cela
  affecte les performances.

  Consultez [Déconnexion automatique d'une session de profil](/docs/multiple-users/api-integration-business#automatic-logout-of-a-profile-session).
</ParamField>

<ParamField body="redirect" type="string">
  Une URL vers laquelle rediriger lorsque le bouton « Done » ou l'image du logo est cliqué. Ajoutez le
  paramètre de requête `origin=true` pour rediriger la fenêtre d'ouverture.
</ParamField>

<ParamField body="allowedSocial" type="array">
  Les réseaux sociaux à afficher sur la page de liaison. Remplace les réseaux configurés
  dans la page [Réseaux sociaux](/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">
  Mode connect uniquement. Le seul réseau social que cette session connecte, ce qui en fait une
  session en **mode direct**. Omettez-le pour une session que votre propre tableau de bord pilote
  sur plusieurs réseaux.

  L'une des valeurs `bluesky`, `facebook`, `gmb`, `instagram`, `instagramApi`, `linkedin`, `pinterest`,
  `reddit`, `snapchat`, `telegram`, `threads`, `tiktok`, `twitter`, `whatsapp`, `x`, `youtube`.
  Toute autre valeur retourne `code: 508` — y compris `fbg`, qui n'est pas une cible de liaison ici.

  Ne peut pas être combiné avec `allowedSocial` (`code: 507`) : une session mono-réseau est déjà sa
  propre allowlist. Un réseau que votre compte n'a pas activé retourne `code: 509`, qui est une
  réponse différente de 508 parce qu'elle est corrigeable sur votre page
  [Réseaux sociaux](/docs/multiple-users/manage-user-profiles#set-social-networks-access).

  En mode grid, il est ignoré.
</ParamField>

<ParamField body="instagramLinkMethod" type="string">
  Remplace le flux de liaison Instagram utilisé pour ce lien. Valeurs valides :

  * `instagram` : Instagram Login direct, aucune page Facebook requise.
  * `facebook` : lier Instagram via une page Facebook connectée.

  Lorsqu'omis, la page de liaison utilise votre paramètre
  [Instagram Login](/docs/multiple-users/manage-user-profiles#instagram-login) à l'échelle du compte.
</ParamField>

<ParamField body="origin" type="string">
  L'origine exacte de la page qui a ouvert la fenêtre de liaison, afin qu'elle puisse être informée
  lorsque la liaison se termine.

  Lorsqu'elle est définie, la page de liaison poste des événements à cette origine avec
  `window.postMessage` à mesure que votre utilisateur connecte chaque compte, et votre page peut
  réagir sans polling. Les événements ne sont jamais envoyés qu'à cette valeur exacte, donc elle
  doit correspondre à l'origine de votre page caractère par caractère, y compris le schéma et tout
  port éventuel.

  Trois formes sont acceptées : une origine `https` (`https://app.example.com`),
  `http://localhost:3000` pour le développement local, et un schéma personnalisé natif
  (`myapp://connected`). Toute autre valeur — une origine `http://` simple autre que localhost, ou
  quelque chose qui n'est pas du tout une origine — est ignorée sur les liens que cet endpoint
  crée : le lien fonctionne toujours, il n'envoie simplement aucun événement. Le paramètre est
  optionnel, donc l'omettre n'est pas une erreur non plus.

  Des trois, seules les deux premières reçoivent des événements. Un schéma personnalisé est une
  cible de retour pour une application mobile et **ne peut pas en recevoir**, car il n'y a pas de
  fenêtre de navigateur à laquelle poster ; les applications natives pollent
  [Obtenir une session de liaison](/docs/apis/profiles/get-link-session) à la place.

  Consultez [Événements de fin de liaison](/docs/multiple-users/link-completion-events).

  **En mode connect, `origin` est requis, et il est vérifié.** La tolérance ci-dessus est le
  comportement du mode grid. Avec `mode: "connect"`, l'omettre retourne `code: 505` et une valeur
  qui n'est pas l'une des trois formes acceptées retourne `code: 506`, dont les `details` répètent
  la forme que vous avez envoyée.
</ParamField>

<ParamField body="domain" type="string">
  Optionnel. Votre domaine de liaison, lorsque votre compte en possède plusieurs. S'il est omis, le
  domaine propre à votre compte est utilisé. Un domaine non enregistré sur votre compte est rejeté.
</ParamField>

<ParamField body="email" type="object">
  Envoie un e-mail Connect Accounts contenant le lien, afin que votre utilisateur accède directement
  à sa page de liaison. Nécessite une adresse `to`.

  Nécessite le Max Pack. La réponse indique le résultat dans `emailSent`, et un échec
  d'envoi retourne `code: 333` au lieu d'une réponse de succès.

  Consultez [E-mail Connect Accounts](/docs/apis/profiles/social-linking-overview#connect-accounts-email).
</ParamField>

<h2 id="connect-mode">
  Mode connect
</h2>

`mode: "connect"` crée une session pour une surface de liaison que vous hébergez vous-même, plutôt
que pour la page de liaison hébergée. Laquelle des deux formes connect vous obtenez dépend d'une
seule chose — si vous passez `network` :

| Vous envoyez                          | Vous recevez                                              | Ce que vous en faites                                                                  |
| ------------------------------------- | --------------------------------------------------------- | -------------------------------------------------------------------------------------- |
| `mode: "connect"` et un `network`     | une `url` pointant vers une page de connexion mono-réseau | ouvrez-la dans une popup — c'est le [mode direct](/docs/multiple-users/connect-direct-mode) |
| `mode: "connect"` et pas de `network` | un `token`, et aucune URL du tout                         | transmettez-le à votre propre front-end                                                |

<Note>
  **La réponse porte le secret exactement une fois.** Une réponse a soit une `url`, soit un `token`,
  jamais les deux et jamais deux URL. Le token d'une session en mode direct vit à l'intérieur de
  l'`url`, exactement comme en mode grid ; une session sans URL pour le porter retourne le `token`
  nu à la place. Tout le reste est identique dans les trois modes : `sessionId`, `expiresAt`,
  `emailSent`, et `title` lorsque le User Profile en a un.
</Note>

### Ce que le mode connect nécessite

Aucun des deux n'est un champ de corps à part entière — le premier est un droit du compte et le
second est le paramètre [`origin`](#body-parameters) ci-dessus, que le mode connect rend
obligatoire.

**Le [Max Pack](/docs/additional/maxpack).** Sans lui, l'appel retourne `code: 504`, vérifié avant les
paramètres du mode connect, donc corriger `origin` ou `network` ne changera pas la réponse.
Contactez le support si vous avez besoin du mode connect sur un compte sans le Max Pack.

**Un `origin`, sur chaque session.** Il n'y a pas d'allowlist ni d'étape d'enregistrement — vous
l'envoyez à chaque appel et il est stocké sur la session, donc un nouvel environnement ne
nécessite aucune configuration de notre côté. Trois formes sont acceptées :

* une origine `https` — `https://app.example.com`
* un schéma personnalisé natif — `myapp://connected`
* `http://localhost` ou `http://localhost:3000`, pour le développement local

Origine uniquement : pas de chemin, de requête ou de fragment, et pas d'identifiants dedans.
L'omettre retourne `code: 505`, et tout ce qui n'est pas l'une des trois formes retourne
`code: 506`.

<Warning>
  `email` ne peut pas être utilisé avec une session qui n'a pas de `network`, car il n'y a aucun
  lien à mettre dans l'e-mail — cette forme retourne un token pour votre propre front-end. L'appel
  retourne `code: 510`. Ajoutez un `network` pour une session en mode direct, qui a bien une URL,
  ou omettez `email`.
</Warning>

Chaque code nommé ci-dessus figure dans la référence
[Erreurs de session de liaison](/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>
