{
  "openapi": "3.1.0",
  "info": {
    "title": "Prop Firm Rules API",
    "version": "v1.0 (dataset prop-firm-rules@0.1.0, last verified 2026-10-04)",
    "summary": "Read-only JSON API for sourced prop-firm drawdown and daily-loss rules, plus a drawdown-room checker.",
    "description": "Public, read-only, CORS-open. Free tier: no key, about 60 requests/minute per IP (best effort). Pay-per-call via x402 may be added later; routes are free today. Every response includes `disclaimer`. Informational only, not financial advice. Prop firms change rules often; always verify every value with the firm's current terms and your account dashboard. Not affiliated with, endorsed by, or sponsored by any prop firm.",
    "license": {
      "name": "MIT (dataset)",
      "url": "https://github.com/kburrus64-max/prop-firm-rules/blob/main/LICENSE"
    }
  },
  "externalDocs": {
    "description": "Human docs",
    "url": "https://floorguard-kappa.vercel.app/api/"
  },
  "servers": [
    {
      "url": "https://floorguard-kappa.vercel.app"
    }
  ],
  "x-disclaimer": "Informational only, not financial advice. Prop firms change rules often; always verify every value with the firm's current terms and your account dashboard. Not affiliated with, endorsed by, or sponsored by any prop firm.",
  "paths": {
    "/api/v1/firms": {
      "get": {
        "operationId": "listFirms",
        "summary": "List firms and programs (ids, sizes, last-verified dates) with dataset version.",
        "responses": {
          "200": {
            "description": "Firms",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FirmsResponse"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests allowed per window (free tier)"
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets"
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/rules": {
      "get": {
        "operationId": "getRules",
        "summary": "Full rule set for one program (daily loss, max drawdown, reset, notes, sources, firm policy).",
        "parameters": [
          {
            "name": "program",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "ftmo_2step",
                "ftmo_1step",
                "fundednext_stellar_2step",
                "the5ers_high_stakes",
                "e8_one",
                "fundingpips_2step_5",
                "fundingpips_2step_3",
                "alpha_pro_10",
                "alpha_pro_8",
                "blue_guardian_2step",
                "topstep_combine",
                "apex_eod_eval",
                "apex_intraday_eval"
              ]
            },
            "example": "ftmo_2step"
          }
        ],
        "responses": {
          "200": {
            "description": "Rules",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RulesResponse"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests allowed per window (free tier)"
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets"
              }
            }
          },
          "400": {
            "description": "Missing program",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown program",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/check": {
      "get": {
        "operationId": "checkAccount",
        "summary": "Remaining daily-loss and max-drawdown room in dollars for an account, and whether a rule is breached.",
        "parameters": [
          {
            "name": "program",
            "in": "query",
            "required": true,
            "description": "Program id from /api/v1/firms, e.g. ftmo_2step",
            "schema": {
              "type": "string",
              "enum": [
                "ftmo_2step",
                "ftmo_1step",
                "fundednext_stellar_2step",
                "the5ers_high_stakes",
                "e8_one",
                "fundingpips_2step_5",
                "fundingpips_2step_3",
                "alpha_pro_10",
                "alpha_pro_8",
                "blue_guardian_2step",
                "topstep_combine",
                "apex_eod_eval",
                "apex_intraday_eval"
              ]
            }
          },
          {
            "name": "accountSize",
            "in": "query",
            "required": true,
            "description": "Nominal account size, e.g. 100000 (must be one of the program sizes when the rule is a fixed $ amount per size)",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "startingBalance",
            "in": "query",
            "required": false,
            "description": "Initial balance the percentages apply to (default: accountSize)",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "currentEquity",
            "in": "query",
            "required": true,
            "description": "Current equity including open P&L",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "currentBalance",
            "in": "query",
            "required": false,
            "description": "Current closed balance (default: currentEquity)",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "highWaterMark",
            "in": "query",
            "required": false,
            "description": "Peak the firm trails from (highest EOD balance / closed balance / intraday equity, per program mode). Default: computed like the site calculator",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "todayPnl",
            "in": "query",
            "required": false,
            "description": "Today's P&L since the firm's daily reset, closed + open (default 0)",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "dayStartBalance",
            "in": "query",
            "required": false,
            "description": "Balance at the daily reset, if positions were held through it (default: currentEquity - todayPnl)",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "customDailyLoss",
            "in": "query",
            "required": false,
            "description": "Your own daily loss limit in $ for programs without one (e.g. Topstep optional DLL)",
            "schema": {
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Check result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CheckResponse"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests allowed per window (free tier)"
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets"
              }
            }
          },
          "400": {
            "description": "Invalid parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown program",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/openapi.json": {
      "get": {
        "operationId": "openapi",
        "summary": "This document.",
        "responses": {
          "200": {
            "description": "OpenAPI document"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Dataset": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "version": {
            "type": "string"
          },
          "commit": {
            "type": "string"
          },
          "lastVerified": {
            "type": "string",
            "format": "date"
          },
          "source": {
            "type": "string"
          },
          "license": {
            "type": "string"
          }
        }
      },
      "Envelope": {
        "type": "object",
        "required": [
          "ok",
          "apiVersion",
          "dataset",
          "disclaimer"
        ],
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "apiVersion": {
            "type": "string"
          },
          "dataset": {
            "$ref": "#/components/schemas/Dataset"
          },
          "disclaimer": {
            "type": "string"
          }
        }
      },
      "Error": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Envelope"
          },
          {
            "type": "object",
            "properties": {
              "error": {
                "type": "object",
                "properties": {
                  "code": {
                    "type": "string"
                  },
                  "message": {
                    "type": "string"
                  },
                  "validPrograms": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        ]
      },
      "FirmsResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Envelope"
          },
          {
            "type": "object",
            "properties": {
              "count": {
                "type": "object"
              },
              "firms": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "programs": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "sizes": {
                            "type": "array",
                            "items": {
                              "type": "number"
                            }
                          },
                          "verified": {
                            "type": "boolean"
                          },
                          "lastVerified": {
                            "type": "string"
                          },
                          "rulesUrl": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              },
              "vocabulary": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          }
        ]
      },
      "RulesResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Envelope"
          },
          {
            "type": "object",
            "properties": {
              "program": {
                "type": "object",
                "description": "dailyLoss {pct|amount|amountBySize, amountBase, reference, kind}, maxDrawdown {pct|amountBySize, mode, lockAt}, reset, notes, sources, verified, lastVerified"
              },
              "firm": {
                "type": "object",
                "description": "id, name, policy (copy trading / automation)"
              }
            }
          }
        ]
      },
      "Limit": {
        "type": [
          "object",
          "null"
        ],
        "properties": {
          "allowance": {
            "type": "number"
          },
          "floor": {
            "type": "number"
          },
          "room": {
            "type": "number",
            "description": "Measured value minus floor (negative = breached)"
          },
          "remaining": {
            "type": "number"
          },
          "breached": {
            "type": "boolean"
          },
          "status": {
            "type": "string",
            "enum": [
              "green",
              "amber",
              "red"
            ]
          }
        }
      },
      "CheckResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Envelope"
          },
          {
            "type": "object",
            "properties": {
              "program": {
                "type": "object"
              },
              "input": {
                "type": "object"
              },
              "result": {
                "type": "object",
                "properties": {
                  "dailyLossRemaining": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "maxDrawdownRemaining": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "breached": {
                    "type": "boolean"
                  },
                  "breachedRules": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "dailyLoss",
                        "maxDrawdown"
                      ]
                    }
                  },
                  "bindingLimit": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "status": {
                    "type": "string"
                  },
                  "daily": {
                    "$ref": "#/components/schemas/Limit"
                  },
                  "maxDrawdown": {
                    "$ref": "#/components/schemas/Limit"
                  }
                }
              },
              "notes": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          }
        ]
      }
    }
  }
}