curl --request POST \
--url https://api.aisa.one/apis/v1/twitter/auth_twitter \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"aisa_api_key": "sk-aisa-...",
"scopes": [
"follows.write",
"tweet.read",
"users.read"
]
}
'import requests
url = "https://api.aisa.one/apis/v1/twitter/auth_twitter"
payload = {
"aisa_api_key": "sk-aisa-...",
"scopes": ["follows.write", "tweet.read", "users.read"]
}
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({
aisa_api_key: 'sk-aisa-...',
scopes: ['follows.write', 'tweet.read', 'users.read']
})
};
fetch('https://api.aisa.one/apis/v1/twitter/auth_twitter', 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/twitter/auth_twitter",
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([
'aisa_api_key' => 'sk-aisa-...',
'scopes' => [
'follows.write',
'tweet.read',
'users.read'
]
]),
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/twitter/auth_twitter"
payload := strings.NewReader("{\n \"aisa_api_key\": \"sk-aisa-...\",\n \"scopes\": [\n \"follows.write\",\n \"tweet.read\",\n \"users.read\"\n ]\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/twitter/auth_twitter")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"aisa_api_key\": \"sk-aisa-...\",\n \"scopes\": [\n \"follows.write\",\n \"tweet.read\",\n \"users.read\"\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.aisa.one/apis/v1/twitter/auth_twitter")
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 \"aisa_api_key\": \"sk-aisa-...\",\n \"scopes\": [\n \"follows.write\",\n \"tweet.read\",\n \"users.read\"\n ]\n}"
response = http.request(request)
puts response.read_body{
"auth_url": "https://twitter.com/i/oauth2/authorize?response_type=code&client_id=AIsa&redirect_uri=https%3A%2F%2Fapi.aisa.one%2Fapis%2Fv1%2Ftwitter%2Foauth_callback&scope=follows.write%20tweet.read%20users.read&state=0c2...d1f&code_challenge=...&code_challenge_method=S256",
"state": "0c2ad1f...",
"expires_at": "2026-04-18T07:00:00Z"
}Link an X Account
Start the OAuth flow that links an X/Twitter account to your AIsa API key. Call once per source user before using any Twitter write endpoint (follow, like, post, DM).
curl --request POST \
--url https://api.aisa.one/apis/v1/twitter/auth_twitter \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"aisa_api_key": "sk-aisa-...",
"scopes": [
"follows.write",
"tweet.read",
"users.read"
]
}
'import requests
url = "https://api.aisa.one/apis/v1/twitter/auth_twitter"
payload = {
"aisa_api_key": "sk-aisa-...",
"scopes": ["follows.write", "tweet.read", "users.read"]
}
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({
aisa_api_key: 'sk-aisa-...',
scopes: ['follows.write', 'tweet.read', 'users.read']
})
};
fetch('https://api.aisa.one/apis/v1/twitter/auth_twitter', 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/twitter/auth_twitter",
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([
'aisa_api_key' => 'sk-aisa-...',
'scopes' => [
'follows.write',
'tweet.read',
'users.read'
]
]),
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/twitter/auth_twitter"
payload := strings.NewReader("{\n \"aisa_api_key\": \"sk-aisa-...\",\n \"scopes\": [\n \"follows.write\",\n \"tweet.read\",\n \"users.read\"\n ]\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/twitter/auth_twitter")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"aisa_api_key\": \"sk-aisa-...\",\n \"scopes\": [\n \"follows.write\",\n \"tweet.read\",\n \"users.read\"\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.aisa.one/apis/v1/twitter/auth_twitter")
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 \"aisa_api_key\": \"sk-aisa-...\",\n \"scopes\": [\n \"follows.write\",\n \"tweet.read\",\n \"users.read\"\n ]\n}"
response = http.request(request)
puts response.read_body{
"auth_url": "https://twitter.com/i/oauth2/authorize?response_type=code&client_id=AIsa&redirect_uri=https%3A%2F%2Fapi.aisa.one%2Fapis%2Fv1%2Ftwitter%2Foauth_callback&scope=follows.write%20tweet.read%20users.read&state=0c2...d1f&code_challenge=...&code_challenge_method=S256",
"state": "0c2ad1f...",
"expires_at": "2026-04-18T07:00:00Z"
}POST /apis/v1/twitter/auth_twitter is the first step for any X/Twitter write action routed through AIsa. It returns a short-lived X OAuth authorization URL — the source user opens it in a browser, approves the requested scopes, and X redirects back to AIsa’s fixed callback. AIsa stores the resulting session against your API key, and every subsequent write call (e.g., POST /twitter/follow_twitter) uses that session automatically.
When to call it
- Once per source user, the first time you link their X account.
- Again if the stored session is revoked, expired, or you need a different scope set.
Flow
Start the flow
POST /apis/v1/twitter/auth_twitter with your AIsa API key. The key must be sent both as the Authorization: Bearer header and as a required aisa_api_key field in the JSON body — the OAuth session is bound to that key. Optionally include a scopes array in the body to request a narrower set than the default.curl -X POST https://api.aisa.one/apis/v1/twitter/auth_twitter \
-H "Authorization: Bearer sk-aisa-..." \
-H "Content-Type: application/json" \
-d '{"aisa_api_key": "sk-aisa-...", "scopes": ["follows.write", "tweet.read", "users.read"]}'
/apis/v1/twitter/auth_twitter — lowercase, underscores (not auth-twitter), version v1, method POST. A hyphenated path, a v2 path, or a GET request returns 404/405. Omitting the aisa_api_key body field returns 422.Open the auth URL
auth_url and a state token. Open auth_url in the source user’s browser. X shows its standard “Authorize AIsa to access your account” screen.User approves
https://api.aisa.one/apis/v1/twitter/oauth_callback). AIsa validates the state token, exchanges the authorization code for tokens, and stores the session against your API key.Write endpoints unlock
Default scopes
If you omit thescopes field, AIsa requests the full set needed for every Twitter write endpoint we expose:
follows.write— follow / unfollowtweet.read— read tweets (required by most write actions)users.read— resolve users, read profile infotweet.write— post, reply, quotelike.write— like / unlikedm.read— read DM threadsdm.write— send DMs
["follows.write", "tweet.read", "users.read"]) if you only need a subset. Write calls that require a missing scope return 403.
Expiry
Theauth_url returned by this endpoint is short-lived (typically 10 minutes). If the user doesn’t complete the flow before expires_at, call POST /apis/v1/twitter/auth_twitter again to generate a fresh URL.
The stored OAuth session itself lives longer (subject to X’s token rotation rules) and is refreshed automatically as long as the user doesn’t revoke access from X’s app settings.
Related
Follow a user
Twitter Autopilot skill
Authentication
Authorizations
Your AIsa API key. The authenticated source user (the account doing the follow) is determined by the OAuth session attached to your key.
Body
Your AIsa API key (the sk-aisa-... value). REQUIRED in the JSON body in addition to the Authorization: Bearer header — the OAuth session is bound to this key. Sending only the header returns HTTP 422; sending only the body returns 404.
Optional list of X OAuth 2.0 scopes to request. Defaults to the set required by AIsa's Twitter write endpoints: follows.write, tweet.read, users.read, tweet.write, like.write, dm.read, dm.write.
["follows.write", "tweet.read", "users.read"]
Response
Authorization URL generated.
Short-lived X OAuth authorization URL. Open it in a browser so the source user can approve the requested scopes.
Opaque CSRF state token that AIsa will validate when X redirects back to its callback. Store it client-side if you need to correlate the flow.
When the auth_url expires. Request a new one if the user hasn't completed the flow before this time.