{
  "openapi": "3.0.1",
  "info": {
    "title": "Wattpad Scraper - Stories, Chapters, Authors & Comments",
    "description": "Scrape Wattpad stories by keyword, tag, category, language or URL. Extract authors, reads, votes, tags, completion status and chapter lists, with optional chapter text, full comment threads, inline paragraph comments and replies.",
    "version": "0.1",
    "x-build-id": "Hh3ECGfndPXml07uG"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/abotapi~wattpad-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-abotapi-wattpad-scraper",
        "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/abotapi~wattpad-scraper/runs": {
      "post": {
        "operationId": "runs-sync-abotapi-wattpad-scraper",
        "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/abotapi~wattpad-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-abotapi-wattpad-scraper",
        "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",
        "required": [
          "mode"
        ],
        "properties": {
          "mode": {
            "title": "Mode",
            "enum": [
              "search",
              "url"
            ],
            "type": "string",
            "description": "Choose 'search' to walk the site's story index by keyword, category, language and completion state, or 'url' to scrape pasted story links, chapter links and plain story ids.",
            "default": "search"
          },
          "query": {
            "title": "Search keyword",
            "type": "string",
            "description": "Only used when mode = search, ignored in url mode. Free text, for example 'werewolf', 'enemies to lovers' or an author name. Leave empty to read the site's default listing instead of a keyword search. A keyword search reaches a much deeper result set than the category and default listings, which the site caps at 1,500 rows."
          },
          "category": {
            "title": "Category",
            "enum": [
              "any",
              "Teen Fiction",
              "Poetry",
              "Fantasy",
              "Romance",
              "Science Fiction",
              "Fanfiction",
              "Humor",
              "Mystery / Thriller",
              "Horror",
              "Classics",
              "Adventure",
              "Paranormal",
              "Action",
              "Non-Fiction",
              "Werewolf",
              "Historical Fiction",
              "ChickLit",
              "General Fiction",
              "Short Story",
              "Vampire",
              "Random",
              "Spiritual"
            ],
            "type": "string",
            "description": "Only used when mode = search, ignored in url mode. One of the site's own categories. The list is checked against the site's OWN published category list on every run, so a category the site has renamed or retired is reported by name instead of being dropped silently. Note the site's own behaviour: a category listing is capped at 1,500 rows, far below a keyword search.",
            "default": "any"
          },
          "filter": {
            "title": "Completion state",
            "enum": [
              "all",
              "complete"
            ],
            "type": "string",
            "description": "Only used when mode = search, ignored in url mode. Keep every story, or keep only the ones the author has marked finished. Applied by the site itself: a completed-only keyword search returns a genuinely smaller result set, not the same set with rows dropped afterwards.",
            "default": "all"
          },
          "language": {
            "title": "Language",
            "enum": [
              "any",
              "Arabic",
              "Czech",
              "Dutch",
              "English",
              "French",
              "German",
              "Greek",
              "Hebrew",
              "Hindi",
              "Hungarian",
              "Indonesian",
              "Italian",
              "Malay",
              "Other",
              "Persian",
              "Polish",
              "Portuguese",
              "Romanian",
              "Russian",
              "Serbian",
              "Slovak",
              "Spanish",
              "Tagalog",
              "Turkish",
              "Ukrainian",
              "Vietnamese"
            ],
            "type": "string",
            "description": "Only used when mode = search, ignored in url mode. The language a story is written in. Applied by the site itself: the name you pick is resolved to the site's own numeric language id against the list it publishes on the day of the run, and that id is sent with the search, so the site returns a smaller result set instead of this actor reading the whole index and dropping most of it. The 26 values offered are the languages the site says stories can be written in; the other languages it publishes exist for its own interface only. A value the site has since retired stops the run by name. Leave on 'Any language' to search every language.",
            "default": "any"
          },
          "startUrls": {
            "title": "Story or chapter links",
            "type": "array",
            "description": "Only used when mode = url, ignored in search mode. Story addresses of the form /story/<id>-slug, chapter addresses of the form /<chapterId>-slug, or plain numeric story ids. Mix all three freely.",
            "items": {
              "type": "string"
            }
          },
          "tags": {
            "title": "Keep only stories carrying these tags",
            "type": "array",
            "description": "Optional, applies in both modes. Tags written the way they appear under a story, for example 'werewolf', 'enemiestolovers' or 'shortstory'. Capitals and spacing do not matter. A story is kept when it carries at least one of them. Leave empty to keep every story. Because the site's own index ignores its tag parameter, this is applied to the tag list the site returns on every story, so no extra request is made and nothing is charged for it.",
            "items": {
              "type": "string"
            }
          },
          "mature": {
            "title": "Include mature-flagged stories",
            "type": "boolean",
            "description": "On by default, applies in both modes. Leave on to keep every story. Switch off to drop stories the site flags as mature, judged on each story's own flag after it is read. Worth knowing before you rely on it: the site's public search index does not return mature-flagged stories at all, so this bites in url mode and on stories reached by their own link, and changes almost nothing in search mode.",
            "default": true
          },
          "fetchChapters": {
            "title": "Include the chapter list",
            "type": "boolean",
            "description": "On by default and free of charge. Returns the story's chapter list: each chapter's id, title, link, publish and update stamps, length, and its own read, vote and comment counters. These arrive inside the story record, so this costs no extra request and never triggers a detail-enrichment charge on its own.",
            "default": true
          },
          "fetchChapterText": {
            "title": "Also download the full chapter text",
            "type": "boolean",
            "description": "Off by default. Downloads the body text of every chapter returned, split into the site's own numbered paragraphs so an inline comment can be matched back to the paragraph it was written on. This is ONE EXTRA REQUEST PER CHAPTER, and a long story can carry over a hundred chapters, so switch it on deliberately. The story is billed a single detail-enrichment event however many chapters it took.",
            "default": false
          },
          "fetchComments": {
            "title": "Also download the comment thread",
            "type": "boolean",
            "description": "Off by default. Walks the story's comment thread chapter by chapter and returns every comment with its author, body, exact time, reply count and permalink. Both kinds come back in one pass: comments left at the end of a chapter, and inline comments written against one specific paragraph, each carrying the paragraph id it belongs to. Extra requests, billed as the same single detail-enrichment event per story.",
            "default": false
          },
          "commentScope": {
            "title": "Which comments to keep",
            "enum": [
              "all",
              "part",
              "inline"
            ],
            "type": "string",
            "description": "Used with the comment thread. The site returns end-of-chapter comments and inline paragraph comments in one walk, so all three settings cost the same requests; this decides what is kept in the record. Inline comments carry the paragraph they were written on, end-of-chapter comments do not.",
            "default": "all"
          },
          "maxCommentsPerStory": {
            "title": "Max comments per story",
            "minimum": 0,
            "type": "integer",
            "description": "Cap on how many comments are returned for one story, counted across all of its chapters. Use 0 to return the story without its thread. Popular stories carry hundreds of thousands of comments, so a cap keeps a run predictable. Each record reports how many were returned and whether the thread was exhausted.",
            "default": 50
          },
          "includeReplies": {
            "title": "Also fetch replies to each comment",
            "type": "boolean",
            "description": "Off by default. A comment's reply count always comes back; switch this on to also fetch the replies themselves, which is one extra request per comment that has any. Still billed inside the same single detail-enrichment event for that story.",
            "default": false
          },
          "maxRepliesPerComment": {
            "title": "Max replies per comment",
            "minimum": 0,
            "type": "integer",
            "description": "Used only when replies are fetched. Cap on how many replies are returned under one comment. Use 0 for every reply the site publishes for it.",
            "default": 5
          },
          "maxItems": {
            "title": "Max results",
            "minimum": 0,
            "type": "integer",
            "description": "Maximum number of stories to return across the whole run. Use 0 for unlimited. Note the site's own limit underneath it: one search scope stops serving rows past result 10,000 even when it advertises a far larger total, and category and default listings stop at 1,500. When a scope is cut short that way the run says so, and incremental mode will not mark anything expired from a scan it knows was incomplete.",
            "default": 10
          },
          "maxPages": {
            "title": "Max result pages per scope",
            "minimum": 0,
            "type": "integer",
            "description": "Maximum number of index pages read per search scope. 0 means no limit, which is the default: the run then stops only at Max results, at the end of the results, or at the site's own depth limit.",
            "default": 0
          },
          "resumeFromRunId": {
            "title": "Resume from a previous run",
            "type": "string",
            "description": "Paste a previous run ID or dataset ID to continue a large pull without returning or charging for stories already collected there. Use this after an interrupted run. For recurring daily monitoring of the same search, use Incremental mode below instead."
          },
          "incrementalMode": {
            "title": "Incremental changes for scheduled runs",
            "type": "boolean",
            "description": "Turn this on for daily or recurring monitoring. The first run returns every matching story as NEW. Later runs normally return only NEW, UPDATED and REAPPEARED stories. Turn on Emit unchanged or Emit expired only when you also want those rows returned (and billed). State is kept separately for each mode, target and filter setup; use State key to name or deliberately share a monitoring campaign. To continue one specific interrupted run instead, use Resume from a previous run above.",
            "default": false
          },
          "stateKey": {
            "title": "State key (optional, incremental mode only)",
            "type": "string",
            "description": "Optional. Name this monitoring campaign to keep its state stable, or to deliberately share state across differently configured runs. Leave empty to let the actor derive a key automatically from the mode, targets and filters, so different searches never mix state with each other."
          },
          "emitUnchanged": {
            "title": "Emit unchanged records (incremental mode only)",
            "type": "boolean",
            "description": "Off by default. Turn on to also return stories that have not changed since the last run, marked UNCHANGED. This returns, and bills, extra rows you already have, so leave it off unless you want the full snapshot every run.",
            "default": false
          },
          "emitExpired": {
            "title": "Emit expired records (incremental mode only)",
            "type": "boolean",
            "description": "Off by default. Turn on to also return stories that were present in a previous run but are no longer found, marked EXPIRED. Only produced once a run has fully scanned the tracked search, so never when Max results capped it, never when Resume was used, and never when a scope hit the site's own result-depth limit. This returns, and bills, extra synthetic rows, so leave it off unless you need expiry tracking.",
            "default": false
          },
          "proxy": {
            "title": "Proxy configuration",
            "type": "object",
            "description": "Apify Proxy is recommended. The standard pool is the default and is sufficient for this site.",
            "default": {
              "useApifyProxy": true
            }
          },
          "mcpConnectors": {
            "title": "Pipe results into your apps (optional)",
            "type": "array",
            "description": "Optionally send results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize one under Apify, Settings, API & Integrations, then select it here. Notion gets a rich page-per-item export; other connectors get a best-effort write or digest. Leave empty to skip; never changes the dataset output. Supported: Notion (https://mcp.notion.com/mcp), Linear (https://mcp.linear.app/sse), Airtable (https://mcp.airtable.com/mcp), Apify (https://mcp.apify.com)."
          },
          "notionParentPageUrl": {
            "title": "Notion parent page (Notion connector only)",
            "type": "string",
            "description": "URL or id of the Notion page under which item pages are created. Required to enable the Notion export; ignored by other connectors."
          },
          "maxNotifyListings": {
            "title": "Max items to export per connector",
            "minimum": 1,
            "maximum": 1000,
            "type": "integer",
            "description": "Cap on items written to each connector per run. Does not affect the dataset.",
            "default": 50
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}