Documentation

Developers · API

Code examples

Copy-paste intSignal API integration snippets in curl, JavaScript (Node), and Python — authentication, listing with pagination, creating records, and error handling.

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.

Need a hand with Developers?Talk to our team →