> ## 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 の作成

> 秘密鍵を送信せずに、User Profile のソーシャル連携用 URL を作成します。

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

User Profile のソーシャル連携用 URL を作成します。返された `url` をユーザーに送ると、ユーザーはそれを開いてソーシャルアカウントを連携できます。

これがリンク用 URL を作成する推奨の方法です。必要なのは API Key と `Profile-Key` だけで、送信する秘密鍵も署名するものもありません。従来の方法で作成したリンク用 URL と異なり、Link Session は保存されるため、使用されたかどうかを確認でき、期限切れ前に失効させることもできます。

返された `url` はユーザーをそのプロファイルにサインインさせるため、パスワードと同様に扱い、各 URL は 1 人のユーザーにのみ送信してください。
[リンク用 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` は
  どちらのエンドポイントでも無視されません — 引き続き任意であり、バリデーションも行われます。
  新しい実装ではこのエンドポイントを使用してください。

  レスポンスには 1 つ違いがあります: `generateJWT` は後方互換性のためにトップレベルの `token` を返しますが、
  このエンドポイントが `url` と**並べて**トークンを返すことはありません — `url` のトークンはその中に
  存在します。移行中でコードが `token` を読み取っている場合は、代わりに `url` を読み取ってください。
  (埋め込みウィジェット用の [Connect モード](#connect-mode)だけが `token` を単体で返す形です。
  トークンを載せる URL が返されないためです。)
</Info>

## ヘッダーパラメータ

<HeaderAPI profileKeyRequired={true} />

<Note>
  `Profile-Key` はこのエンドポイントではヘッダーです — `profileKey` ボディパラメータはありません。
  欠落している場合は `code: 188` が返され、そのメッセージには `privateKey` や `profileKey` などの
  レガシーなフィールド名が列挙されます。これは[リンク用 URL の生成](/docs/apis/profiles/generate-jwt)と
  共有されているためです。「Profile-Key ヘッダーが欠落しているか誤っている」と読み替えてください。
  メッセージ内の他の名前は、このエンドポイントのパラメータではありません。
</Note>

<ParamField header="X-Twitter-OAuth1-Api-Key" type="string">
  X Developer Portal からの X API Key(Consumer Key)。指定すると、リンク用 URL は OAuth 連携に
  あなた自身の X デベロッパーアプリを使用します。
</ParamField>

<ParamField header="X-Twitter-OAuth1-Api-Secret" type="string">
  X Developer Portal からの X API Secret(Consumer Secret)。`X-Twitter-OAuth1-Api-Key` が指定されている
  場合は必須です。
</ParamField>

## ボディパラメータ

<ParamField body="mode" type="string" default="grid">
  このセッションがどのリンクサーフェスを駆動するか。

  * `grid` — ホスト型リンクページ。許可しているすべてのネットワークを表示します。これがデフォルト
    なので、`mode` を省略したリクエストはこれを作成します。
  * `connect` — 貴社自身のダッシュボードから開く、一度に 1 ネットワークの連携。下記の
    [Connect モード](#connect-mode)と[ダイレクトモード](/docs/multiple-users/connect-direct-mode)を
    参照してください。

  推測されることはありません: `origin` や `network` を渡しても connect モードにはならないため、
  grid セッションが誤ってゲート付きのセッションになることはありません。それ以外の値は、`details` に
  2 つの有効な値を挙げた `code: 188` を返します。
</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}>
  現在のセッションを自動的にログアウトします。パフォーマンスに影響するため、本番環境での使用は推奨しません。

  詳細については、[プロフィールセッションの自動ログアウト](/docs/multiple-users/api-integration-business#automatic-logout-of-a-profile-session)をご覧ください。
</ParamField>

<ParamField body="redirect" type="string">
  「Done」ボタンまたはロゴ画像がクリックされたときにリダイレクトする URL。オープナーウィンドウを
  リダイレクトするには、クエリパラメータ `origin=true` を追加してください。
</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`): 単一ネットワークのセッションは、
  それ自体がすでにホワイトリストだからです。アカウントで有効になっていないネットワークは
  `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 ページ不要。
  * `facebook`: 連携済みの Facebook ページを経由して Instagram を連携。

  省略した場合、連携ページはアカウント全体の
  [Instagram Login](/docs/multiple-users/manage-user-profiles#instagram-login) 設定を使用します。
</ParamField>

<ParamField body="origin" type="string">
  リンクウィンドウを開いたページの正確なオリジン。連携の完了時に通知を受け取れるようにします。

  設定すると、ユーザーが各アカウントを接続するたびに、リンクページが `window.postMessage` でその
  オリジンにイベントを post し、貴社のページはポーリングなしで反応できます。イベントはこの正確な
  値にのみ送信されるため、スキームやポートを含め、貴社のページのオリジンと 1 文字違わず一致する
  必要があります。

  受け付けられる形は 3 つです: `https` オリジン(`https://app.example.com`)、ローカル開発用の
  `http://localhost:3000`、ネイティブのカスタムスキーム(`myapp://connected`)。それ以外 —
  localhost 以外の素の `http://` オリジンや、そもそもオリジンでないもの — は、このエンドポイントが
  作成するリンクでは無視されます: リンクは動作しますが、イベントは送信されません。任意なので、
  省略してもエラーにはなりません。

  3 つのうちイベントを受信できるのは最初の 2 つだけです。カスタムスキームはモバイルアプリの戻り先で
  あり、**イベントを受信できません**。post する先のブラウザウィンドウが存在しないためです。ネイティブ
  アプリは代わりに [Link Session の取得](/docs/apis/profiles/get-link-session)をポーリングします。

  [リンク完了イベント](/docs/multiple-users/link-completion-events)を参照してください。

  **connect モードでは `origin` は必須であり、チェックされます。** 上記の寛容な扱いは grid モードの
  挙動です。`mode: "connect"` では、省略すると `code: 505` が返され、受け付けられる 3 つの形の
  いずれでもない値は `code: 506` を返します。その `details` には送信した形がそのまま示されます。
</ParamField>

<ParamField body="domain" type="string">
  任意。アカウントに複数のリンク用ドメインがある場合に指定する、あなたのリンク用ドメイン。省略した場合は
  アカウント自身のドメインが使用されます。アカウントに登録されていないドメインは拒否されます。
</ParamField>

<ParamField body="email" type="object">
  リンクを含む Connect Accounts メールを送信し、ユーザーが連携ページに直接アクセスできるようにします。
  `to` アドレスが必要です。

  Max Pack が必要です。送信結果はレスポンスの `emailSent` に反映され、送信に失敗した場合は成功レスポンス
  ではなく `code: 333` が返されます。

  詳細については、[Connect Accounts メール](/docs/apis/profiles/social-linking-overview#connect-accounts-email)をご覧ください。
</ParamField>

<h2 id="connect-mode">
  Connect モード
</h2>

`mode: "connect"` は、ホスト型リンクページではなく、貴社自身がホストするリンクサーフェス用の
セッションを作成します。2 つある connect の形のどちらになるかは、`network` を渡すかどうか、その
1 点で決まります:

| 送信するもの                             | 返ってくるもの                        | それをどうするか                                                           |
| ---------------------------------- | ------------------------------ | ------------------------------------------------------------------ |
| `mode: "connect"` と `network`      | 単一ネットワークの connect ページを指す `url` | ポップアップで開きます — これが[ダイレクトモード](/docs/multiple-users/connect-direct-mode)です |
| `mode: "connect"` のみ(`network` なし) | `token` のみ。URL はまったくなし         | 貴社自身のフロントエンドに渡します                                                  |

<Note>
  **レスポンスがシークレットを運ぶのはちょうど 1 回です。** レスポンスには `url` か `token` の
  どちらか一方があり、両方を持つことも URL が 2 つになることもありません。ダイレクトモードの
  セッションのトークンは、grid モードと同じように `url` の中にあります。トークンを載せる URL の
  ないセッションは、代わりに `token` を単体で返します。それ以外は 3 つのモードすべてで同じです:
  `sessionId`、`expiresAt`、`emailSent`、そして User Profile に設定されていれば `title`。
</Note>

### Connect モードに必要なもの

どちらもそれ自体がボディフィールドなのではありません — 1 つ目はアカウントの権限で、2 つ目は上記の
[`origin`](#body-parameters) パラメータであり、connect モードはこれを必須にします。

**[Max Pack](/docs/additional/maxpack)。** これがないと呼び出しは `code: 504` を返します。connect モードの
パラメータより先にチェックされるため、`origin` や `network` を修正しても結果は変わりません。Max Pack
のないアカウントで connect モードを有効にする必要がある場合は、サポートにお問い合わせください。

**すべてのセッションに `origin`。** ホワイトリストも登録手順もありません — 呼び出しごとに送信し、
セッションに保存されるため、新しい環境で当社側の設定は不要です。受け付けられる形は 3 つです:

* `https` オリジン — `https://app.example.com`
* ネイティブのカスタムスキーム — `myapp://connected`
* `http://localhost` または `http://localhost:3000`(ローカル開発用)

オリジンのみです: パス、クエリ、フラグメント、認証情報を含めてはいけません。省略すると `code: 505`
が返され、3 つの形のいずれでもないものは `code: 506` を返します。

<Warning>
  `email` は `network` のないセッションでは使用できません。メールに載せるリンクが存在しない
  からです — その形は貴社のフロントエンド用のトークンを返します。呼び出しは `code: 510` を返します。
  URL を持つダイレクトモードのセッションにするために `network` を追加するか、`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 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>
