{
  "openapi": "3.1.0",
  "info": {
    "title": "EarlyFra.me Edge Signal Orchestration API",
    "version": "7.1.2",
    "summary": "Stateful 1-to-4 edge webhook fan-out with confluence traps, approval gates, durable retries and replay.",
    "description": "Route one inbound webhook to up to four destinations with de-duplication, JSON rescue, stateful multi-signal confluence traps, human-in-the-loop approval gates, UTC blackout windows, a durable retry queue and time-travel replay.",
    "termsOfService": "https://earlyfra.me/terms",
    "contact": {
      "name": "EarlyFra.me Engineering",
      "email": "curator@earlyfra.me",
      "url": "https://earlyfra.me/contact"
    },
    "license": {
      "name": "Proprietary",
      "url": "https://earlyfra.me/terms"
    }
  },
  "servers": [
    {
      "url": "https://relay.earlyfra.me",
      "description": "Production"
    },
    {
      "url": "https://earlyfra.me",
      "description": "Apex"
    }
  ],
  "externalDocs": {
    "description": "Full documentation",
    "url": "https://earlyfra.me/docs/mcp"
  },
  "security": [
    {
      "apiKeyAuth": []
    }
  ],
  "tags": [
    {
      "name": "routes",
      "description": "Fan-out route configuration"
    },
    {
      "name": "telemetry",
      "description": "Live execution telemetry and signal memory"
    },
    {
      "name": "orchestration",
      "description": "Confluence traps and replay"
    },
    {
      "name": "approvals",
      "description": "Human-in-the-loop holds"
    },
    {
      "name": "templates",
      "description": "Schema extraction, template preview and template saves"
    },
    {
      "name": "billing",
      "description": "Plans, checkout and machine-payable claims"
    }
  ],
  "paths": {
    "/v1/hook/{whk_token}": {
      "post": {
        "tags": [
          "routes"
        ],
        "summary": "Ingest a webhook (isolated route token)",
        "description": "Primary ingest endpoint. Substitute the per-route whk_ token minted when the route was created. No Master Passkey required.",
        "security": [],
        "parameters": [
          {
            "name": "whk_token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "whk_2f9c1a8b7d6e5f4a"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            },
            "text/plain": {
              "schema": {
                "type": "string"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Signal delivered to every configured target.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "202": {
            "description": "Buffered, waiting on a confluence leg.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Unparseable payload.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "404": {
            "description": "Unknown route token.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "429": {
            "description": "Quota exhausted.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/v1/approve/{approvalId}": {
      "get": {
        "tags": [
          "approvals"
        ],
        "summary": "Resolve a held execution with a signed decision",
        "description": "One-click decision link embedded in the chat notification. `sig` is an HMAC over `<approvalId>:<action>`. Honoured exactly once. `rearm` is a separate signature that fires an already-expired hold once, up to 24h after its deadline; an expired `approve` link stays permanently inert.",
        "security": [],
        "parameters": [
          {
            "name": "approvalId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "action",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "approve",
                "reject",
                "rearm"
              ],
              "default": "approve"
            }
          },
          {
            "name": "sig",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Decision applied (HTML confirmation card).",
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Invalid signature.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "404": {
            "description": "Hold aged past the 7-day retention window (HTML card for a browser click).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "409": {
            "description": "Already settled.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "410": {
            "description": "Hold window closed. Within 24h of the deadline the card carries a signed `action=rearm` link.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/routes": {
      "get": {
        "tags": [
          "routes"
        ],
        "summary": "List deployed routes",
        "security": [
          {
            "apiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "X-EarlyFrame-Key": {
              "description": "Master Passkey (ef_live_...) or Sandbox Passkey",
              "schema": {
                "type": "string"
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Routes for the authenticated passkey.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid passkey.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "routes"
        ],
        "summary": "Create or update a route",
        "security": [
          {
            "apiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "X-EarlyFrame-Key": {
              "description": "Master Passkey (ef_live_...) or Sandbox Passkey",
              "schema": {
                "type": "string"
              }
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Route saved.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "402": {
            "description": "Tier required for write operations.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/telemetry": {
      "get": {
        "tags": [
          "telemetry"
        ],
        "summary": "Inspect live execution telemetry",
        "security": [
          {
            "apiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "X-EarlyFrame-Key": {
              "description": "Master Passkey (ef_live_...) or Sandbox Passkey",
              "schema": {
                "type": "string"
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Latest executions with inbound edge location, delivery latency and drop reasons.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/signals": {
      "get": {
        "tags": [
          "telemetry"
        ],
        "summary": "Query signal memory",
        "security": [
          {
            "apiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "X-EarlyFrame-Key": {
              "description": "Master Passkey (ef_live_...) or Sandbox Passkey",
              "schema": {
                "type": "string"
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Archived executions plus legs waiting in a confluence window.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/confluence": {
      "post": {
        "tags": [
          "orchestration"
        ],
        "summary": "Arm a multi-signal confluence trap",
        "security": [
          {
            "apiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "X-EarlyFrame-Key": {
              "description": "Master Passkey (ef_live_...) or Sandbox Passkey",
              "schema": {
                "type": "string"
              }
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Trap armed or disarmed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/replay": {
      "post": {
        "tags": [
          "orchestration"
        ],
        "summary": "Replay / backtest an archived event",
        "security": [
          {
            "apiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "X-EarlyFrame-Key": {
              "description": "Master Passkey (ef_live_...) or Sandbox Passkey",
              "schema": {
                "type": "string"
              }
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Replay evaluation.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/approvals": {
      "get": {
        "tags": [
          "approvals"
        ],
        "summary": "List executions currently held for approval",
        "security": [
          {
            "apiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "X-EarlyFrame-Key": {
              "description": "Master Passkey (ef_live_...) or Sandbox Passkey",
              "schema": {
                "type": "string"
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Held executions.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/inbounds": {
      "get": {
        "tags": [
          "templates"
        ],
        "summary": "Read the raw bytes a sender POSTed",
        "description": "MCP twin: `inspect_inbound_payload`. One execution by `event_id`, or the newest `limit` for a `route_id`. Reports what arrived, before parsing, enrichment or filtering — which is what a template has to be written against. Costs no quota.",
        "security": [
          {
            "apiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "X-EarlyFrame-Key": {
              "description": "Master Passkey (ef_live_...) or Sandbox Passkey",
              "schema": {
                "type": "string"
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Retained inbound payloads.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "404": {
            "description": "Unknown event_id or route.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/schema-catalog": {
      "get": {
        "tags": [
          "templates"
        ],
        "summary": "Extract the {{tokens}} live traffic actually fills",
        "description": "MCP twin: `extract_schema_tokens`. Dot-notation paths (nested objects, array projections) with inferred type, sample values and presence ratio. Send `template_body` to also get which tokens resolve, which were omitted, and the cleaned render.",
        "security": [
          {
            "apiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "X-EarlyFrame-Key": {
              "description": "Master Passkey (ef_live_...) or Sandbox Passkey",
              "schema": {
                "type": "string"
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Field catalogue plus retained samples.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/templates/preview": {
      "post": {
        "tags": [
          "templates"
        ],
        "summary": "Dry-run a template without saving a route",
        "description": "MCP twin: `preview_alert_template`. Body takes `raw_payload` or a retained `event_id`, optional `route_id`, and any of `template_title`, `template_body`, `custom_body_template`. Returns the rendered alert, the exact JSON each destination would receive and the tokens omitted because the payload did not carry them. Charges no quota.",
        "security": [
          {
            "apiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "X-EarlyFrame-Key": {
              "description": "Master Passkey (ef_live_...) or Sandbox Passkey",
              "schema": {
                "type": "string"
              }
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Preview envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Neither raw_payload nor a retained event_id was supplied.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/agents/plans": {
      "get": {
        "tags": [
          "billing"
        ],
        "summary": "Machine-readable plan catalog",
        "security": [],
        "responses": {
          "200": {
            "description": "Plans with settlement currencies.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/agents/subscribe": {
      "post": {
        "tags": [
          "billing"
        ],
        "summary": "Machine-payable checkout",
        "security": [],
        "description": "Creates a crypto deposit address. Returns pay_address, pay_amount, pay_currency and claim_token.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "plan_id": {
                    "type": "string",
                    "example": "neural_monthly"
                  },
                  "email": {
                    "type": "string",
                    "format": "email"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Deposit instructions + claim token.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/agents/claim": {
      "post": {
        "tags": [
          "billing"
        ],
        "summary": "Claim a settled subscription for a Master Passkey",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "order_id": {
                    "type": "string"
                  },
                  "claim_token": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Status becomes completed and ef_live_... is returned.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/agents/status": {
      "get": {
        "tags": [
          "billing"
        ],
        "summary": "Subscription tier, quota and expiry",
        "security": [
          {
            "apiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "X-EarlyFrame-Key": {
              "description": "Master Passkey (ef_live_...) or Sandbox Passkey",
              "schema": {
                "type": "string"
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Current subscription state.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/health": {
      "get": {
        "tags": [
          "telemetry"
        ],
        "summary": "Liveness probe",
        "security": [],
        "responses": {
          "200": {
            "description": "Engine status and enabled feature flags.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "X-EarlyFrame-Key",
        "description": "Master Passkey (ef_live_...) or Sandbox Passkey."
      }
    }
  }
}