{
  "openapi": "3.0.1",
  "info": {
    "title": "SpringerLink Scraper — Journals, Books & Conference Papers",
    "description": "Scrape SpringerLink journals, books and conference papers: abstracts, author keywords, full author lists with affiliations and ORCIDs, open-access status, PDF links and exact citation counts. Includes incremental monitoring that emits only new or updated papers.",
    "version": "1.0",
    "x-build-id": "oG2Ef5c3AfCWtfVMR"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/trev0n~springerlink-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-trev0n-springerlink-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/trev0n~springerlink-scraper/runs": {
      "post": {
        "operationId": "runs-sync-trev0n-springerlink-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/trev0n~springerlink-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-trev0n-springerlink-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",
        "properties": {
          "searchQuery": {
            "title": "🔍 Search query",
            "type": "array",
            "description": "What to search for. Add several queries to run them in one go (e.g. \"machine learning\", \"battery recycling\"). Leave empty if you use journals or direct URLs instead.",
            "items": {
              "type": "string"
            }
          },
          "journalIds": {
            "title": "📚 Journals",
            "type": "array",
            "description": "Restrict the run to specific journals. Accepts a SpringerLink journal id (the number in link.springer.com/journal/10994) or an ISSN (e.g. 1573-0565). With no search query this collects everything the journal published, newest first.",
            "items": {
              "type": "string"
            }
          },
          "issn": {
            "title": "🔢 ISSN",
            "type": "string",
            "description": "A single journal ISSN to scope the search to. Same effect as adding it to Journals."
          },
          "contentType": {
            "title": "📄 Content type",
            "enum": [
              "any",
              "article",
              "chapter",
              "book",
              "reference-work-entry",
              "protocol"
            ],
            "type": "string",
            "description": "Limit results to one kind of publication. Springer files conference papers as book chapters, so they arrive together; full mode then labels the ones it can confirm as conference papers.",
            "default": "any"
          },
          "yearFrom": {
            "title": "📅 Published from (year)",
            "minimum": 1800,
            "maximum": 2100,
            "type": "integer",
            "description": "Only include publications from this year onwards."
          },
          "yearTo": {
            "title": "📅 Published to (year)",
            "minimum": 1800,
            "maximum": 2100,
            "type": "integer",
            "description": "Only include publications up to and including this year."
          },
          "publishedWithin": {
            "title": "🕒 Published within",
            "enum": [
              "any",
              "m3",
              "m6",
              "m12",
              "m24"
            ],
            "type": "string",
            "description": "Keep only recently published work, counted back from today. Ignored when a year range above is set.",
            "default": "any"
          },
          "sortBy": {
            "title": "↕️ Sort by",
            "enum": [
              "relevance",
              "newest",
              "oldest"
            ],
            "type": "string",
            "description": "Result order.",
            "default": "relevance"
          },
          "openAccessOnly": {
            "title": "🔓 Open access only",
            "type": "boolean",
            "description": "Keep only freely readable publications.",
            "default": false
          },
          "minCitations": {
            "title": "📈 Minimum citations",
            "minimum": 0,
            "type": "integer",
            "description": "Drop publications cited fewer times than this. Needs citation counts enabled (they are by default).",
            "default": 0
          },
          "includeKeywords": {
            "title": "✅ Must contain",
            "type": "array",
            "description": "Keep a publication only if its title, abstract or keywords contain at least one of these words.",
            "items": {
              "type": "string"
            }
          },
          "excludeKeywords": {
            "title": "🚫 Must not contain",
            "type": "array",
            "description": "Drop publications whose title, abstract or keywords contain any of these words.",
            "items": {
              "type": "string"
            }
          },
          "startUrls": {
            "title": "🔗 Direct URLs",
            "type": "array",
            "description": "Scrape specific SpringerLink URLs — article pages, chapter pages, journal pages or search result pages.",
            "items": {
              "type": "object",
              "required": [
                "url"
              ],
              "properties": {
                "url": {
                  "type": "string",
                  "title": "URL of a web page",
                  "format": "uri"
                }
              }
            }
          },
          "dois": {
            "title": "🆔 DOIs",
            "type": "array",
            "description": "Scrape publications by DOI (e.g. 10.1007/s10994-025-06923-w). The right page is found automatically, whether it is an article, a chapter or a protocol.",
            "items": {
              "type": "string"
            }
          },
          "maxResults": {
            "title": "🔢 Max results",
            "minimum": 0,
            "type": "integer",
            "description": "Stop after this many publications. Set 0 for no limit.",
            "default": 100
          },
          "maxPages": {
            "title": "📑 Max pages per search",
            "minimum": 0,
            "type": "integer",
            "description": "Stop each search after this many result pages. 0 means no page limit.",
            "default": 0
          },
          "detailConcurrency": {
            "title": "⚡ Detail concurrency",
            "minimum": 1,
            "maximum": 10,
            "type": "integer",
            "description": "Full mode only: how many publication pages to read in parallel from the one warm browser session. Measured on 200 pages, 4 and 8 finish within about 10% of each other and neither tripped Springer's protection check, so 4 is the default for its slightly lower retry rate. Going much higher risks a burst being refused, which costs more than it saves.",
            "default": 4
          },
          "fetchArticlePages": {
            "title": "📖 Full mode — read SpringerLink pages (affiliations, view counts, metrics)",
            "type": "boolean",
            "description": "Additionally open each publication's page on SpringerLink for everything no open index carries: the abstract of anything published too recently to have been indexed, author affiliations, corresponding-author e-mails, the publisher's own keyword list and the view/Altmetric counters. Measured on 200 brand-new publications: abstracts went from 25% to 98%, keywords from 65% to 99%, affiliations from none to 94%. Springer runs a protection check on page reads, so this drives a real browser — give the run 2048 MB. It needs no proxy, and costs about 8× the default mode per publication (200 items in 90 seconds against 13), which is why it is off by default.",
            "default": false
          },
          "abstractMaxLength": {
            "title": "✂️ Abstract max length",
            "minimum": 0,
            "type": "integer",
            "description": "Trim abstracts to this many characters. 0 keeps them in full.",
            "default": 0
          },
          "includeReferences": {
            "title": "📎 Include reference lists",
            "type": "boolean",
            "description": "Add the full list of works each article cites. Makes records much bigger.",
            "default": false
          },
          "includeCitationCounts": {
            "title": "📊 Exact citation counts",
            "type": "boolean",
            "description": "Add exact citation counts and reference counts. Recommended — the counts shown on the page itself are rounded (\"19k\").",
            "default": true
          },
          "includeOpenAlexData": {
            "title": "🏷️ Keywords, topics & open-access status from the open index",
            "type": "boolean",
            "description": "Adds keywords, topics, open-access status and a fallback abstract from an open scholarly index. On by default: it needs no proxy, is never blocked, and covers the great majority of recent publications.",
            "default": true
          },
          "includeSpringerAbstracts": {
            "title": "📝 Abstracts from Springer's citation records (needs your own proxy)",
            "type": "boolean",
            "description": "Fetches a ~2 KB citation record for every publication that still has no abstract — no browser and no 300 KB page. Off by default because it does not work from Apify: measured, Springer's citation service answered its JavaScript protection check to every attempt — plain requests, the Apify residential proxy, sticky sequential sessions, cookies borrowed from a browser that had already cleared link.springer.com, and even a real browser pointed straight at it. Turn it on only if you supply proxy URLs for a network Springer trusts, such as a university connection. For a supported cheap abstract channel use the Springer Nature API key below instead.",
            "default": false
          },
          "springerApiKey": {
            "title": "🔑 Springer Nature API key (free) — abstracts without page reads",
            "type": "string",
            "description": "Paste a free Springer Nature API key to fill in abstracts straight from Springer's official API instead of opening publication pages. Get one in a minute at dev.springernature.com: sign up, create an application, copy the key. The free tier allows 500 requests a day and this actor batches 25 publications per request, so one key covers about 12,500 abstracts a day. Use this when you want abstracts cheaply but do not need author affiliations or view counts — those exist only on the publication page, so they still need full mode."
          },
          "discoveryChannel": {
            "title": "🧭 Search channel",
            "enum": [
              "auto",
              "crossref",
              "site-search"
            ],
            "type": "string",
            "description": "How keyword searches are answered. Automatic is unlimited and recommended. \"SpringerLink search\" mirrors the website's own ranking but is capped at 1,000 results per query and can be rate-limited.",
            "default": "auto"
          },
          "warmupTimeoutSecs": {
            "title": "⏳ Connection warm-up timeout",
            "minimum": 30,
            "maximum": 600,
            "type": "integer",
            "description": "Full mode only. How long to give the browser to get through Springer's protection check before trying a different address. Raise this on slow networks.",
            "default": 240
          },
          "browserChannel": {
            "title": "🌐 Browser",
            "enum": [
              "chrome",
              "chromium"
            ],
            "type": "string",
            "description": "Full mode only. Which browser to drive. Google Chrome is the only one that reliably gets through the protection check.",
            "default": "chrome"
          },
          "crossrefMailto": {
            "title": "📧 Contact e-mail",
            "type": "string",
            "description": "Optional. A contact address sent with metadata requests to get the faster service tier."
          },
          "compact": {
            "title": "🗜️ Compact output",
            "type": "boolean",
            "description": "Emit only the essential fields (title, authors, abstract, keywords, citations, link).",
            "default": false
          },
          "excludeEmptyFields": {
            "title": "🧹 Drop empty fields",
            "type": "boolean",
            "description": "Leave empty fields out of the records entirely.",
            "default": false
          },
          "incrementalMode": {
            "title": "🔄 Incremental monitoring",
            "type": "boolean",
            "description": "Across scheduled runs, emit only publications that are new or changed since last time. Cuts the cost of daily literature alerts by 80–95%.",
            "default": false
          },
          "stateKey": {
            "title": "🔑 Monitoring key",
            "type": "string",
            "description": "Name for this monitoring baseline. Leave empty to derive one from your search settings. Use different keys for different watch lists."
          },
          "emitUnchanged": {
            "title": "♻️ Include unchanged",
            "type": "boolean",
            "description": "Also emit publications that haven't changed since the previous run.",
            "default": false
          },
          "emitExpired": {
            "title": "🗑️ Include disappeared",
            "type": "boolean",
            "description": "Also emit publications that were in the previous run but are no longer found.",
            "default": false
          },
          "webhookUrl": {
            "title": "🔔 Webhook URL",
            "type": "string",
            "description": "POST the run results to this URL when monitoring finds something."
          },
          "telegramBotToken": {
            "title": "🤖 Telegram bot token",
            "type": "string",
            "description": "Send new publications to a Telegram chat."
          },
          "telegramChatId": {
            "title": "💬 Telegram chat id",
            "type": "string",
            "description": "Chat that receives the Telegram messages."
          },
          "discordWebhookUrl": {
            "title": "🎮 Discord webhook",
            "type": "string",
            "description": "Send new publications to a Discord channel."
          },
          "slackWebhookUrl": {
            "title": "💼 Slack webhook",
            "type": "string",
            "description": "Send new publications to a Slack channel."
          },
          "notifyOnlyChanges": {
            "title": "🔕 Only notify on changes",
            "type": "boolean",
            "description": "Stay silent when a monitoring run finds nothing new.",
            "default": true
          },
          "notificationLimit": {
            "title": "📝 Items per notification",
            "minimum": 1,
            "type": "integer",
            "description": "How many publications to list in a notification message.",
            "default": 10
          },
          "includeRunSummary": {
            "title": "📈 Include run summary",
            "type": "boolean",
            "description": "Add the run statistics to webhook payloads.",
            "default": true
          },
          "proxyConfiguration": {
            "title": "🌍 Proxy configuration",
            "type": "object",
            "description": "Proxy settings. None is the default because no mode needs one: the metadata channels are never blocked, and in full mode the real browser clears Springer's protection check straight from Apify's network — measured in about a second, with zero refusals across several hundred publication pages. If you do configure a proxy it is kept in reserve and only used once a page is actually refused, so you never pay for residential traffic speculatively. Residential is worth setting if a run reports refused pages, since the check is address-scoped.",
            "default": {
              "useApifyProxy": false
            }
          },
          "debug": {
            "title": "🐞 Debug logging",
            "type": "boolean",
            "description": "Log the status, title and first characters of any page that could not be read. Useful when a run returns fewer results than expected.",
            "default": false
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}