{
  "openapi": "3.0.1",
  "info": {
    "title": "Sports Betting Value Bet & Arbitrage Finder",
    "description": "Finds +EV value bets and arbitrage across bookmaker odds datasets. Compares soft-book prices to a sharp bookmaker's no-vig fair odds, with edge %, Kelly fraction and stake splits. Works with Pinnacle, FanDuel, DraftKings, MelBet, 22Bet and 1xBet data.",
    "version": "1.0",
    "x-build-id": "9jSfhsHCvGUEkH1ub"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/mrdoe~odds-value-bet-arbitrage-finder/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-mrdoe-odds-value-bet-arbitrage-finder",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/acts/mrdoe~odds-value-bet-arbitrage-finder/runs": {
      "post": {
        "operationId": "runs-sync-mrdoe-odds-value-bet-arbitrage-finder",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor and returns information about the initiated run in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/runsResponseSchema"
                }
              }
            }
          }
        }
      }
    },
    "/acts/mrdoe~odds-value-bet-arbitrage-finder/run-sync": {
      "post": {
        "operationId": "run-sync-mrdoe-odds-value-bet-arbitrage-finder",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "inputSchema": {
        "type": "object",
        "properties": {
          "oddsDataset1": {
            "title": "Odds dataset 1 (optional)",
            "type": "string",
            "description": "Dataset produced by a bookmaker odds Actor run (Pinnacle, FanDuel, DraftKings, MelBet, 22Bet, 1xBet). Add one per bookmaker; the more books, the more opportunities. Leave all empty to try the Actor on a small built-in sample slate."
          },
          "oddsDataset2": {
            "title": "Odds dataset 2 (optional)",
            "type": "string",
            "description": "Dataset produced by a bookmaker odds Actor run (Pinnacle, FanDuel, DraftKings, MelBet, 22Bet, 1xBet). Add one per bookmaker; the more books, the more opportunities."
          },
          "oddsDataset3": {
            "title": "Odds dataset 3 (optional)",
            "type": "string",
            "description": "Dataset produced by a bookmaker odds Actor run (Pinnacle, FanDuel, DraftKings, MelBet, 22Bet, 1xBet). Add one per bookmaker; the more books, the more opportunities."
          },
          "oddsDataset4": {
            "title": "Odds dataset 4 (optional)",
            "type": "string",
            "description": "Dataset produced by a bookmaker odds Actor run (Pinnacle, FanDuel, DraftKings, MelBet, 22Bet, 1xBet). Add one per bookmaker; the more books, the more opportunities."
          },
          "fetchLiveOdds": {
            "title": "Fetch live odds now",
            "type": "boolean",
            "description": "Runs this repo's own bookmaker Actors (Pinnacle, FanDuel, DraftKings, MelBet, 22Bet, 1xBet) right now and scans their fresh odds, in addition to any datasets above. Each is a separate Actor run on your account, billed and timed as its own run.",
            "default": false
          },
          "liveBookmakers": {
            "title": "Bookmakers to fetch live (optional)",
            "type": "array",
            "description": "Which of pinnacle, fanduel, draftkings, melbet, 22bet, 1xbet to fetch. Leave empty for all six.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "liveSports": {
            "title": "Sports to fetch live (optional)",
            "type": "array",
            "description": "Sports to pass to each bookmaker Actor. Leave empty for soccer.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "liveMaxMatchesPerBook": {
            "title": "Max matches per bookmaker",
            "minimum": 1,
            "type": "integer",
            "description": "Caps how many matches each bookmaker Actor fetches.",
            "default": 20
          },
          "focusBookmaker": {
            "title": "Focus on one bookmaker (optional)",
            "type": "string",
            "description": "Only return opportunities involving this bookmaker (e.g. \"1xbet\", \"melbet\", \"pinnacle\"). Leave empty to see every opportunity across all books.",
            "default": ""
          },
          "sharpBookmaker": {
            "title": "Sharp bookmaker",
            "type": "string",
            "description": "The bookmaker whose no-vig price is treated as the fair price. Its name must match the bookmaker field in the datasets. Used as the single default sharp source when Sharp bookmakers (consensus) below is left empty.",
            "default": "Pinnacle"
          },
          "sharpBookmakers": {
            "title": "Sharp bookmakers for consensus (optional)",
            "type": "array",
            "description": "Two or more bookmakers to combine into a consensus fair price (e.g. Pinnacle, Betfair). Each is normalized (margin removed) independently before combining. Leave empty to use only the single Sharp bookmaker above.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "consensusMethod": {
            "title": "Consensus method",
            "enum": [
              "average",
              "weighted"
            ],
            "type": "string",
            "description": "How multiple sharp sources are combined: a plain average, or weighted by Sharp source weights below.",
            "default": "average"
          },
          "sharpWeights": {
            "title": "Sharp source weights (optional)",
            "type": "object",
            "description": "Only used when Consensus method is \"weighted\". An object of bookmaker name to weight, e.g. {\"pinnacle\": 2, \"betfair\": 1}. A source with no weight listed defaults to 1 (equal weight).",
            "default": {}
          },
          "minimumSharpSources": {
            "title": "Minimum independent sharp sources",
            "minimum": 1,
            "type": "integer",
            "description": "A market is unavailable (no value bet published) unless at least this many distinct, valid, sufficiently fresh sharp sources agree on it.",
            "default": 1
          },
          "mode": {
            "title": "What to find",
            "enum": [
              "both",
              "value",
              "arbitrage"
            ],
            "type": "string",
            "description": "Value bets against the sharp fair price, arbitrage across books, or both.",
            "default": "both"
          },
          "minEdgePercent": {
            "title": "Minimum edge (%)",
            "minimum": 0,
            "type": "number",
            "description": "Only report value bets with at least this expected value, as a percentage of stake (edgePercent = (odds * fairProbability - 1) * 100). A conservative starting point, not a guarantee of profitability.",
            "default": 3
          },
          "minArbitrageMarginPercent": {
            "title": "Minimum arbitrage margin (%)",
            "minimum": 0,
            "type": "number",
            "description": "Only report arbitrage with at least this guaranteed margin.",
            "default": 0
          },
          "enableArbitrageDetection": {
            "title": "Enable arbitrage detection",
            "type": "boolean",
            "description": "When off, arbitrage is never evaluated: every value-bet row's arbitrageStatus is \"not-evaluated\" and no arbitrage rows are produced, regardless of Mode.",
            "default": true
          },
          "bankroll": {
            "title": "Bankroll for stake split",
            "minimum": 1,
            "type": "number",
            "description": "Total amount split across the legs of each arbitrage.",
            "default": 100
          },
          "maxStartDiffHours": {
            "title": "Max start-time difference (hours)",
            "minimum": 0.5,
            "type": "number",
            "description": "Two listings count as the same match when their start times are within this many hours.",
            "default": 3
          },
          "maximumOddsAgeSeconds": {
            "title": "Maximum odds age (seconds)",
            "minimum": 1,
            "type": "integer",
            "description": "Reject a price whose own scrapedAt timestamp is older than this, so a candidate or sharp price is only used while still fresh. Rows with no scrapedAt (age unknown) are not rejected on this basis alone, since that can't be verified either way.",
            "default": 30
          },
          "maximumSnapshotDifferenceSeconds": {
            "title": "Maximum snapshot time difference (seconds)",
            "minimum": 1,
            "type": "integer",
            "description": "Maximum gap between a candidate bookmaker's scrapedAt and the sharp reference's scrapedAt (or between arbitrage legs' scrapedAt) for them to be treated as simultaneous.",
            "default": 30
          },
          "minimumValidOdds": {
            "title": "Minimum valid decimal odds",
            "minimum": 1.001,
            "type": "number",
            "description": "Prices below this are treated as invalid data and excluded.",
            "default": 1.01
          },
          "maximumValidOdds": {
            "title": "Maximum valid decimal odds",
            "minimum": 1.01,
            "type": "number",
            "description": "Prices above this are treated as invalid data and excluded.",
            "default": 1000
          },
          "fractionalKellyMultiplier": {
            "title": "Fractional Kelly multiplier",
            "minimum": 0,
            "type": "number",
            "description": "kellyFraction = max(0, fullKellyFraction) * this multiplier. Default is quarter Kelly (0.25), a common conservative choice; it does not compensate for a poor probability estimate.",
            "default": 0.25
          },
          "maximumKellyFraction": {
            "title": "Maximum Kelly fraction (bankroll cap)",
            "minimum": 0,
            "type": "number",
            "description": "Caps the reported kellyFraction at this bankroll fraction (e.g. 0.05 = 5%), regardless of what the formula alone would suggest.",
            "default": 0.05
          },
          "maxResults": {
            "title": "Max results per type",
            "minimum": 0,
            "type": "integer",
            "description": "Maximum value bets and maximum arbitrage returned. Default is 5 for a quick test; set 0 to return everything found.",
            "default": 5
          }
        }
      },
      "runsResponseSchema": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "actId": {
                "type": "string"
              },
              "userId": {
                "type": "string"
              },
              "startedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "finishedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "status": {
                "type": "string",
                "example": "READY"
              },
              "meta": {
                "type": "object",
                "properties": {
                  "origin": {
                    "type": "string",
                    "example": "API"
                  },
                  "userAgent": {
                    "type": "string"
                  }
                }
              },
              "stats": {
                "type": "object",
                "properties": {
                  "inputBodyLen": {
                    "type": "integer",
                    "example": 2000
                  },
                  "rebootCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "restartCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "resurrectCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "computeUnits": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "options": {
                "type": "object",
                "properties": {
                  "build": {
                    "type": "string",
                    "example": "latest"
                  },
                  "timeoutSecs": {
                    "type": "integer",
                    "example": 300
                  },
                  "memoryMbytes": {
                    "type": "integer",
                    "example": 1024
                  },
                  "diskMbytes": {
                    "type": "integer",
                    "example": 2048
                  }
                }
              },
              "buildId": {
                "type": "string"
              },
              "defaultKeyValueStoreId": {
                "type": "string"
              },
              "defaultDatasetId": {
                "type": "string"
              },
              "defaultRequestQueueId": {
                "type": "string"
              },
              "buildNumber": {
                "type": "string",
                "example": "1.0.0"
              },
              "containerUrl": {
                "type": "string"
              },
              "usage": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "integer",
                    "example": 1
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "usageTotalUsd": {
                "type": "number",
                "example": 0.00005
              },
              "usageUsd": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "number",
                    "example": 0.00005
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}