Skip to documentation
API docs/Signal feedChapters +
Documentation/API reference
v1

API reference

Signal feed

Coverage tiers, response fields, and signal history.

Every row is one indicator changing its mind about one asset on one closed candle. The compute job runs hourly at :03 UTC — 1h readings refresh every hour, 4h on 4-hour boundaries, 1d at 00:00 UTC — so a universe-tier change is logged within ~3-5 minutes of the close that produced it. Rows are append-only: never edited, never selectively removed, they only age out (universe tier 365 days, alert tier 90). The history you evaluate against is the history that actually fired.

Two tiers share one schema, so you never branch on the source. Universe covers all 251 assets × 3 timeframes and logs changes for 6 indicators; its current state also carries PerpKit’s trend reading. Alerts is the narrower set our subscribers receive — the full strategy engines, including PerpKit, with explicit entry and exit actions. Pass tier=universe|alerts|all.

FieldTypeMeaning
idstringStable identifier — safe to dedupe on
tierenum"universe" · "alerts" — which pipeline produced the row
tickerstringAsset symbol, e.g. "BTC"
asset_classenum"crypto" · "stock" · "metal"
indicatorstringStable id, e.g. "trend_oracle"
indicator_namestringHuman-readable name, e.g. "Trend Oracle"
timeframeenum"1h" · "4h" · "1d"
directionenum"bullish" · "bearish" · "neutral" · "exit" — normalized across both tiers
transitionobject | null{from, to} on the universe tier — the state change itself
change_typeenum | null"reversal" (bullish ↔ bearish) · "activation" (neutral → a direction) · "deactivation" (a direction → neutral) on the universe tier; null on the alerts tier
actionstring | nullLONG · SHORT · CLOSE on the alerts tier. CLOSE does not say which side it closes; BUY · SELL are legacy values
pricenumber | nullAsset price when the signal fired
created_atISO 8601When Eclipse wrote the row, not when the signal fired (see timing below)

Timing and known limitations

created_at is when Eclipse wrote the row, not when the signal fired. Universe-tier rows are written by the hourly job a few minutes after the candle that produced them closes; if an asset’s candles had not updated in time, its change is written at that timeframe’s next run instead. Alerts-tier rows are written when the alert job publishes them, and alerts published in the same run carry created_at values milliseconds apart even when they fired on different candles.

Alerts tier only: the same action for the same ticker, indicator and timeframe is published at most once per 20 candles of that timeframe (80 hours on 4h, 20 days on 1d). An alert held back by this rule is published later, when its window ends, or never if another alert for that ticker, indicator and timeframe is published first. The universe tier has no such rule and logs every change.

CLOSE ends the strategy’s open position but does not say whether that position was long or short. Because of the alerts-tier cooldown, the entry it closes may be missing from the feed or published late. BUY and SELL are legacy values; the current alert engines publish LONG, SHORT and CLOSE.

Every change to the API is listed, dated, in the changelog field of the manifest.

# The whole board in one call — every indicator, every asset, every timeframe
curl https://www.eclipse.trade/api/v1/state \
  -H "Authorization: Bearer ek_YOUR_KEY"

# Only what changed since your cursor (poll this every 15 min)
curl "https://www.eclipse.trade/api/v1/signals?since=2026-08-01T12:00:00Z" \
  -H "Authorization: Bearer ek_YOUR_KEY"

# Where 4+ different indicators currently agree, bullish, 4h
curl "https://www.eclipse.trade/api/v1/confluence?timeframe=4h&min_agree=4" \
  -H "Authorization: Bearer ek_YOUR_KEY"
{
  "signals": [
    {
      "id": "…",
      "tier": "universe",
      "ticker": "LINK",
      "asset_class": "crypto",
      "indicator": "trend_oracle",
      "indicator_name": "Trend Oracle",
      "timeframe": "4h",
      "direction": "bullish",
      "transition": { "from": "neutral", "to": "bullish" },
      "change_type": "activation",
      "price": 11.42,
      "created_at": "2026-08-01T12:03:11.412Z"
    }
  ],
  "pagination": { "limit": 50, "offset": 0, "returned": 1,
                  "has_more": false, "next_cursor": "2026-08-01T12:03:11.412Z" }
}

Pagination and polling

Results are newest first. next_cursor is the newest timestamp on the page, not a link to the next page of older events. Advancing since immediately can skip unread events.

For a fixed backlog, keep since and all filters unchanged while increasing offset by limit. Consume every page before saving the newest timestamp from the first page as your next polling watermark. Deduplicate stored events by tier and id.

Offset pagination is not a frozen snapshot: new inserts can shift pages, and an exclusive timestamp can miss late-arriving events at the same time. Use overlapping polling windows and deduplication, and reconcile current readings with /api/v1/state. This interface does not guarantee lossless event replay.

Signals are informational outputs of technical indicators, not investment advice or a solicitation to trade. Past signals do not guarantee future performance. Use of this API is governed by the Eclipse terms of use.

Standard API access is self-serve under the published Eclipse terms of use and the pricing and quota on /api/docs/access. No separately negotiated agreement is required for standard access. There is no formal uptime SLA. Redistribution, resale, or custom commercial terms require a separate written agreement through /api/v1/access-request.

Support & access recovery

Search API documentation

↑ ↓ to navigate · Enter to openEsc to close
Signal feed | Eclipse API