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
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);
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
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);
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}");
}
}
}
}
{
"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.
}
{
"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"
}
{
"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"
}
{
"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"
}
{
"action": "JWT",
"status": "error",
"code": 188,
"message": "Missing or incorrect privateKey, profileKey, domain, email 'to', or expiresIn fields."
}
{
"action": "JWT",
"status": "error",
"code": 189,
"message": "Error generating JWT. Check the sent parameters.",
"details": "Missing or incorrect domain."
}
{
"action": "JWT",
"status": "error",
"code": 340,
"message": "Max Pack required. Go to your dashboard to add the Max Pack."
}
Profiles
创建 Link Session
无需发送 private key,即可为 user profile 创建社交账号链接 URL。
POST
/
profiles
/
link-sessions
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
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);
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
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);
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}");
}
}
}
}
{
"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.
}
{
"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"
}
{
"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"
}
{
"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"
}
{
"action": "JWT",
"status": "error",
"code": 188,
"message": "Missing or incorrect privateKey, profileKey, domain, email 'to', or expiresIn fields."
}
{
"action": "JWT",
"status": "error",
"code": 189,
"message": "Error generating JWT. Check the sent parameters.",
"details": "Missing or incorrect domain."
}
{
"action": "JWT",
"status": "error",
"code": 340,
"message": "Max Pack required. Go to your dashboard to add the Max Pack."
}
为 User Profile 创建社交账号链接 URL。将返回的
上面提到的每个错误码都收录在 Link Session 错误
参考中。
url 发送给您的用户,用户打开它即可关联自己的社交账号。
这是创建链接 URL 的推荐方式。它只需要您的 API Key 和一个 Profile-Key —— 无需发送 private key,也没有任何需要签名的内容。与以前创建的链接 URL 不同,link session(链接会话)会被存储,因此您可以查询它是否已被使用,并在过期前吊销它。
返回的 url 会让您的用户登录到他们的 profile,因此请像对待密码一样对待它,并且每个链接只发送给一位用户。参见发送链接 URL。
该 URL 默认有效期为 5 分钟。可使用
expiresIn 设置不同的有效期,最长 2880 分钟(48 小时)。生成链接 URL 执行相同的操作,并保持原样继续工作。它仍接受旧的
privateKey、base64 和 verify 参数并将其忽略。domain 在两个端点上都不会被忽略 ——
它保持可选,并且仍会被校验。新的集成应使用本端点。响应中有一处差异:generateJWT 为了向后兼容会返回顶层的 token,而本端点不会在返回 url
的同时再返回一个 —— url 中的 token 就存在于 URL 内部。如果您正在迁移且代码会读取
token,请改为读取 url。(面向嵌入式小组件的 Connect 模式是唯一返回裸
token 的形态,因为它不返回可以承载 token 的 URL。)Header 参数
在本端点上,
Profile-Key 是一个 header —— 不存在 profileKey body 参数。如果缺少它,您会收到
code: 188,其 message 会列出 privateKey、profileKey 以及其他旧字段名,因为该错误与
生成链接 URL 共用。请将其理解为“Profile-Key header 缺失或不正确”;
其中列出的其他名称都不是本端点的参数。string
来自 X Developer Portal 的 X API Key(Consumer Key)。当提供该值时,链接 URL
将使用您自己的 X Developer App 进行 OAuth 关联。
string
来自 X Developer Portal 的 X API Secret(Consumer Secret)。当提供
X-Twitter-OAuth1-Api-Key 时必填。Body 参数
string
默认值:"grid"
本会话驱动哪种关联界面。
grid—— 托管关联页面,显示您允许的所有网络。这是默认值,因此省略mode的请求创建的就是 这种会话。connect—— 一次一个网络,从您自己的控制台打开。参见下方的 Connect 模式 以及直连模式。
origin 或 network 并不会让您进入 connect 模式,因此 grid 会话不会
意外变成受限会话。任何其他值都会返回 code: 188,其 details 会列出这两个取值。boolean
默认值:false
自动登出当前会话。不建议在生产环境中使用,因为会影响性能。参见自动登出 Profile 会话。
string
指定当点击 “Done”(完成)按钮或 logo 图片时要跳转到的 URL。在该 URL 上添加查询参数
origin=true 可跳转原始 opener 窗口。array
指定在关联页面上要显示的社交网络。此设置会覆盖在社交网络页面配置的社交网络。
Only display Facebook, X/Twitter, LinkedIn, and TikTok
{
"allowedSocial": ["facebook", "twitter", "linkedin", "tiktok"]
}
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 区分开,是因为它可以在您的
社交网络页面上自行修复。在 grid 模式下它会被忽略。string
覆盖此链接使用的 Instagram 关联流程。有效值:
instagram:直接使用 Instagram Login,无需 Facebook Page。facebook:通过已关联的 Facebook Page 关联 Instagram。
string
打开关联窗口的页面的确切 origin,以便在关联完成时通知它。设置后,关联页面会在您的用户连接每个账号时,通过
window.postMessage 向该 origin 发送事件,
您的页面无需轮询即可做出反应。事件只会发送到这个确切值,因此它必须与您页面的 origin 逐字符
匹配,包括协议和端口。接受三种形态:https origin(https://app.example.com)、用于本地开发的
http://localhost:3000,以及原生自定义 scheme(myapp://connected)。其他任何值 ——
localhost 之外的普通 http:// origin,或根本不是 origin 的值 —— 在本端点创建的链接上会被
忽略:链接仍然有效,只是不会发送任何事件。它是可选的,因此省略它也不是错误。三者之中只有前两种会收到事件。自定义 scheme 是移动应用的返回目标,无法接收事件,因为
没有可供发送的浏览器窗口;原生应用应改为轮询
获取 Link Session。参见关联完成事件。在 connect 模式下 origin 是必需的,并且会被校验。 上述宽容行为是 grid 模式的行为。使用
mode: "connect" 时,省略它返回 code: 505;不属于三种可接受形态的值返回 code: 506,
其 details 会复述您发送的形态。string
可选。当您的账户拥有多个链接 domain 时,指定要使用的 domain。省略时使用您账户自身的
domain。未注册到您账户的 domain 会被拒绝。
object
发送一封携带该链接的 Connect Accounts 邮件,让您的用户可以直接访问其关联页面。需要提供
to 地址。需要 Max Pack。响应会在 emailSent 中报告发送结果,发送失败会返回 code: 333
而不是成功响应。参见 Connect Accounts 邮件。Connect 模式
mode: "connect" 创建的会话面向您自己托管的关联界面,而不是托管关联页面。您得到两种 connect
形态中的哪一种,取决于一件事 —— 是否传入 network:
| 您发送的 | 您得到的 | 用途 |
|---|---|---|
mode: "connect" 加一个 network | 指向单网络连接页面的 url | 在弹窗中打开它 —— 这就是直连模式 |
mode: "connect" 且不带 network | 一个 token,完全没有 URL | 交给您自己的前端 |
响应只携带一次机密。 一个响应要么有
url,要么有 token,绝不会两者都有,也绝不会有两个
URL。直连模式会话的 token 存在于 url 内部,与 grid 模式相同;没有 URL 承载它的会话则改为
返回裸 token。其余部分在三种模式下都相同:sessionId、expiresAt、emailSent,以及当
User Profile 有标题时的 title。Connect 模式的要求
这两项都不是独立的 body 字段 —— 第一项是账户权益,第二项是上方的origin
参数,connect 模式将其变为必需。
Max Pack。 没有它,调用返回 code: 504,且在 connect 模式参数之前
检查,因此修正 origin 或 network 不会改变这个结果。如果您需要在没有 Max Pack 的账户上启用
connect 模式,请联系支持团队。
每个会话都要有 origin。 没有允许列表,也没有注册步骤 —— 您在每次调用时发送它,它被存储在
会话上,因此新环境在我们这一侧无需任何设置。接受三种形态:
httpsorigin ——https://app.example.com- 原生自定义 scheme ——
myapp://connected http://localhost或http://localhost:3000,用于本地开发
code: 505,不属于三种形态的值
返回 code: 506。
email 不能用于没有 network 的会话,因为没有可放进邮件的链接 —— 该形态返回的是交给您自己
前端的 token。此时调用返回 code: 510。请为直连模式会话加上 network(它有 URL),或省略
email。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
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);
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
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);
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}");
}
}
}
}
{
"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.
}
{
"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"
}
{
"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"
}
{
"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"
}
{
"action": "JWT",
"status": "error",
"code": 188,
"message": "Missing or incorrect privateKey, profileKey, domain, email 'to', or expiresIn fields."
}
{
"action": "JWT",
"status": "error",
"code": 189,
"message": "Error generating JWT. Check the sent parameters.",
"details": "Missing or incorrect domain."
}
{
"action": "JWT",
"status": "error",
"code": 340,
"message": "Max Pack required. Go to your dashboard to add the Max Pack."
}