Documentation Index
Fetch the complete documentation index at: https://docs.shoal.xyz/llms.txt
Use this file to discover all available pages before exploring further.
Resolve an Entity by Name
curl -X GET "https://api.shoal.xyz/v1/entities/byName?name=ethereum&limit=5" \
-H "Authorization: Bearer YOUR_API_KEY"
import os, requests
API_KEY = os.environ.get("SHOAL_API_KEY", "YOUR_API_KEY")
r = requests.get(
"https://api.shoal.xyz/v1/entities/byName",
headers={"Authorization": f"Bearer {API_KEY}"},
params={"name": "ethereum", "limit": 5},
)
print(r.json())
const API_KEY = process.env.SHOAL_API_KEY || 'YOUR_API_KEY';
const url = new URL('https://api.shoal.xyz/v1/entities/byName');
url.searchParams.set('name', 'ethereum');
url.searchParams.set('limit', '5');
const res = await fetch(url, { headers: { Authorization: `Bearer ${API_KEY}` } });
console.log(await res.json());
Get One Entity Timeline
curl -X GET "https://api.shoal.xyz/v1/timeline/byOrganizationId?id=23151&since=2026-02-01T00:00:00Z&limit=10" \
-H "Authorization: Bearer YOUR_API_KEY"
requests.get(
"https://api.shoal.xyz/v1/timeline/byOrganizationId",
headers={"Authorization": f"Bearer {API_KEY}"},
params={"id": 23151, "since": "2026-02-01T00:00:00Z", "limit": 10}
)
const radarRes = await fetch(
'https://api.shoal.xyz/v1/timeline/byOrganizationId?id=23151&since=2026-02-01T00:00:00Z&limit=10',
{ headers: { Authorization: `Bearer ${API_KEY}` } }
);
Get Entity Relationships
curl -X GET "https://api.shoal.xyz/v1/entities/23151/relationships?limit=10" \
-H "Authorization: Bearer YOUR_API_KEY"
requests.get(
"https://api.shoal.xyz/v1/entities/23151/relationships",
headers={"Authorization": f"Bearer {API_KEY}"},
params={"limit": 10}
)
const res2 = await fetch(
'https://api.shoal.xyz/v1/entities/23151/relationships?limit=10',
{ headers: { Authorization: `Bearer ${API_KEY}` } }
);
Signal by Category
curl -X GET "https://api.shoal.xyz/v1/signal/byCategory?category=partnership" \
-H "Authorization: Bearer YOUR_API_KEY"
requests.get(
"https://api.shoal.xyz/v1/signal/byCategory",
headers={"Authorization": f"Bearer {API_KEY}"},
params={"category": "partnership"}
)
const res3 = await fetch(
'https://api.shoal.xyz/v1/signal/byCategory?category=partnership',
{ headers: { Authorization: `Bearer ${API_KEY}` } }
);
Poll the Premium Signal Feed
For broad bulk polling workflows, use the bulk signal feed only if that surface is enabled on your plan.
import time
cursor = "2026-02-01T00:00:00Z"
while True:
r = requests.get(
"https://api.shoal.xyz/v1/signal/all",
headers={"Authorization": f"Bearer {API_KEY}"},
params={"since": cursor},
)
data = r.json()["data"]
if data:
cursor = data[0]["latestPostTimestamp"]
for event in data:
print(event["title"], event["signal"])
time.sleep(60)
Batch Brief (Agent Workflow)
Monitor an entire portfolio in one call when batch brief is available on your plan:
curl -X GET "https://api.shoal.xyz/v1/brief/batch?ids=526,765,1024&since=2026-02-28T00:00:00Z&compact=true" \
-H "Authorization: Bearer YOUR_API_KEY"
PORTFOLIO = "526,765,1024,2048"
r = requests.get(
"https://api.shoal.xyz/v1/brief/batch",
headers={"Authorization": f"Bearer {API_KEY}"},
params={"ids": PORTFOLIO, "since": "2026-02-28T00:00:00Z", "compact": "true"},
)
data = r.json()
for org in data["organizations"]:
if org["counts"]["signal"] > 0:
print(f"{org['label']}: {org['counts']['signal']} new signals")
const portfolio = '526,765,1024,2048';
const briefRes = await fetch(
`https://api.shoal.xyz/v1/brief/batch?ids=${portfolio}&since=2026-02-28T00:00:00Z&compact=true`,
{ headers: { Authorization: `Bearer ${API_KEY}` } }
);
const { organizations } = await briefRes.json();
organizations
.filter(org => org.counts.signal > 0)
.forEach(org => console.log(`${org.label}: ${org.counts.signal} new signals`));
Check Your Usage
curl -X GET "https://api.shoal.xyz/v1/usage" \
-H "Authorization: Bearer YOUR_API_KEY"
Compatibility note
The older organizations/* routes still exist, but new integrations should start with /v1/entities/byName and then traverse the returned Shoal entity id.