Skip to main content
POST
/
v1
/
admin
/
control-plane
/
matcher-subscriptions
Admin Control Plane Matcher Subscriptions
curl --request POST \
  --url https://api.glider.fi/v1/admin/control-plane/matcher-subscriptions \
  --header 'X-API-KEY: <api-key>'
This route gives a centralized matcher service a stable, typed feed of active authored workflow subscriptions without coupling that matcher to raw workflow rows or Cloudflare dynamic worker internals.

Scope

  • Internal-only
  • Protected by ADMIN_AUTH_SECRET_TOKEN
  • Intended for matcher/control-plane infrastructure, not browser traffic

Request

{
  "limit": 200,
  "ownerAddress": "0x1111111111111111111111111111111111111111",
  "portfolioId": "pf_123"
}
Optional fields:
  • limit
  • ownerAddress
  • portfolioId
  • workflowIds

Response

{
  "asOfIso": "2026-04-14T20:15:00.000Z",
  "subscriptions": [
    {
      "subscriptionId": "wf_123",
      "workflowId": "wf_123",
      "workflowKind": "monitor_then_action",
      "ownerAddress": "0x1111111111111111111111111111111111111111",
      "portfolioId": "pf_123",
      "linkedPortfolioIds": ["pf_123"],
      "status": "active",
      "title": "Buy ETH on threshold",
      "trigger": {
        "dependencies": [
          {
            "kind": "market.price",
            "assetId": "eth:8453",
            "venue": "coinbase"
          },
          {
            "kind": "account.cash_usd",
            "ref": "source"
          },
          {
            "kind": "portfolio.held_asset_metrics",
            "ref": "target",
            "lookbackWindow": "24h"
          }
        ],
        "watchKeys": [
          "market.price:eth:8453:coinbase",
          "account.cash_usd:source",
          "portfolio.held_asset_metrics:target:24h"
        ],
        "cadence": {
          "mode": "event",
          "minIntervalSeconds": 60
        },
        "semantics": {
          "matchMode": "edge",
          "rearm": "cooldown",
          "cooldownSeconds": 3600
        },
        "runtime": {
          "singleton": {
            "kind": "portfolio",
            "ref": "target"
          }
        },
        "summary": "Monitor ETH and portfolio metrics for a buy opportunity."
      },
      "monitor": {
        "status": "waiting",
        "lastEvaluatedAt": "2026-04-14T10:00:00.000Z",
        "nextWakeAt": "2026-04-14T11:00:00.000Z",
        "waitingUntil": "2026-04-14T11:00:00.000Z",
        "retryAfter": null,
        "retryCount": 0,
        "triggerSummary": null
      },
      "evaluationTarget": {
        "provider": "cloudflare_strategy_facet",
        "portfolioId": "pf_123",
        "strategyId": "wf_123",
        "workflowId": "wf_123"
      },
      "route": {
        "notifyPath": "/v1/admin/control-plane/workflow-monitors/notify-trigger-match",
        "ownerAddress": "0x1111111111111111111111111111111111111111",
        "portfolioId": "pf_123",
        "workflowId": "wf_123"
      }
    }
  ]
}

Notes

  • The first cut intentionally includes only authored_sdk workflows.
  • watchKeys are matcher indexing helpers, not replacements for canonical dependency descriptors.
  • Supported shared-fact families now include market, account, approval, and portfolio-relative lanes such as approval.pending_count, account.buying_power_usd, portfolio.cash_pct, portfolio.drift_from_target, and portfolio.concentration.
  • evaluationTarget.provider tells downstream infrastructure whether the authored evaluation path currently resolves to Cloudflare StrategyFacet runtime or a temporary shared-service fallback.
  • Trigger delivery still flows through POST /v1/admin/control-plane/workflow-monitors/notify-trigger-match.
  • ownerAddress is useful for tenant-scoped matcher workers that only want subscriptions for one authenticated owner lane at a time.

Runtime behavior

The intended centralized matcher loop is:
  1. load matcher subscriptions
  2. compile shared dependency watches from trigger.dependencies and watchKeys
  3. maintain cooldown/rearm state outside per-portfolio actors
  4. on match, call notify-trigger-match
  5. let Cloudflare resume or start the correct durable monitor workflow