curl --request POST \
--url https://api.aisa.one/apis/v1/unipile/hosted/link \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"providers": [
"<string>"
],
"api_url": "<string>",
"expiresOn": "<string>"
}
'import requests
url = "https://api.aisa.one/apis/v1/unipile/hosted/link"
payload = {
"providers": ["<string>"],
"api_url": "<string>",
"expiresOn": "<string>"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({providers: ['<string>'], api_url: '<string>', expiresOn: '<string>'})
};
fetch('https://api.aisa.one/apis/v1/unipile/hosted/link', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.aisa.one/apis/v1/unipile/hosted/link",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'providers' => [
'<string>'
],
'api_url' => '<string>',
'expiresOn' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.aisa.one/apis/v1/unipile/hosted/link"
payload := strings.NewReader("{\n \"providers\": [\n \"<string>\"\n ],\n \"api_url\": \"<string>\",\n \"expiresOn\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.aisa.one/apis/v1/unipile/hosted/link")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"providers\": [\n \"<string>\"\n ],\n \"api_url\": \"<string>\",\n \"expiresOn\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.aisa.one/apis/v1/unipile/hosted/link")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"providers\": [\n \"<string>\"\n ],\n \"api_url\": \"<string>\",\n \"expiresOn\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"object": "HostedAuthUrl",
"url": "<string>"
}Hosted Auth Link
Create a hosted authorization link for connecting a LinkedIn account.
curl --request POST \
--url https://api.aisa.one/apis/v1/unipile/hosted/link \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"providers": [
"<string>"
],
"api_url": "<string>",
"expiresOn": "<string>"
}
'import requests
url = "https://api.aisa.one/apis/v1/unipile/hosted/link"
payload = {
"providers": ["<string>"],
"api_url": "<string>",
"expiresOn": "<string>"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({providers: ['<string>'], api_url: '<string>', expiresOn: '<string>'})
};
fetch('https://api.aisa.one/apis/v1/unipile/hosted/link', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.aisa.one/apis/v1/unipile/hosted/link",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'providers' => [
'<string>'
],
'api_url' => '<string>',
'expiresOn' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.aisa.one/apis/v1/unipile/hosted/link"
payload := strings.NewReader("{\n \"providers\": [\n \"<string>\"\n ],\n \"api_url\": \"<string>\",\n \"expiresOn\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.aisa.one/apis/v1/unipile/hosted/link")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"providers\": [\n \"<string>\"\n ],\n \"api_url\": \"<string>\",\n \"expiresOn\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.aisa.one/apis/v1/unipile/hosted/link")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"providers\": [\n \"<string>\"\n ],\n \"api_url\": \"<string>\",\n \"expiresOn\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"object": "HostedAuthUrl",
"url": "<string>"
}notify_url and AISA handles everything — poll GET /apis/v1/unipile/me/accounts until the account appears (usually within seconds of the user finishing the wizard); no webhook infrastructure needed on your side. Self-hosted mode: pass your own notify_url and Unipile POSTs {"status":"CREATION_SUCCESS","account_id":"…","name":"…"} to it when the flow completes — store that account_id, it is the identifier every other endpoint requires, and with your own webhook there is no listing endpoint to re-discover it (managed-mode users read me/accounts instead). The name you set here is echoed back in self-hosted mode, so use it to map the account to your own user. Reply 200 within 30 seconds or the event is retried five times; consider verifying a shared-secret header on your endpoint. Links expire on Unipile’s daily restart regardless of expiresOn, so generate a fresh link each time a user wants to connect. Note: re-authorizing the same LinkedIn account creates a new account_id; earlier bindings remain listed until disconnected.
Reference price: $0.000001 USD per successful request.
Example
curl -X POST "https://api.aisa.one/apis/v1/unipile/hosted/link" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"type": "create", "providers": ["LINKEDIN"], "api_url": "https://api68.unipile.com:19823", "expiresOn": "2026-12-31T23:59:59.999Z", "name": "your-internal-user-id", "notify_url": "https://example.com/hooks/unipile", "success_redirect_url": "https://example.com/connected", "failure_redirect_url": "https://example.com/failed"}'
Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Body
create connects a new account, reconnect re-authenticates an existing one.
create, reconnect Provider list, for example ["LINKEDIN"]. Only used with type=create.
The Unipile server URL of this AIsa binding, for example https://api68.unipile.com:19823. Use the value documented here; a generic Unipile URL will not match the binding.
ISO 8601 UTC expiry, for example 2026-12-31T23:59:59.999Z. Required by upstream, even though links also die on Unipile's daily restart.
Label echoed back in events so you can match the account to your own user.
Callback notified once the connection completes.
Browser redirect after a successful connection.
Browser redirect after a failed connection.
Account id to re-authenticate. Required when type is reconnect.
Skip Unipile's hosted success screen before the browser follows success_redirect_url.
Provider features to disable on the connected account: linkedin_recruiter, linkedin_sales_navigator, or linkedin_organizations_mailboxes.