{
  "openapi": "3.0.1",
  "info": {
    "title": "PDF Text Extractor: OCR, Markdown, Page Checks",
    "description": "Read your PDFs and get the text plus a verdict on every page — the file's own layer, OCR for scans at no per-page charge, or a row saying why it couldn't be read. A wrong layer is flagged, not passed off as clean. Full text or Markdown, page ranges, locked files, uploads. Failed files cost nothing.",
    "version": "0.1",
    "x-build-id": "1J59vdqnft5igqczu"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/pradio~pdf-text-verifier/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-pradio-pdf-text-verifier",
        "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/pradio~pdf-text-verifier/runs": {
      "post": {
        "operationId": "runs-sync-pradio-pdf-text-verifier",
        "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/pradio~pdf-text-verifier/run-sync": {
      "post": {
        "operationId": "run-sync-pradio-pdf-text-verifier",
        "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": {
          "urls": {
            "title": "PDF links",
            "type": "array",
            "description": "the PDF links, one per line — a comma or semicolon splits a pasted line. Drive and Dropbox share links work too. If the same file comes up twice we mark it a duplicate instead of reading it again; a page that only lists more links isn't followed",
            "items": {
              "type": "string"
            }
          },
          "pdfFile": {
            "title": "One PDF file (upload or a web link)",
            "type": "string",
            "description": "pick the file in the Console's file picker, or pass its web URL through the API — a path on your machine isn't a URL. The same file twice is marked duplicate, not read again"
          },
          "inputDatasetId": {
            "title": "A saved dataset of PDF links",
            "type": "string",
            "description": "the id of a saved Apify dataset — the letters and digits under its name in Storage — shared so anyone who has it can read it; it needs the id itself, not a link. Each item is read for the link in the url column, or whichever column urlField names; a duplicate is marked, not read again"
          },
          "urlField": {
            "title": "Column each link is in",
            "type": "string",
            "description": "leave it as url unless your saved table names its link column something else; a row that is itself just a link is read as is",
            "default": "url"
          },
          "outputFormat": {
            "title": "Output format",
            "enum": [
              "text",
              "markdown",
              "both"
            ],
            "type": "string",
            "description": "what each row's whole-document columns carry: the text (default), Markdown with the layout's headings and lists, or both; per-page results carry the same text either way",
            "default": "text"
          },
          "keepRows": {
            "title": "Which rows to keep",
            "enum": [
              "all",
              "answered",
              "flagged",
              "missed"
            ],
            "type": "string",
            "description": "which results a run keeps: everything, only files that read, only flagged ones (suspect or unreadable), or only failures. A failure comes back as a free row naming it, and an entry your filter drops still shows up named — never billed",
            "default": "all"
          },
          "cleanText": {
            "title": "Clean up the text",
            "type": "boolean",
            "description": "drop the headers and footers repeated on 30% or more of pages, page-number lines, space runs and split hyphens; the row lists what it removed, and per-page text stays as read",
            "default": false
          },
          "extractTables": {
            "title": "Extract tables",
            "type": "boolean",
            "description": "rebuild the tables each page's layout carries — every table comes back with its page, rows of cells and a note on whether the rebuild is certain. A page read by OCR has no layout to work from; your text and page results stay as they are",
            "default": false
          },
          "extractImages": {
            "title": "Extract embedded images",
            "type": "boolean",
            "description": "save each embedded image to the run's key-value store as a PNG, with its page, size and link listed in the row's images field; at most 200 a document",
            "default": false
          },
          "skipEmptyPages": {
            "title": "Skip blank pages",
            "type": "boolean",
            "description": "leave a page carrying nothing — no text layer, no OCR words — out of the page results and the counts. A page the OCR cap stopped stays listed: never read isn't blank",
            "default": false
          },
          "pageRange": {
            "title": "Page range",
            "type": "string",
            "description": "which pages to read in each file: 1-5 or 2-5,8, 10- to the end, -3 for the last three; empty reads everything. A typo names the entry in the results and bills nothing"
          },
          "mustContain": {
            "title": "Must contain phrases",
            "type": "array",
            "description": "up to 20 phrases every file must carry, matched as written ignoring case; each row says found, which pages and the first matching line. More than 20, or an entry that isn't text, is refused",
            "items": {
              "type": "string"
            }
          },
          "pdfPassword": {
            "title": "PDF password",
            "type": "string",
            "description": "the password that opens your protected PDFs — an entry's own password wins. A file that needs one and gets none comes back named and free"
          },
          "ocrLanguage": {
            "title": "Language of scanned pages",
            "type": "string",
            "description": "the language your scanned pages are written in, English by default; join codes with + (eng+deu) for a document in two. A code the engine doesn't ship is refused before anything reads; OCR runs where a page has no text layer, and on every page when the page check is on",
            "default": "eng"
          },
          "verifyPages": {
            "title": "Check each page's text against a scan (charged per page checked)",
            "type": "boolean",
            "description": "render every page and re-read the picture by OCR, flagging a born-digital text layer that disagrees. A scan's own transcript cannot be judged this way either: the fresh OCR is a second transcript, not a witness. It comes back verify_inconclusive, like a page whose read was too weak to judge. Inconclusive pages keep their text and bill nothing. Billed $0.008 per page the check verifies",
            "default": false
          },
          "pdfTextMode": {
            "title": "Where a page's text comes from (leave Automatic)",
            "enum": [
              "auto",
              "text",
              "ocr"
            ],
            "type": "string",
            "description": "auto reads the embedded layer and OCRs a page that has no usable one; text never runs OCR, so a layerless page answers no_layer with nothing; ocr reads every page by OCR and ships that text whatever the layer holds. With the page check on, text is refused",
            "default": "auto"
          },
          "autoRotate": {
            "title": "Auto-rotate scans",
            "type": "boolean",
            "description": "retry a badly read OCR page turned 90, 180 and 270 degrees and keep the best read, for sideways scans; turned pages are marked in the page results",
            "default": true
          },
          "dpi": {
            "title": "OCR image resolution (DPI)",
            "minimum": 72,
            "maximum": 400,
            "type": "integer",
            "description": "the resolution pages are rendered at for OCR, 72 to 400; empty applies 144 — the setting the stated rates were measured at"
          },
          "preprocessMode": {
            "title": "Clean up scans before OCR (leave None)",
            "enum": [
              "none",
              "grayscale",
              "contrast",
              "binarise"
            ],
            "type": "string",
            "description": "a cleanup the rendered page gets before OCR reads it: grayscale drops the colour, contrast stretches light and dark, binarise makes every pixel black or white. For faded or noisy scans; none leaves the page as rendered",
            "default": "none"
          },
          "minOcrConfidence": {
            "title": "Minimum OCR confidence",
            "minimum": 0,
            "maximum": 100,
            "type": "integer",
            "description": "leave empty to flag nothing; 0 to 100 flags an OCR-read page whose confidence falls under it. The words stay, marked in the page results and the low-confidence list"
          },
          "segmentationMode": {
            "title": "Page layout for scanned pages (leave Automatic)",
            "enum": [
              "auto",
              "auto_osd",
              "single_column",
              "single_block",
              "single_line",
              "single_word",
              "sparse_text",
              "sparse_text_osd",
              "raw_line"
            ],
            "type": "string",
            "description": "leave Automatic unless a scan reads wrong: tells OCR whether the page is one column, a block, a line, a word or scattered text; the orientation choices also detect rotation",
            "default": "auto"
          },
          "includeWords": {
            "title": "List each word OCR found",
            "type": "boolean",
            "description": "each OCR-read page lists every word it found with its confidence and position, for checking a scan word by word; a very large row may shorten the list and says so",
            "default": false
          },
          "chunkSize": {
            "title": "Chunk size (characters)",
            "minimum": 200,
            "maximum": 20000,
            "type": "integer",
            "description": "split each document's text into chunks of about this size, each naming its pages; cuts fall at a paragraph, line or space. Empty for none; 200 to 20000"
          },
          "chunkOverlap": {
            "title": "Characters repeated between chunks",
            "minimum": 0,
            "maximum": 10000,
            "type": "integer",
            "description": "characters repeated from a chunk's end into the next so a sentence cut at an edge stays whole; only used with Chunk size, at most half of it",
            "default": 200
          },
          "maxItems": {
            "title": "Maximum items",
            "minimum": 1,
            "maximum": 100000,
            "type": "integer",
            "description": "the most rows one run returns, free rows counting too. Entries past it are named on a free cap_reached row — or on the run's last row when the cap is 1",
            "default": 100
          },
          "maxPagesPerDocument": {
            "title": "Maximum pages per document",
            "minimum": 1,
            "maximum": 50000,
            "type": "integer",
            "description": "the most pages one file contributes; a longer one is read to here and marked pages_truncated. The cap also bounds a long file's extra-page charges",
            "default": 300
          },
          "ocrMaxPagesPerDocument": {
            "title": "Max pages to OCR per document",
            "minimum": 1,
            "maximum": 50000,
            "type": "integer",
            "description": "the most pages of one file OCR may read, never more than Maximum pages per document; leave empty for no limit. A page past the cap is marked, never skipped"
          },
          "maxConcurrency": {
            "title": "Documents read at once",
            "minimum": 1,
            "maximum": 5,
            "type": "integer",
            "description": "how many files read at once, up to 5 (empty means 5). Rows keep your order and OCR still reads a page at a time; a run that renders (the page check, an OCR mode, image extraction) reads fewer at once, held by the memory the run was given — on a small allocation use Low-memory mode",
            "default": 5
          },
          "lowMemory": {
            "title": "Low-memory mode",
            "type": "boolean",
            "description": "read one file at a time so the buffers only ever hold one: slower, but the biggest allowed files fit 1024 MB. Ignores Documents read at once",
            "default": false
          },
          "requestTimeoutSecs": {
            "title": "Fetch timeout per document (seconds)",
            "minimum": 5,
            "maximum": 600,
            "type": "integer",
            "description": "seconds one file's download may take before its row answers timeout, 5 to 600; empty keeps 60. A host asking for a short wait is waited out once"
          },
          "maxDocumentSizeMb": {
            "title": "Maximum document size (MB)",
            "minimum": 1,
            "maximum": 250,
            "type": "integer",
            "description": "a file over this many megabytes isn't fetched — you get a free too_large row naming its size; empty keeps 80"
          },
          "onlyNew": {
            "title": "Only new or changed documents",
            "type": "boolean",
            "description": "for lists you run again: skip a file an earlier run already returned when the file and your options match. Skipped entries are free and each named on its row; matching is by the file's fingerprint only",
            "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
                  },
                  "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}