Practical, copy-paste snippets for integrating with the intSignal API from your own code. All examples authenticate with a bearer API key and follow the shared conventions (JSON, cursor pagination, standard errors).
Set your key as an environment variable first:
export INTSIGNAL_TOKEN="your-api-key"
Authenticate & read
curl
curl "https://api.intsignal.com/v1/soc/cases?limit=50" \
-H "Authorization: Bearer $INTSIGNAL_TOKEN" \
-H "Accept: application/json"
JavaScript (Node 18+)
const BASE = "https://api.intsignal.com/v1";
const token = process.env.INTSIGNAL_TOKEN;
async function api(path, init = {}) {
const res = await fetch(BASE + path, {
...init,
headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json", ...init.headers },
});
if (!res.ok) throw new Error(`${res.status} ${(await res.json()).error?.message ?? res.statusText}`);
return res.json();
}
const { data } = await api("/soc/cases?limit=50");
console.log(data.length, "cases");
Python (requests)
import os, requests
BASE = "https://api.intsignal.com/v1"
session = requests.Session()
session.headers.update({"Authorization": f"Bearer {os.environ['INTSIGNAL_TOKEN']}"})
r = session.get(f"{BASE}/soc/cases", params={"limit": 50})
r.raise_for_status()
print(len(r.json()["data"]), "cases")
Pagination
List endpoints return a page of data plus a next_cursor; pass it back as cursor
until it comes back null. Loop to pull everything:
JavaScript
async function listAll(path) {
const out = [];
let cursor = null;
do {
const q = new URL(BASE + path);
q.searchParams.set("limit", "200");
if (cursor) q.searchParams.set("cursor", cursor);
const page = await api(q.pathname + q.search);
out.push(...page.data);
cursor = page.next_cursor;
} while (cursor);
return out;
}
Python
def list_all(path, params=None):
items, cursor = [], None
while True:
p = {"limit": 200, **(params or {})}
if cursor:
p["cursor"] = cursor
page = session.get(f"{BASE}{path}", params=p).json()
items += page["data"]
cursor = page.get("next_cursor")
if not cursor:
return items
Tip
Prefer filtering server-side with since and paging with cursor
over pulling everything on a tight loop — you'll stay well under the
rate limits.
Create a record
POST with a JSON body and the right scope (here soc:write):
curl
curl -X POST https://api.intsignal.com/v1/soc/cases/case_8f21c0 \
-H "Authorization: Bearer $INTSIGNAL_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "status": "contained", "note": "Approved endpoint isolation." }'
Python
r = session.patch(
f"{BASE}/soc/cases/case_8f21c0",
json={"status": "contained", "note": "Approved endpoint isolation."},
)
r.raise_for_status()
Handle errors & retry
Treat 5xx and 429 as retryable with exponential backoff; treat other 4xx as a bug
to fix. Always log the request_id from the error body.
async function withRetry(fn, tries = 4) {
for (let i = 0; i < tries; i++) {
try {
return await fn();
} catch (e) {
const status = Number(String(e.message).slice(0, 3));
if (![429, 500, 502, 503, 504].includes(status) || i === tries - 1) throw e;
await new Promise((r) => setTimeout(r, 2 ** i * 500 + Math.random() * 250));
}
}
}
See Rate limits for Retry-After and the limit headers.
