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

# Create a Link Session

> Create a social-linking URL for a user profile, without sending a private key.

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

Create a social-linking URL for a User Profile. Send the returned `url` to your user, and
they open it to connect their social accounts.

This is the recommended way to create a linking URL. It needs only your API key and a
`Profile-Key` — there is no private key to send and nothing to sign. Unlike a linking
URL created before, a link session is stored, so you can check whether it has been used
and revoke it before it expires.

The returned `url` signs your user into their profile, so treat it like a password and send
each one to a single user. See
[Sending the Linking URL](/docs/apis/profiles/generate-jwt-overview#sending-the-linking-url).

<Note>
  The URL is valid for **5 minutes** by default. Use `expiresIn` to set a different
  window, up to 2880 minutes (48 hours).
</Note>

<Info>
  [Generate a Linking URL](/docs/apis/profiles/generate-jwt) performs the same operation and keeps
  working unchanged. It accepts the legacy `privateKey`, `base64` and `verify` parameters
  and ignores them. `domain` is not ignored on either endpoint - it stays optional and is
  still validated. New integrations should use this endpoint.

  One difference in the response: `generateJWT` returns a top-level `token` for backwards
  compatibility, and this endpoint does not. The token exists only inside the returned `url`.
  If you are migrating and your code reads `token`, read `url` instead.
</Info>

## Header Parameters

<HeaderAPI profileKeyRequired={true} />

<Note>
  The `Profile-Key` is a header on this endpoint — there is no `profileKey` body
  parameter. If it is missing you get `code: 188`, whose message lists `privateKey`,
  `profileKey` and other legacy field names because it is shared with
  [Generate a Linking URL](/docs/apis/profiles/generate-jwt). Read it as "the Profile-Key header is
  missing or wrong"; none of the other names in it are parameters of this endpoint.
</Note>

<ParamField header="X-Twitter-OAuth1-Api-Key" type="string">
  Your X API Key (Consumer Key) from the X Developer Portal. When provided, the linking
  URL will use your own X Developer App for OAuth linking.
</ParamField>

<ParamField header="X-Twitter-OAuth1-Api-Secret" type="string">
  Your X API Secret (Consumer Secret) from the X Developer Portal. Required when
  `X-Twitter-OAuth1-Api-Key` is provided.
</ParamField>

## Body Parameters

<ParamField body="expiresIn" type="number" default={5}>
  Longevity of the link in minutes. Range: 1 to 2880 minutes.

  Requires the Max Pack.

  See [JWT Expires In](/docs/apis/profiles/generate-jwt-overview#jwt-expires-in) for more information.
</ParamField>

<ParamField body="logout" type="boolean" default={false}>
  Automatically log out the current session. Not recommended in production, since it
  affects performance.

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

<ParamField body="redirect" type="string">
  A URL to redirect to when the "Done" button or logo image is clicked. Add the query
  parameter `origin=true` to redirect the opener window.
</ParamField>

<ParamField body="allowedSocial" type="array">
  The social networks to display on the linking page. Overrides the networks configured
  on the [Social Networks](/docs/multiple-users/manage-user-profiles#set-social-networks-access)
  page.

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

<ParamField body="instagramLinkMethod" type="string">
  Override which Instagram linking flow is used for this link. Valid values:

  * `instagram`: Direct Instagram Login, no Facebook Page required.
  * `facebook`: Link Instagram via a connected Facebook Page.

  When omitted, the linking page uses your account-wide
  [Instagram Login](/docs/multiple-users/manage-user-profiles#instagram-login) setting.
</ParamField>

<ParamField body="domain" type="string">
  Optional. Your linking domain, when your account has more than one. When omitted, your
  account's own domain is used. A domain not registered to your account is rejected.
</ParamField>

<ParamField body="email" type="object">
  Send a Connect Accounts email carrying the link, so your user can reach their linking
  page directly. Requires a `to` address.

  Requires the Max Pack. The response reports the outcome in `emailSent`, and a send
  failure returns `code: 333` rather than a success response.

  See [Connect Accounts Email](/docs/apis/profiles/generate-jwt-overview#connect-accounts-email).
</ParamField>

<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())
  ```
</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 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>
