Skip to main content

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.

Overview

The since parameter lets you fetch only events newer than a given timestamp instead of re-fetching everything.
since is required on /v1/radar/all and /v1/signal/all. Those bulk feed endpoints may be limited to higher-tier plans. It is optional on filtered endpoints like byOrganizationId and byCategory.
/v1/radar/all and /v1/signal/all are recent-monitoring surfaces. Their since value cannot be older than 7 days. For deeper history, use scoped routes or contact Shoal about export access.
If you need a merged premium historical surface across both feeds, use /v1/replay/global instead of trying to stretch the bulk feed endpoints into a replay API.

How It Works

  1. First call - fetch recent events:
curl "https://api.shoal.xyz/v1/signal/all?since=2026-04-04T00:00:00Z" \
  -H "Authorization: Bearer YOUR_API_KEY"
  1. Save the cursor - note the latestPostTimestamp from the most recent event in the response (e.g. 2026-02-28T06:18:44Z).
  2. Poll for updates - pass it as the since parameter:
curl "https://api.shoal.xyz/v1/signal/all?since=2026-02-28T06:18:44Z" \
  -H "Authorization: Bearer YOUR_API_KEY"
  1. Handle the response - if data is empty, nothing new has happened. Otherwise, process the new events and update your cursor.
If you only need one organization or one category, prefer the filtered endpoints instead of the bulk feed. They are usually a better fit for operational monitoring.

Supported Endpoints

Endpointsince
GET /v1/radar/allRequired
GET /v1/signal/allRequired
GET /v1/radar/byOrganizationIdOptional
GET /v1/radar/byCategoryOptional
GET /v1/signal/byOrganizationIdOptional
GET /v1/signal/byCategoryOptional

Format

The since parameter accepts any valid ISO 8601 timestamp:
  • 2026-02-28T06:18:44Z
  • 2026-02-28T06:18:44+00:00
  • 2026-02-28
Invalid timestamps (e.g. since=garbage) are rejected with 400 Bad Request.
const API_KEY = process.env.SHOAL_API_KEY;
let cursor = new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString(); // start 24h ago

async function poll() {
  const url = `https://api.shoal.xyz/v1/signal/all?since=${cursor}`;

  const res = await fetch(url, {
    headers: { Authorization: `Bearer ${API_KEY}` },
  });
  const { data } = await res.json();

  if (data.length > 0) {
    // Update cursor to the newest event's timestamp
    cursor = data[0].latestPostTimestamp;
    // Process new events...
  }
}

// Poll every 60 seconds
setInterval(poll, 60_000);

Cursor-Based Pagination

If a poll returns a full page of results, the response includes a next_cursor field. You can pass this as the cursor query parameter (along with the same since value) to fetch the next page without using offset. This is especially useful when there are more results than offset limits allow. See the Pagination Guide for details.

Tips

  • Recommended polling interval: 60 seconds for most use cases
  • Combine with limit: Use since together with limit and offset for paginated polling, or use cursor for cursor-based pagination
  • First call: use a reasonable recent start time (for example 24 hours ago), not an older historical date