{
  "openapi": "3.0.1",
  "info": {
    "title": "Marketplace Signal",
    "description": "Scrape Framer Marketplace and ThemeForest to compare templates across both. Deterministic opportunity grades, category density, price benchmarks, and cross-marketplace signals — no AI — for niche selection, pricing calibration, and deciding where to sell.",
    "version": "0.0",
    "x-build-id": "KYv4h3oavY77HVkIz"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/bessuraba~marketplace-signal/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-bessuraba-marketplace-signal",
        "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/bessuraba~marketplace-signal/runs": {
      "post": {
        "operationId": "runs-sync-bessuraba-marketplace-signal",
        "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/bessuraba~marketplace-signal/run-sync": {
      "post": {
        "operationId": "run-sync-bessuraba-marketplace-signal",
        "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": {
          "source": {
            "title": "Source marketplace(s)",
            "type": "array",
            "description": "Which marketplace site(s) to run — named after the site itself, not its parent company. Leave empty to run the default, 'Framer Marketplace' only. 'ThemeForest' is implemented but not run by default — Envato (its operator)'s Acceptable Use Policy bans scraping outright (see docs/legal/legal-risk-assessment.md), so it must be named explicitly to opt in. An unknown value errors rather than silently falling back to \"run everything\".",
            "items": {
              "type": "string",
              "enum": [
                "framer",
                "themeforest"
              ],
              "enumTitles": [
                "Framer Marketplace",
                "ThemeForest"
              ]
            },
            "default": []
          },
          "type": {
            "title": "Item type",
            "enum": [
              "template",
              "plugin",
              "component",
              "theme"
            ],
            "type": "string",
            "description": "A shared vocabulary across sources — never a source's own name, that's what `source` is for. Meaning and validity are still source-specific: Framer accepts \"template\"/\"plugin\"/\"component\" (its three marketplace sections, defaults to \"template\"; verified live 2026-09-07: framer.com/marketplace/{templates,plugins,components}/ are all real, distinct sections). ThemeForest accepts \"template\"/\"theme\" (its site-templates vs. WordPress-themes category trees, defaults to \"template\"; verified live 2026-09-07: themeforest.net/category/{site-templates,wordpress} are both real). \"template\" is valid for both at once — that's intentional overlap, not a collision, since `type` is always read together with `source`. Leave empty to use each requested source's own default; an explicit value invalid for that source errors rather than silently falling back."
          },
          "category": {
            "title": "Category",
            "type": "string",
            "description": "Filter by category — taxonomy differs per source, not a shared list. The dropdown below is every known-real category across both sources, combined (Framer's 49/6/6 template/plugin/component slugs plus ThemeForest's 8/7 template/theme subcategory slugs) — pick one, or type your own: neither list is proven exhaustive (Framer's own API confirms real categories exist outside its scraped list, e.g. \"coaching\", \"startup\", \"non-profit\"; ThemeForest's nav undercounted its own page's tile data the same way), so this is suggestions, not a closed set — see README's Category taxonomy section for which values belong to which source/type. Leave empty to scrape the unfiltered root/taxonomy."
          },
          "search": {
            "title": "Search (Framer only)",
            "type": "string",
            "description": "Filters results by title. Applied client-side against rendered-page results; if the internal API fallback kicks in, it also runs as real server-side search there. Not supported for ThemeForest yet (v1 is category-browsing only) — set for that source is ignored with a warning."
          },
          "sort": {
            "title": "Sort (Framer only)",
            "enum": [
              "newest",
              "popular"
            ],
            "type": "string",
            "description": "Result ordering, matching Framer's own \"Latest\"/\"Trending\" toggle. Verified live 2026-09-07 on both the rendered page and the internal API: 'popular' reorders results to match the site's \"Trending\" tab. Not applied when 'search' is set — untested in combination with search relevance ranking.",
            "default": "newest"
          },
          "priceFilter": {
            "title": "Price filter",
            "enum": [
              "all",
              "free",
              "paid"
            ],
            "type": "string",
            "description": "Filter to free-only or paid-only items. Client-side only — verified live 2026-09-07 that Framer's internal API silently ignores both `isFree` and `sort=price` params, so there is no real server-side equivalent to ask for. Applied after price is known, before an item counts toward maxResults, so a narrow filter on a mostly-opposite category can return fewer than maxResults.",
            "default": "all"
          },
          "maxResults": {
            "title": "Max results",
            "minimum": 1,
            "type": "integer",
            "description": "Maximum number of items to scrape and output. Framer: rendered pages alone cap out around ~24-30 per category/search, the internal API fills the rest automatically. ThemeForest: capped at whatever one category page naturally contains (~40, ~126 seen on the WordPress-themes root) — v1 doesn't paginate, so a higher value is a no-op past that.",
            "default": 50
          },
          "proxyConfiguration": {
            "title": "Proxy configuration",
            "type": "object",
            "description": "Apify Proxy settings, used as-is for Framer's requests. ThemeForest defaults to the RESIDENTIAL group instead (Cloudflare blocks datacenter IPs much harder) unless you set this field, in which case your choice is used for both sources.",
            "default": {
              "useApifyProxy": true
            }
          }
        }
      },
      "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
                  }
                }
              },
              "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}