curl --request POST \
--url https://api.superx.so/v1/signals/agents \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "Build in public founders",
"icp_description": "Indie founders building SaaS in public, sharing MRR and launch updates",
"precision_mode": "high",
"keywords": [
"building in public",
"just shipped my MVP"
]
}
'import requests
url = "https://api.superx.so/v1/signals/agents"
payload = {
"name": "Build in public founders",
"icp_description": "Indie founders building SaaS in public, sharing MRR and launch updates",
"precision_mode": "high",
"keywords": ["building in public", "just shipped my MVP"]
}
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({
name: 'Build in public founders',
icp_description: 'Indie founders building SaaS in public, sharing MRR and launch updates',
precision_mode: 'high',
keywords: ['building in public', 'just shipped my MVP']
})
};
fetch('https://api.superx.so/v1/signals/agents', 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.superx.so/v1/signals/agents",
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([
'name' => 'Build in public founders',
'icp_description' => 'Indie founders building SaaS in public, sharing MRR and launch updates',
'precision_mode' => 'high',
'keywords' => [
'building in public',
'just shipped my MVP'
]
]),
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.superx.so/v1/signals/agents"
payload := strings.NewReader("{\n \"name\": \"Build in public founders\",\n \"icp_description\": \"Indie founders building SaaS in public, sharing MRR and launch updates\",\n \"precision_mode\": \"high\",\n \"keywords\": [\n \"building in public\",\n \"just shipped my MVP\"\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.superx.so/v1/signals/agents")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"Build in public founders\",\n \"icp_description\": \"Indie founders building SaaS in public, sharing MRR and launch updates\",\n \"precision_mode\": \"high\",\n \"keywords\": [\n \"building in public\",\n \"just shipped my MVP\"\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.superx.so/v1/signals/agents")
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 \"name\": \"Build in public founders\",\n \"icp_description\": \"Indie founders building SaaS in public, sharing MRR and launch updates\",\n \"precision_mode\": \"high\",\n \"keywords\": [\n \"building in public\",\n \"just shipped my MVP\"\n ]\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": 12,
"name": "Build in public founders",
"status": "active",
"status_detail": null,
"icp_description": "Indie founders building SaaS in public, sharing MRR and launch updates",
"precision_mode": "high",
"destination_list_id": "contact:V1StGXR8_Z5jdHi6B-myT",
"created_at": "2026-07-08T10:00:00.000Z",
"updated_at": "2026-07-08T10:00:00.000Z",
"deposited_count": 0,
"last_checked": null,
"signals": [
{
"id": 31,
"type": "keyword_watch",
"handle": null,
"name": null,
"avatar": null,
"query": "building in public",
"list_name": null,
"status": "active",
"status_detail": null,
"last_run_at": null,
"created_at": "2026-07-08T10:00:00.000Z"
}
],
"destination_list_created": true
}
}{
"error": {
"code": "invalid_parameter",
"message": "icp_description is required (1-500 characters)"
}
}{
"error": {
"code": "invalid_api_key",
"message": "Unknown or revoked API key"
}
}{
"error": {
"code": "cap_reached",
"message": "You've reached your plan's signal agent limit (1 on the pro plan). Pause and delete an agent, or upgrade your plan."
}
}{
"error": {
"code": "list_not_found",
"message": "No contact list with that id belongs to this account."
}
}{
"error": {
"code": "idempotency_key_reuse",
"message": "This Idempotency-Key was already used with a different request body."
}
}{
"error": {
"code": "rate_limited",
"message": "Rate limit exceeded for the Pro plan (30 requests/min). Upgrade for higher limits.",
"retry_after": 42
}
}{
"error": {
"code": "internal_error",
"message": "Failed to fetch posts"
}
}{
"error": {
"code": "upstream_error",
"message": "Failed to fetch scheduled posts. Try again shortly."
}
}{
"error": {
"code": "upstream_unavailable",
"message": "The scheduling service is temporarily unavailable. Retry with the same Idempotency-Key."
}
}Create a signal agent
Create a signal agent: it watches X for the given keywords and scores
the people it finds against icp_description. Matching leads land in
Signals (and GET /v1/signals/leads) over the following minutes and
days; nothing is returned synchronously.
keywords is shorthand for keyword watches; signals carries all
four watch types (keyword_watch, profile_watch, follower_watch,
list_watch). Send either or both: 1-5 distinct entries combined,
keywords first. Omit both and 1-3 keyword watches are suggested from
the ICP (if suggestion fails, nothing is created and you get 502
upstream_error). Omit destination_list_id and a contact list
named Leads: <agent name> is created for the leads, flagged
destination_list_created: true in the response.
PARTIAL SUCCESS: entries the add path rejects (an unknown handle, a
private list, a duplicate, the per-agent signal cap) come back in
warnings and the agent is still created from the entries that
landed. Only when EVERY entry fails is the agent rolled back and an
error returned. Read warnings before reporting what the agent
watches, and re-add the fixed entries with
POST /v1/signals/agents/{id}/signals.
A create carrying any profile_watch, follower_watch or
list_watch entry resolves those targets live and consumes ONE unit
of the enrichment allowance (one per call, not per entry).
Plan limits apply (403 cap_reached). Supports Idempotency-Key
(max 64 chars): retries with the same key and body replay the
original response with Idempotency-Replayed: true. Works for your main account or any account linked to it (account_id); accounts shared with you are read-only.
curl --request POST \
--url https://api.superx.so/v1/signals/agents \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "Build in public founders",
"icp_description": "Indie founders building SaaS in public, sharing MRR and launch updates",
"precision_mode": "high",
"keywords": [
"building in public",
"just shipped my MVP"
]
}
'import requests
url = "https://api.superx.so/v1/signals/agents"
payload = {
"name": "Build in public founders",
"icp_description": "Indie founders building SaaS in public, sharing MRR and launch updates",
"precision_mode": "high",
"keywords": ["building in public", "just shipped my MVP"]
}
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({
name: 'Build in public founders',
icp_description: 'Indie founders building SaaS in public, sharing MRR and launch updates',
precision_mode: 'high',
keywords: ['building in public', 'just shipped my MVP']
})
};
fetch('https://api.superx.so/v1/signals/agents', 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.superx.so/v1/signals/agents",
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([
'name' => 'Build in public founders',
'icp_description' => 'Indie founders building SaaS in public, sharing MRR and launch updates',
'precision_mode' => 'high',
'keywords' => [
'building in public',
'just shipped my MVP'
]
]),
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.superx.so/v1/signals/agents"
payload := strings.NewReader("{\n \"name\": \"Build in public founders\",\n \"icp_description\": \"Indie founders building SaaS in public, sharing MRR and launch updates\",\n \"precision_mode\": \"high\",\n \"keywords\": [\n \"building in public\",\n \"just shipped my MVP\"\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.superx.so/v1/signals/agents")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"Build in public founders\",\n \"icp_description\": \"Indie founders building SaaS in public, sharing MRR and launch updates\",\n \"precision_mode\": \"high\",\n \"keywords\": [\n \"building in public\",\n \"just shipped my MVP\"\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.superx.so/v1/signals/agents")
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 \"name\": \"Build in public founders\",\n \"icp_description\": \"Indie founders building SaaS in public, sharing MRR and launch updates\",\n \"precision_mode\": \"high\",\n \"keywords\": [\n \"building in public\",\n \"just shipped my MVP\"\n ]\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": 12,
"name": "Build in public founders",
"status": "active",
"status_detail": null,
"icp_description": "Indie founders building SaaS in public, sharing MRR and launch updates",
"precision_mode": "high",
"destination_list_id": "contact:V1StGXR8_Z5jdHi6B-myT",
"created_at": "2026-07-08T10:00:00.000Z",
"updated_at": "2026-07-08T10:00:00.000Z",
"deposited_count": 0,
"last_checked": null,
"signals": [
{
"id": 31,
"type": "keyword_watch",
"handle": null,
"name": null,
"avatar": null,
"query": "building in public",
"list_name": null,
"status": "active",
"status_detail": null,
"last_run_at": null,
"created_at": "2026-07-08T10:00:00.000Z"
}
],
"destination_list_created": true
}
}{
"error": {
"code": "invalid_parameter",
"message": "icp_description is required (1-500 characters)"
}
}{
"error": {
"code": "invalid_api_key",
"message": "Unknown or revoked API key"
}
}{
"error": {
"code": "cap_reached",
"message": "You've reached your plan's signal agent limit (1 on the pro plan). Pause and delete an agent, or upgrade your plan."
}
}{
"error": {
"code": "list_not_found",
"message": "No contact list with that id belongs to this account."
}
}{
"error": {
"code": "idempotency_key_reuse",
"message": "This Idempotency-Key was already used with a different request body."
}
}{
"error": {
"code": "rate_limited",
"message": "Rate limit exceeded for the Pro plan (30 requests/min). Upgrade for higher limits.",
"retry_after": 42
}
}{
"error": {
"code": "internal_error",
"message": "Failed to fetch posts"
}
}{
"error": {
"code": "upstream_error",
"message": "Failed to fetch scheduled posts. Try again shortly."
}
}{
"error": {
"code": "upstream_unavailable",
"message": "The scheduling service is temporarily unavailable. Retry with the same Idempotency-Key."
}
}Authorizations
A SuperX API key ("sxk_..."), created in the SuperX app under Account > API / MCP / CLI. Keys are server-side secrets.
Headers
Unique key (max 64 characters) for safe retries. Replays carry the "Idempotency-Replayed" response header set to "true". Keys are retained for 24 hours.
64Body
Agent name shown in SuperX.
80Who the ideal leads are; found people are scored against this.
500high = fewer, stricter matches; discovery = broader net.
high, discovery Plain-language descriptions of what the target customer posts about. Omit to auto-suggest from the ICP. Keywords beyond your plan's per-agent signal limit are dropped; the response lists the signals actually created.
1 - 5 elements180Non-keyword watches to add alongside keywords. Combined with keywords, at most 5 distinct entries.
1 - 5 elementsShow child attributes
Show child attributes
Contact list id (from GET /v1/contact-lists) that receives the leads. Omit to auto-create one.
Any account you own, meaning your main account (the default when omitted) or one linked to it. An account shared with you returns 403 writes_main_account_only.
Response
The created agent with its keyword signals, plus whether a destination list was auto-created.
Show child attributes
Show child attributes