{
  "openapi": "3.0.1",
  "info": {
    "title": "Website SEO Audit: Broken Links & Fix List",
    "description": "Crawl a website, verify every internal and external link, and get a prioritized, actionable list of SEO issues with fix instructions.",
    "version": "0.1",
    "x-build-id": "SaQvSsNxOeFNP2XKc"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/zerahdata~website-seo-audit/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-zerahdata-website-seo-audit",
        "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/zerahdata~website-seo-audit/runs": {
      "post": {
        "operationId": "runs-sync-zerahdata-website-seo-audit",
        "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/zerahdata~website-seo-audit/run-sync": {
      "post": {
        "operationId": "run-sync-zerahdata-website-seo-audit",
        "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": {
          "startUrls": {
            "title": "Start URLs",
            "type": "array",
            "description": "Websites to audit. The crawler starts here, follows internal links, and also reads each site's sitemap.xml (via robots.txt) to find pages that aren't linked from the homepage. Accepts objects ({\"url\": \"https://...\"}) or plain URL strings. Note: when calling the Apify API directly (not the Console UI), this field's editor rejects bare domains like 'example.com' - use the 'Domains' field below instead if you only have bare domains.",
            "items": {
              "type": "object",
              "required": [
                "url"
              ],
              "properties": {
                "url": {
                  "type": "string",
                  "title": "URL of a web page",
                  "format": "uri"
                }
              }
            }
          },
          "domains": {
            "title": "Domains (bare domains allowed)",
            "type": "array",
            "description": "Optional additional sites, merged with 'Start URLs' above. Unlike 'Start URLs', this field accepts bare domains (e.g. example.com) with no 'https://' prefix required - useful when calling the Apify API directly, since the 'Start URLs' editor rejects bare domains there. Each entry is audited as https://<domain>/.",
            "items": {
              "type": "string"
            },
            "default": []
          },
          "maxPagesPerSite": {
            "title": "Max pages per site",
            "minimum": 1,
            "maximum": 5000,
            "type": "integer",
            "description": "Maximum number of pages crawled and audited per site (the site a start URL lands on). This is also the number of billable 'page' rows a site can produce. Start URLs on the same site share this budget.",
            "default": 50
          },
          "maxDepth": {
            "title": "Max crawl depth",
            "minimum": 0,
            "maximum": 50,
            "type": "integer",
            "description": "Maximum number of link hops from a start URL. 0 audits only the start URLs. Sitemap-discovered pages are not limited by depth. Set high (e.g. 10) for a thorough crawl, low (e.g. 1-2) to stay close to the homepage.",
            "default": 10
          },
          "sameDomainOnly": {
            "title": "Stay on the same domain",
            "type": "boolean",
            "description": "If enabled (default), the crawler only follows and audits links on the same registrable domain as the start URL (see 'Include subdomains' below). Links leaving the domain are still checked for broken status if 'Check external links' is enabled, but are never crawled as pages.",
            "default": true
          },
          "includeSubdomains": {
            "title": "Include subdomains",
            "type": "boolean",
            "description": "When 'Stay on the same domain' is enabled, also crawl and audit pages on subdomains of the start URL's domain (e.g. blog.example.com and shop.example.com when starting from example.com).",
            "default": false
          },
          "checkExternalLinks": {
            "title": "Check external links",
            "type": "boolean",
            "description": "Verify links that point to other domains (lightweight GET request with a short timeout; 401/403/429 answers are reported as unverified, not broken, because they usually mean the site blocks bots). Results are cached so the same external URL is never checked twice in a run. Disable to skip external checks entirely and reduce run time.",
            "default": true
          },
          "maxExternalLinksChecked": {
            "title": "Max external links checked per run",
            "minimum": 0,
            "maximum": 20000,
            "type": "integer",
            "description": "Caps the total number of unique external URLs verified across the whole run, to bound cost and duration on sites with very many outbound links. Once the cap is reached, remaining external links are left unchecked (not reported as broken or OK).",
            "default": 300
          },
          "respectRobotsTxt": {
            "title": "Respect robots.txt",
            "type": "boolean",
            "description": "Skip URLs disallowed for the configured user agent by the site's robots.txt. Recommended: keep enabled for ethical crawling. The actor still fetches and reports on robots.txt itself (missing / blocking everything) regardless of this setting.",
            "default": true
          },
          "userAgent": {
            "title": "User-Agent header",
            "type": "string",
            "description": "Custom User-Agent string sent on every request, and the agent name used to evaluate robots.txt rules when 'Respect robots.txt' is enabled. Leave at the default unless a site specifically blocks it.",
            "default": "Mozilla/5.0 (compatible; WebsiteSEOAuditBot/1.0; +https://apify.com)"
          },
          "concurrency": {
            "title": "Concurrency",
            "minimum": 1,
            "maximum": 50,
            "type": "integer",
            "description": "Maximum number of parallel HTTP requests (page fetches and link checks) per site. Lower it on slow or rate-limiting sites.",
            "default": 10
          },
          "slowPageThresholdMs": {
            "title": "Slow page threshold (ms)",
            "minimum": 100,
            "maximum": 60000,
            "type": "integer",
            "description": "Pages whose total response time exceeds this threshold are flagged with the 'slow-page' issue and counted in the site summary's slowest pages.",
            "default": 2000
          },
          "excludeUrlPatterns": {
            "title": "Exclude URL patterns",
            "type": "array",
            "description": "Substrings or regex patterns (wrap in slashes, e.g. \"/\\\\/page\\\\/\\\\d+/\") of URLs to skip crawling. Useful for CMS paths like /tag/, /author/, /page/. Matching URLs are never fetched as pages, but may still appear as link-check targets.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "proxyConfiguration": {
            "title": "Proxy configuration",
            "type": "object",
            "description": "Optional proxy configuration. Using Apify Proxy is recommended when auditing many sites or sites that rate-limit datacenter IPs.",
            "default": {
              "useApifyProxy": false
            }
          },
          "trackChanges": {
            "title": "Track changes between runs (monitoring mode)",
            "type": "boolean",
            "description": "If enabled, the actor saves each site's issues, broken links and score in a named key-value store, and compares them to the previous run with the same 'Monitor name'. Differences are output as extra 'change' rows (new/resolved issues, score changes, new/fixed broken links, pages added/removed). The first run with a given monitor name only saves a baseline and reports no changes.",
            "default": false
          },
          "monitorName": {
            "title": "Monitor name",
            "type": "string",
            "description": "Name identifying this monitoring setup, used to pick which saved snapshot to compare against (and update) on each run. Only relevant when 'Track changes between runs' is enabled. Leave empty to auto-derive one from the start URLs/domains - but set a fixed value if you plan to change the list of sites between runs and still want continuous tracking.",
            "default": ""
          },
          "outputMode": {
            "title": "Output mode",
            "enum": [
              "all",
              "issuesOnly",
              "summaryOnly"
            ],
            "type": "string",
            "description": "'All' outputs page rows plus issue, summary and change rows. 'Issues only' suppresses page rows and keeps the fix list, summary and change rows - useful when you only care about what to fix. 'Summary only' keeps just the per-site summary (and change rows). Pricing is per audited page in every mode.",
            "default": "all"
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}