Skip to main content
POST
/
extract
Extract rich content from a document
curl --request POST \
  --url https://api.runpulse.com/extract \
  --header 'Content-Type: multipart/form-data' \
  --header 'x-api-key: <api-key>' \
  --form file='@example-file' \
  --form 'fileUrl=<string>' \
  --form detectSelections=true \
  --form extractionConfigId=3c90c3cc-0d44-4b50-8888-8dd25736052a \
  --form 'pages=<string>' \
  --form 'figureProcessing={
  "description": false,
  "showImages": false
}' \
  --form 'extensions={
  "footnoteReferences": false,
  "chunking": {
    "chunkTypes": [],
    "chunkSize": 2
  },
  "altOutputs": {
    "wlbb": false,
    "returnHtml": false,
    "returnXml": false
  }
}' \
  --form 'spreadsheet={
  "includeHiddenRows": false,
  "includeHiddenCols": false,
  "includeHiddenSheets": false,
  "useRawValues": false,
  "onlyDataRows": false,
  "onlyDataCols": false
}' \
  --form 'storage={
  "enabled": true,
  "folderName": "<string>",
  "folderId": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}' \
  --form async=false \
  --form 'structuredOutput={
  "schema": {},
  "schemaPrompt": "<string>",
  "effort": false
}' \
  --form 'schema={}' \
  --form 'schemaPrompt=<string>' \
  --form 'customPrompt=<string>' \
  --form 'chunking=<string>' \
  --form chunkSize=2 \
  --form extractFigure=false \
  --form figureDescription=false \
  --form showImages=false \
  --form returnHtml=false \
  --form thinking=false
import requests

url = "https://api.runpulse.com/extract"

files = { "file": ("example-file", open("example-file", "rb")) }
payload = {
"fileUrl": "<string>",
"detectSelections": "true",
"extractionConfigId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"pages": "<string>",
"figureProcessing": "{
\"description\": false,
\"showImages\": false
}",
"extensions": "{
\"footnoteReferences\": false,
\"chunking\": {
\"chunkTypes\": [],
\"chunkSize\": 2
},
\"altOutputs\": {
\"wlbb\": false,
\"returnHtml\": false,
\"returnXml\": false
}
}",
"spreadsheet": "{
\"includeHiddenRows\": false,
\"includeHiddenCols\": false,
\"includeHiddenSheets\": false,
\"useRawValues\": false,
\"onlyDataRows\": false,
\"onlyDataCols\": false
}",
"storage": "{
\"enabled\": true,
\"folderName\": \"<string>\",
\"folderId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"
}",
"async": "false",
"structuredOutput": "{
\"schema\": {},
\"schemaPrompt\": \"<string>\",
\"effort\": false
}",
"schema": "{}",
"schemaPrompt": "<string>",
"customPrompt": "<string>",
"chunking": "<string>",
"chunkSize": "2",
"extractFigure": "false",
"figureDescription": "false",
"showImages": "false",
"returnHtml": "false",
"thinking": "false"
}
headers = {"x-api-key": "<api-key>"}

response = requests.post(url, data=payload, files=files, headers=headers)

print(response.text)
const form = new FormData();
form.append('file', '<string>');
form.append('fileUrl', '<string>');
form.append('detectSelections', 'true');
form.append('extractionConfigId', '3c90c3cc-0d44-4b50-8888-8dd25736052a');
form.append('pages', '<string>');
form.append('figureProcessing', '{
"description": false,
"showImages": false
}');
form.append('extensions', '{
"footnoteReferences": false,
"chunking": {
"chunkTypes": [],
"chunkSize": 2
},
"altOutputs": {
"wlbb": false,
"returnHtml": false,
"returnXml": false
}
}');
form.append('spreadsheet', '{
"includeHiddenRows": false,
"includeHiddenCols": false,
"includeHiddenSheets": false,
"useRawValues": false,
"onlyDataRows": false,
"onlyDataCols": false
}');
form.append('storage', '{
"enabled": true,
"folderName": "<string>",
"folderId": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}');
form.append('async', 'false');
form.append('structuredOutput', '{
"schema": {},
"schemaPrompt": "<string>",
"effort": false
}');
form.append('schema', '{}');
form.append('schemaPrompt', '<string>');
form.append('customPrompt', '<string>');
form.append('chunking', '<string>');
form.append('chunkSize', '2');
form.append('extractFigure', 'false');
form.append('figureDescription', 'false');
form.append('showImages', 'false');
form.append('returnHtml', 'false');
form.append('thinking', 'false');

const options = {method: 'POST', headers: {'x-api-key': '<api-key>'}};

options.body = form;

fetch('https://api.runpulse.com/extract', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));
<?php

$curl = curl_init();

curl_setopt_array($curl, [
CURLOPT_URL => "https://api.runpulse.com/extract",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"fileUrl\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"detectSelections\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"extractionConfigId\"\r\n\r\n3c90c3cc-0d44-4b50-8888-8dd25736052a\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"pages\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"figureProcessing\"\r\n\r\n{\r\n \"description\": false,\r\n \"showImages\": false\r\n}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"extensions\"\r\n\r\n{\r\n \"footnoteReferences\": false,\r\n \"chunking\": {\r\n \"chunkTypes\": [],\r\n \"chunkSize\": 2\r\n },\r\n \"altOutputs\": {\r\n \"wlbb\": false,\r\n \"returnHtml\": false,\r\n \"returnXml\": false\r\n }\r\n}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"spreadsheet\"\r\n\r\n{\r\n \"includeHiddenRows\": false,\r\n \"includeHiddenCols\": false,\r\n \"includeHiddenSheets\": false,\r\n \"useRawValues\": false,\r\n \"onlyDataRows\": false,\r\n \"onlyDataCols\": false\r\n}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"storage\"\r\n\r\n{\r\n \"enabled\": true,\r\n \"folderName\": \"<string>\",\r\n \"folderId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\r\n}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"async\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"structuredOutput\"\r\n\r\n{\r\n \"schema\": {},\r\n \"schemaPrompt\": \"<string>\",\r\n \"effort\": false\r\n}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"schema\"\r\n\r\n{}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"schemaPrompt\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"customPrompt\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"chunking\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"chunkSize\"\r\n\r\n2\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"extractFigure\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"figureDescription\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"showImages\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"returnHtml\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"thinking\"\r\n\r\nfalse\r\n-----011000010111000001101001--",
CURLOPT_HTTPHEADER => [
"Content-Type: multipart/form-data",
"x-api-key: <api-key>"
],
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
package main

import (
"fmt"
"strings"
"net/http"
"io"
)

func main() {

url := "https://api.runpulse.com/extract"

payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"fileUrl\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"detectSelections\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"extractionConfigId\"\r\n\r\n3c90c3cc-0d44-4b50-8888-8dd25736052a\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"pages\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"figureProcessing\"\r\n\r\n{\r\n \"description\": false,\r\n \"showImages\": false\r\n}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"extensions\"\r\n\r\n{\r\n \"footnoteReferences\": false,\r\n \"chunking\": {\r\n \"chunkTypes\": [],\r\n \"chunkSize\": 2\r\n },\r\n \"altOutputs\": {\r\n \"wlbb\": false,\r\n \"returnHtml\": false,\r\n \"returnXml\": false\r\n }\r\n}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"spreadsheet\"\r\n\r\n{\r\n \"includeHiddenRows\": false,\r\n \"includeHiddenCols\": false,\r\n \"includeHiddenSheets\": false,\r\n \"useRawValues\": false,\r\n \"onlyDataRows\": false,\r\n \"onlyDataCols\": false\r\n}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"storage\"\r\n\r\n{\r\n \"enabled\": true,\r\n \"folderName\": \"<string>\",\r\n \"folderId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\r\n}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"async\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"structuredOutput\"\r\n\r\n{\r\n \"schema\": {},\r\n \"schemaPrompt\": \"<string>\",\r\n \"effort\": false\r\n}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"schema\"\r\n\r\n{}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"schemaPrompt\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"customPrompt\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"chunking\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"chunkSize\"\r\n\r\n2\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"extractFigure\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"figureDescription\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"showImages\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"returnHtml\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"thinking\"\r\n\r\nfalse\r\n-----011000010111000001101001--")

req, _ := http.NewRequest("POST", url, payload)

req.Header.Add("x-api-key", "<api-key>")

res, _ := http.DefaultClient.Do(req)

defer res.Body.Close()
body, _ := io.ReadAll(res.Body)

fmt.Println(string(body))

}
HttpResponse<String> response = Unirest.post("https://api.runpulse.com/extract")
.header("x-api-key", "<api-key>")
.body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"fileUrl\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"detectSelections\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"extractionConfigId\"\r\n\r\n3c90c3cc-0d44-4b50-8888-8dd25736052a\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"pages\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"figureProcessing\"\r\n\r\n{\r\n \"description\": false,\r\n \"showImages\": false\r\n}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"extensions\"\r\n\r\n{\r\n \"footnoteReferences\": false,\r\n \"chunking\": {\r\n \"chunkTypes\": [],\r\n \"chunkSize\": 2\r\n },\r\n \"altOutputs\": {\r\n \"wlbb\": false,\r\n \"returnHtml\": false,\r\n \"returnXml\": false\r\n }\r\n}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"spreadsheet\"\r\n\r\n{\r\n \"includeHiddenRows\": false,\r\n \"includeHiddenCols\": false,\r\n \"includeHiddenSheets\": false,\r\n \"useRawValues\": false,\r\n \"onlyDataRows\": false,\r\n \"onlyDataCols\": false\r\n}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"storage\"\r\n\r\n{\r\n \"enabled\": true,\r\n \"folderName\": \"<string>\",\r\n \"folderId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\r\n}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"async\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"structuredOutput\"\r\n\r\n{\r\n \"schema\": {},\r\n \"schemaPrompt\": \"<string>\",\r\n \"effort\": false\r\n}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"schema\"\r\n\r\n{}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"schemaPrompt\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"customPrompt\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"chunking\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"chunkSize\"\r\n\r\n2\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"extractFigure\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"figureDescription\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"showImages\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"returnHtml\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"thinking\"\r\n\r\nfalse\r\n-----011000010111000001101001--")
.asString();
require 'uri'
require 'net/http'

url = URI("https://api.runpulse.com/extract")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<api-key>'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"fileUrl\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"detectSelections\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"extractionConfigId\"\r\n\r\n3c90c3cc-0d44-4b50-8888-8dd25736052a\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"pages\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"figureProcessing\"\r\n\r\n{\r\n \"description\": false,\r\n \"showImages\": false\r\n}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"extensions\"\r\n\r\n{\r\n \"footnoteReferences\": false,\r\n \"chunking\": {\r\n \"chunkTypes\": [],\r\n \"chunkSize\": 2\r\n },\r\n \"altOutputs\": {\r\n \"wlbb\": false,\r\n \"returnHtml\": false,\r\n \"returnXml\": false\r\n }\r\n}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"spreadsheet\"\r\n\r\n{\r\n \"includeHiddenRows\": false,\r\n \"includeHiddenCols\": false,\r\n \"includeHiddenSheets\": false,\r\n \"useRawValues\": false,\r\n \"onlyDataRows\": false,\r\n \"onlyDataCols\": false\r\n}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"storage\"\r\n\r\n{\r\n \"enabled\": true,\r\n \"folderName\": \"<string>\",\r\n \"folderId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\r\n}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"async\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"structuredOutput\"\r\n\r\n{\r\n \"schema\": {},\r\n \"schemaPrompt\": \"<string>\",\r\n \"effort\": false\r\n}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"schema\"\r\n\r\n{}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"schemaPrompt\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"customPrompt\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"chunking\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"chunkSize\"\r\n\r\n2\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"extractFigure\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"figureDescription\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"showImages\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"returnHtml\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"thinking\"\r\n\r\nfalse\r\n-----011000010111000001101001--"

response = http.request(request)
puts response.read_body
{
  "markdown": "<string>",
  "extensions": {
    "chunking": {
      "semantic": [
        "<string>"
      ],
      "header": [
        "<string>"
      ],
      "page": [
        "<string>"
      ],
      "recursive": [
        "<string>"
      ]
    },
    "footnoteReferences": [
      {
        "symbol": "<string>",
        "footnoteTextId": "<string>",
        "referenceTextIds": [
          "<string>"
        ]
      }
    ],
    "altOutputs": {
      "wlbb": {
        "words": [
          {
            "id": "<string>",
            "text": "<string>",
            "page_number": 2,
            "bounding_box": [
              123
            ],
            "average_word_confidence": 123
          }
        ],
        "error": "<string>"
      },
      "html": "<string>",
      "xml": "<string>"
    }
  },
  "bounding_boxes": {
    "Images": [
      {
        "id": "<string>",
        "content": "<string>",
        "page_number": 2,
        "bounding_box": [
          123
        ],
        "image_url": "<string>",
        "description": "<string>",
        "classification": {
          "confidence": 0.5,
          "model": "<string>",
          "error": "<string>"
        },
        "sheet_name": "<string>",
        "sheet_index": 123,
        "workbook_sheet_index": 123,
        "excel_range": "<string>",
        "chart_type": "<string>",
        "chart_title": "<string>",
        "source_ranges": [
          "<string>"
        ],
        "render_error": "<string>",
        "description_error": "<string>"
      }
    ],
    "Tables": [
      {
        "table_info": {
          "id": "<string>",
          "dimensions": [
            123
          ],
          "excel_range": "<string>",
          "sheet_name": "<string>",
          "sheet_index": 123,
          "workbook_sheet_index": 123,
          "section_index": 123,
          "section_type": "<string>",
          "section_name": "<string>",
          "table_name": "<string>",
          "layout_type": "<string>",
          "is_chart": true,
          "chart_type": "<string>",
          "chart_title": "<string>",
          "source_ranges": [
            "<string>"
          ],
          "location": {}
        },
        "cell_data": [
          {}
        ]
      }
    ],
    "Text": [
      {
        "id": "<string>",
        "content": "<string>",
        "page_number": 2,
        "bounding_box": [
          123
        ],
        "excel_range": "<string>",
        "sheet_name": "<string>",
        "sheet_index": 123,
        "workbook_sheet_index": 123,
        "selected": true
      }
    ],
    "Title": [
      {
        "id": "<string>",
        "content": "<string>",
        "page_number": 2,
        "bounding_box": [
          123
        ],
        "excel_range": "<string>",
        "sheet_name": "<string>",
        "sheet_index": 123,
        "workbook_sheet_index": 123,
        "selected": true
      }
    ],
    "Footer": [
      {
        "id": "<string>",
        "content": "<string>",
        "page_number": 2,
        "bounding_box": [
          123
        ],
        "excel_range": "<string>",
        "sheet_name": "<string>",
        "sheet_index": 123,
        "workbook_sheet_index": 123,
        "selected": true
      }
    ],
    "markdown_with_ids": "<string>"
  },
  "extraction_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
  "extraction_url": "<string>",
  "page_count": 2,
  "plan_info": {
    "tier": "<string>",
    "total_credits_used": 123,
    "pages_used": 1,
    "note": "<string>"
  },
  "warnings": [
    "<string>"
  ],
  "credits_used": 123,
  "html": "<string>",
  "chunks": {
    "semantic": [
      "<string>"
    ],
    "header": [
      "<string>"
    ],
    "page": [
      "<string>"
    ],
    "recursive": [
      "<string>"
    ]
  },
  "structured_output": {
    "values": {},
    "citations": {}
  },
  "input_schema": {},
  "schema_error": "<string>",
  "content": "<string>",
  "job_id": "<string>",
  "metadata": {}
}
{
"job_id": "<string>",
"message": "<string>",
"queuedAt": "2023-11-07T05:31:56Z",
"credits_used": 123
}

Overview

Pipeline Step 1 — Extract is always the first step. After extraction, you can optionally split the document into topics, apply schema extraction to get structured data, or use tables for span-aware table extraction.
Extract content from documents. Returns markdown or HTML formatted content with optional structured data extraction. For large results (typically documents over 70 pages, or any response above 5 MB), the API returns a one-time download link at https://api.runpulse.com/large_results/{job_id} instead of inlining the payload. See Large Document Response below.
For large documents or batch processing workflows, set async: true to process asynchronously and poll for results via GET /job/jobId.
To process many files at once, use Batch Extract. It accepts an S3 prefix, local directory, or list of URLs and runs /extract on each file in parallel.

Async Mode

Set async: true to return immediately with a job ID for polling:
{
  "file_url": "https://example.com/document.pdf",
  "async": true
}
Async Response (200):
{
  "job_id": "abc123-def456",
  "status": "pending",
  "message": "Document processing started"
}
Use GET /job/{job_id} to poll for completion.

Request

Document Source

Provide the document using one of these methods:
FieldTypeDescription
filebinaryDocument file to upload directly (multipart/form-data).
file_urlstringPublic or pre-signed URL that Pulse will download and extract.

Extraction Options

FieldTypeDefaultDescription
modelstring (enum)defaultExtraction model to use. One of default or pulse-ultra-2. pulse-ultra-2 uses Pulse’s vision-language model with built-in refinement, figure/chart extraction, and word-level bounding boxes.
pagesstring-Page range filter (1-indexed). Supports segments like 1-2 or mixed ranges like 1-2,5. Page 1 is the first page.
figure_processingobject-Settings that control how figures in the document are processed. These affect the markdown output directly and do not produce additional output fields. See Figure Processing.
extensionsobject-Settings that enable additional processing or alternate output formats. Each enabled extension produces a corresponding result under response.extensions.*. See Extensions.
spreadsheetobject-Settings for Excel/spreadsheet extraction. Controls handling of hidden rows, columns, sheets, and the automatic trimming of empty trailing rows/columns past the last data-bearing cell. Applies to .xlsx, .xlsm, and .xls files. See Spreadsheet Options.
storageobject-Options for persisting extraction artifacts. See Storage Options.
asyncbooleanfalseIf true, returns immediately with a job_id for polling via GET /job/{jobId}.
structured_outputobject-⚠️ Deprecated — Use the /schema endpoint after extraction instead. Still works for backward compatibility.

Figure Processing

Settings under figure_processing control how figures (images, charts, diagrams) and embedded visuals are processed. Applies to both PDFs/images (figures detected from layout) and spreadsheets (charts and embedded images read directly from the workbook). Affects the markdown output and the bounding_boxes.Images[] array.
FieldTypeDefaultDescription
figure_processing.descriptionbooleanfalseGenerate descriptive captions for extracted visuals. Captions appear under bounding_boxes.Images[].description and inline in the markdown output. Applies to both detected charts and non-chart images.
figure_processing.show_imagesbooleanfalseReturn image URLs for extracted visuals. URLs appear under bounding_boxes.Images[].image_url and resolve to a Pulse-hosted PNG/JPEG served from GET /results/{jobId}/images/{filename}. Applies to both detected charts and non-chart images.
For spreadsheets specifically, show_images: true collects every embedded chart and image in the workbook and emits one entry per visual under bounding_boxes.Images, with chart-specific fields like chart_type, chart_title, and source_ranges populated. See Bounding Boxes for the full field list.

Spreadsheet Options

Settings under spreadsheet control how Excel workbooks (.xlsx, .xlsm, .xls) are processed. By default, hidden rows, columns, and sheets are excluded from extraction output, and cell values are rendered the way Excel displays them. Phantom-cell trimming is opt-in.
FieldTypeDefaultDescription
spreadsheet.include_hidden_rowsbooleanfalseInclude rows that are hidden in the Excel workbook.
spreadsheet.include_hidden_colsbooleanfalseInclude columns that are hidden in the Excel workbook.
spreadsheet.include_hidden_sheetsbooleanfalseInclude sheets that are hidden in the Excel workbook.
spreadsheet.use_raw_valuesbooleanfalseEmit the underlying numeric value for number cells instead of the Excel display-formatted text — e.g. 1201.67 rather than $1,202 when the cell uses a rounded currency format. Useful when downstream processing needs exact amounts (cent-level precision) rather than what the workbook shows visually. Percent-formatted cells and dates keep their display rendering. Does not apply to legacy .xls files.
spreadsheet.only_data_rowsbooleanfalseWhen true, trim trailing empty rows past the last cell carrying a value or formula. See Phantom-cell trimming below.
spreadsheet.only_data_colsbooleanfalseWhen true, trim trailing empty columns past the last cell carrying a value or formula. Same rationale as only_data_rows.
These settings accept both camelCase (includeHiddenRows, onlyDataRows) and snake_case (include_hidden_rows, only_data_rows) formats.

Phantom-cell trimming (only_data_rows / only_data_cols)

Excel files exported from claims systems, ERPs, and other automated pipelines routinely declare a “used range” that extends hundreds of thousands of rows past where the data actually ends. A typical case: a 57 MB workbook with only ~500 rows of real data, where the other ~1,000,000 rows are empty cells that exist only because they were once selected and styled. These phantom cells inflate file size by orders of magnitude and can exhaust parser memory on the extraction pipeline. Set only_data_rows: true and only_data_cols: true to have Pulse scan each sheet once before parsing, find the largest row and column containing a value or formula, and ignore everything beyond that extent. Surviving cells keep their original A1 coordinates (e.g., a value at B7 in the source is still B7 in the output), so any citation or bounding box that references a specific cell remains stable. The trim only kicks in on large sheets (≥5 MB of XML per sheet), so small, well-formed workbooks pay no overhead either way. Both flags default to false.

Pulse Ultra 2 Options

These options are available only when model: pulse-ultra-2 is set. Passing any of them with the default model returns a 400 error listing the offending fields.
FieldTypeDefaultDescription
refinebooleanfalseRun a full-page OCR and formatting correction pass after extraction. Improves accuracy on dense layouts, numerical values, and table structure. Adds ~1–2s per page. Overridden by refine_options if both are provided.
refine_optionsobject-Granular refinement targets. Takes precedence over the boolean refine flag. See below.
refine_options.tablesbooleanfalseFix table cell values, structure, and headers against the source image.
refine_options.textbooleanfalseFix OCR errors, missing or extra content, and numerical accuracy (tables untouched).
refine_options.formattingbooleanfalseAdd strikethrough, italic, bold, super/subscript, and LaTeX formatting (tables untouched).
extract_figurebooleanfalseConvert charts and data visualizations into HTML <table> blocks, wrapped in <figure-table> tags. Useful for financial decks, dashboards, and scientific charts.
figure_descriptionbooleanfalseGenerate a 1–2 paragraph natural-language description of each picture, wrapped in <figure-description> tags. Combines well with extract_figure.
detect_selectionsbooleantrueDetect selected and unselected marks with a specialized selection-mark model. Improves accuracy on forms, checkboxes, radio buttons, handwritten checkmarks, X marks, and similar controls. Enabled by default for pulse-ultra-2; set to false to skip this pass.
additional_promptstring""Extra context injected into the extraction prompt. Use to steer extraction toward a specific domain or attention focus. Max 4000 characters.
custom_image_promptstring""Extra context appended to the prompt used by figure_description and extract_figure. Tunes image and chart interpretation. Max 2000 characters.
custom_refine_promptstring""Extra context appended to the refinement prompt. Only applies when refine: true or refine_options is set. Max 2000 characters.

Selection mark detection

Use detect_selections: true with model: pulse-ultra-2 when a document contains forms, checkboxes, radio buttons, handwritten selection marks, or other marked-choice controls. Pulse runs a specialized detection pass for these marks so selected/unselected states are less likely to be missed or confused with nearby text, boxes, or handwriting. When available, the detected state is returned on the relevant bounding-box items as selected.

Markdown output additions

When extract_figure or figure_description is enabled, figures in response.markdown include additional tags:
<figure data-page="1">
  <figure-table>...HTML table for the chart...</figure-table>
  <figure-description>...1–2 paragraph description...</figure-description>
</figure>
When refine (or refine_options) is set, markdown content is post-processed page-by-page; output is cleaner but typically grows ~1.5–3x in size for dense documents. No new tags are introduced.

Extensions

Settings under extensions enable additional processing passes or alternate output formats. Each enabled extension produces a corresponding output field under response.extensions.*. For example, enabling extensions.chunking produces response.extensions.chunking, and enabling extensions.alt_outputs.return_html produces response.extensions.alt_outputs.html.
FieldTypeDefaultDescription
extensions.footnote_referencesbooleanfalseLink footnote markers to their corresponding footnote text.
extensions.chunkingobject-Chunking configuration. See below.
extensions.chunking.chunk_typesstring[]-List of chunking strategies: semantic, header, page, recursive.
extensions.chunking.chunk_sizeinteger-Maximum characters per chunk.
extensions.alt_outputsobject-Alternate output formats. See below.
extensions.alt_outputs.wlbbbooleanfalseEnable word-level bounding boxes (PDF only). Results in response.extensions.alt_outputs.wlbb.
extensions.alt_outputs.return_htmlbooleanfalseInclude HTML representation. response.markdown is still present; HTML is at response.extensions.alt_outputs.html.
extensions.alt_outputs.return_xmlbooleanfalseInclude XML representation (work in progress).

pulse-ultra-2 Rate Limits

Requests made with model: pulse-ultra-2 are subject to dedicated rate limits, separate from standard extraction:
LimitValue
Per minute5 extractions
Per hour20 extractions
File size50 MB
Concurrent2 per API key
The concurrent limit is the one that most commonly applies in practice — long-running extractions held open while new requests arrive will trip it first.

Storage Options

Control whether extractions are saved to your extraction library:
FieldTypeDefaultDescription
storage.enabledbooleantrueWhether to persist extraction artifacts. Set to false for temporary extractions.
storage.folder_namestring-Target folder name to save the extraction to. Creates the folder if it doesn’t exist.
storage.folder_idstring (uuid)-Target folder ID to save the extraction to. Takes precedence over folder_name.

Deprecated Fields

The following input fields are deprecated and will be removed in a future version. They are still accepted for backward compatibility.
FieldReplacement
show_imagesUse figure_processing.show_images
chunkingUse extensions.chunking.chunk_types (array instead of comma-separated string)
chunk_sizeUse extensions.chunking.chunk_size
return_htmlUse extensions.alt_outputs.return_html
structured_outputUse /schema endpoint after extraction. Pass extraction_id + schema_config. Accepts schema, schema_prompt, and effort.
schemaUse /schema endpoint after extraction
schema_promptUse /schema endpoint with schema_config.schema_prompt
custom_promptNo replacement
thinkingNo replacement
When legacy input fields are used, the API returns a deprecation warning in the warnings array directing you to the updated field names. See the latest documentation for details.

Response

The response structure varies based on document size to optimize for different use cases.

Standard Response (Under 70 Pages)

For documents under 70 pages, results are returned directly in the response body:
{
  "markdown": "# Document Title\n\nExtracted content...",
  "page_count": 15,
  "extraction_id": "abc123-def456-ghi789",
  "extraction_url": "https://platform.runpulse.com/dashboard/extractions/abc123",
  "credits_used": 1.0,
  "plan_info": {
    "tier": "growth",
    "pages_used": 15,
    "total_credits_used": 49.5,
    "note": "Pulse Ultra"
  },
  "bounding_boxes": {
    "Title": [],
    "Text": [],
    "Tables": [],
    "Images": [
      {
        "id": "excel_image_1_1",
        "visual_type": "chart",
        "image_url": "https://api.runpulse.com/results/abc123-def456-ghi789/images/excel_image_1_1.png",
        "chart_type": "BarChart",
        "chart_title": "Revenue",
        "excel_range": "D2",
        "sheet_name": "Charts"
      }
    ],
    "markdown_with_ids": "<p data-bb-text-id=\"txt-1\">..."
  },
  "extensions": {
    "chunking": {
      "semantic": ["chunk 1...", "chunk 2..."],
      "header": ["section 1...", "section 2..."]
    },
    "altOutputs": {
      "html": "<html>...</html>"
    }
  },
  "warnings": []
}

Response Fields

FieldTypeDescription
markdownstringClean markdown content extracted from the document. Always present.
page_countintegerTotal number of pages processed.
extraction_idstring (uuid)Persisted extraction ID. Present when storage is enabled (default). Use with /split and /schema.
extraction_urlstringURL to view the extraction in the Pulse Platform. Present when storage is enabled.
credits_usednumberCredits consumed by this request. Only present when the org has the credit billing system enabled.
plan_infoobjectBilling tier and cumulative usage information for the calling org, including this request. Includes tier, total_credits_used (primary billing metric), pages_used (legacy), and an optional note.
bounding_boxesobjectTyped bounding-box data — Images, Tables, Text, Title, Footer, plus markdown_with_ids. See Bounding Boxes for the full field list including the chart/image fields under Images.
extensionsobjectOutput from enabled extensions. Only keys for enabled extensions are present. See below.
extensions.chunkingobjectChunk results by strategy (when extensions.chunking is enabled).
extensions.footnoteReferencesarrayList of detected footnotes with their in-text references (when extensions.footnote_references is enabled). See Footnote References below.
extensions.altOutputs.wlbbobjectWord-level bounding boxes (when extensions.alt_outputs.wlbb is enabled).
extensions.altOutputs.htmlstringHTML representation (when extensions.alt_outputs.return_html is enabled).
extensions.altOutputs.xmlstringXML representation (when extensions.alt_outputs.return_xml is enabled, WIP).
warningsarrayNon-fatal warnings generated during extraction, including deprecation notices for legacy input usage.

Deprecated Response Fields

FieldReplacementDescription
htmlextensions.altOutputs.htmlPresent when legacy return_html input is used.
chunksextensions.chunkingPresent when legacy chunking input is used.
plan-infoplan_infoPresent when only legacy inputs are used.
structured_outputUse /schemaPresent when deprecated structured_output input was used.
input_schemaUse /schemaEcho of the applied schema (deprecated path only).
schema_errorUse /schemaError message if schema processing failed (deprecated path only).

Large Document Response (70+ Pages)

For documents with 70 or more pages — or any response payload above the 5 MB inline threshold — the API returns a one-time download link to /large_results/{job_id} instead of inlining the payload. This prevents timeout issues and keeps the immediate response small.
{
  "is_url": true,
  "url": "https://api.runpulse.com/large_results/abc123-def456-ghi789",
  "plan_info": {
    "tier": "growth",
    "pages_used": 150,
    "total_credits_used": 312.0
  }
}

Large Document Response Fields

FieldTypeDescription
is_urlbooleanAlways true for large document responses. Use this to detect URL-based responses.
urlstringOne-time download link of the form https://api.runpulse.com/large_results/{job_id}. The link streams the complete extraction result the first time it is fetched and is then invalidated (subsequent reads return 410 Gone). It also expires 1 hour after the job completes. Authenticate the request with your x-api-key header.
plan_infoobjectBilling information including pages used and plan tier.
/large_results/{job_id} links are single-use and expire 1 hour after the job completes. Download and persist the payload immediately — do not pass the URL through queues or share it across workers.

Handling Large Document Responses

import requests
from pulse import Pulse

API_KEY = "YOUR_API_KEY"
client = Pulse(api_key=API_KEY)

response = client.extract(
    file_url="https://platform.runpulse.com/api/examples/637e5678-30b1-45fa-acc4-877f2d636419/pdf"
)

if hasattr(response, "is_url") and response.is_url:
    full_result = requests.get(
        response.url,
        headers={"x-api-key": API_KEY},
    ).json()
    print(full_result["markdown"])
else:
    print(response.markdown)
import { PulseClient } from 'pulse-ts-sdk';

const API_KEY = "YOUR_API_KEY";
const client = new PulseClient({ apiKey: API_KEY });

const response = await client.extract({
    fileUrl: "https://platform.runpulse.com/api/examples/637e5678-30b1-45fa-acc4-877f2d636419/pdf"
});

if ((response as any).is_url) {
    const fullResult = await fetch((response as any).url, {
        headers: { "x-api-key": API_KEY },
    }).then(r => r.json());
    console.log(fullResult.markdown);
} else {
    console.log(response.markdown);
}
curl -X POST https://api.runpulse.com/extract \
  -H "x-api-key: YOUR_API_KEY" \
  -F "file=@large_document.pdf"

# Response: {"is_url": true, "url": "https://api.runpulse.com/large_results/abc123-..."}

# Fetch the result once (single-use link, valid for 1 hour after job completion)
curl -H "x-api-key: YOUR_API_KEY" \
  "https://api.runpulse.com/large_results/abc123-..."
Because /large_results/{job_id} is one-time use, persist the result to your own storage on first download. If you need to access the result later, enable storage.enabled and retrieve it from your extraction library on the Pulse Platform.

Example Usage

Basic Extraction

from pulse import Pulse
from pulse.types import (
    ExtractRequestFigureProcessing,
    ExtractRequestExtensions,
    ExtractRequestExtensionsAltOutputs,
)

client = Pulse(api_key="YOUR_API_KEY")

# Extract from URL with figure processing and HTML output
response = client.extract(
    file_url="https://platform.runpulse.com/api/examples/637e5678-30b1-45fa-acc4-877f2d636419/pdf",
    figure_processing=ExtractRequestFigureProcessing(
        description=True,
    ),
    extensions=ExtractRequestExtensions(
        alt_outputs=ExtractRequestExtensionsAltOutputs(
            return_html=True,
        ),
    ),
)

print(f"Markdown: {response.markdown}")
print(f"HTML: {response.extensions.alt_outputs.html}")
print(f"Extraction ID: {response.extraction_id}")
import { PulseClient } from 'pulse-ts-sdk';

const client = new PulseClient({ apiKey: "YOUR_API_KEY" });

const response = await client.extract({
    fileUrl: "https://platform.runpulse.com/api/examples/637e5678-30b1-45fa-acc4-877f2d636419/pdf",
    figureProcessing: { description: true },
    extensions: { altOutputs: { returnHtml: true } }
});

console.log(`Markdown: ${response.markdown}`);
console.log(`HTML: ${response.extensions?.altOutputs?.html}`);
console.log(`Extraction ID: ${response.extraction_id}`);
# Extract from URL with figure processing
curl -X POST https://api.runpulse.com/extract \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "file_url": "https://platform.runpulse.com/api/examples/637e5678-30b1-45fa-acc4-877f2d636419/pdf",
    "figureProcessing": {"description": true},
    "extensions": {"altOutputs": {"returnHtml": true}}
  }'

File Upload

from pulse.types import ExtractRequestFigureProcessing

# Upload and extract a local file
with open("document.pdf", "rb") as f:
    response = client.extract(
        file=f,
    figure_processing=ExtractRequestFigureProcessing(
        description=True,
    ),
    )
import * as fs from 'fs';

const fileBuffer = fs.readFileSync("document.pdf");
const blob = new Blob([fileBuffer], { type: 'application/pdf' });

const response = await client.extract({
    file: blob,
});
curl -X POST https://api.runpulse.com/extract \
  -H "x-api-key: YOUR_API_KEY" \
  -F "file=@document.pdf"

Structured Data (Extract → Schema)

The structured_output parameter on /extract is deprecated. Use the /schema endpoint after extraction instead. This gives you better control, re-runnability, and support for split-mode schemas.
Recommended two-step approach:
# Step 1: Extract the document
response = client.extract(
    file_url="https://platform.runpulse.com/api/examples/637e5678-30b1-45fa-acc4-877f2d636419/pdf"
)

extraction_id = response.extraction_id

# Step 2: Apply schema separately
schema_result = client.schema(
    extraction_id=extraction_id,
    schema_config={
        "input_schema": {
            "type": "object",
            "properties": {
                "total": {"type": "number"},
                "vendor": {"type": "string"}
            }
        },
        "schema_prompt": "Extract invoice total and vendor"
    }
)

print(schema_result.schema_output)
// Step 1: Extract the document
const response = await client.extract({
    fileUrl: "https://platform.runpulse.com/api/examples/637e5678-30b1-45fa-acc4-877f2d636419/pdf"
});

const extractionId = response.extraction_id;

// Step 2: Apply schema separately
const schemaResult = await client.schema({
    extraction_id: extractionId,
    schema_config: {
        input_schema: {
            type: "object",
            properties: {
                total: { type: "number" },
                vendor: { type: "string" }
            }
        },
        schema_prompt: "Extract invoice total and vendor"
    }
});

console.log(schemaResult.schema_output);
# Step 1: Extract the document
curl -X POST https://api.runpulse.com/extract \
  -H "x-api-key: YOUR_API_KEY" \
  -F "file=@invoice.pdf"

# Response includes extraction_id: "abc123-..."

# Step 2: Apply schema
curl -X POST https://api.runpulse.com/schema \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "extraction_id": "abc123-...",
    "schema_config": {
      "input_schema": {"type": "object", "properties": {"total": {"type": "number"}, "vendor": {"type": "string"}}},
      "schema_prompt": "Extract invoice total and vendor"
    }
  }'

Page Range and Chunking

from pulse.types import (
    ExtractRequestExtensions,
    ExtractRequestExtensionsChunking,
)

response = client.extract(
    file_url="https://platform.runpulse.com/api/examples/637e5678-30b1-45fa-acc4-877f2d636419/pdf",
    pages="1-5,10",  # 1-indexed
    extensions=ExtractRequestExtensions(
        chunking=ExtractRequestExtensionsChunking(
            chunk_types=["semantic", "page"],
            chunk_size=1000,
        ),
    ),
)

# Chunk data is in extensions.chunking
print(response.extensions.chunking.semantic)
print(response.extensions.chunking.page)
const response = await client.extract({
    fileUrl: "https://platform.runpulse.com/api/examples/637e5678-30b1-45fa-acc4-877f2d636419/pdf",
    pages: "1-5,10",  // 1-indexed
    extensions: {
        chunking: {
            chunkTypes: ["semantic", "page"],
            chunkSize: 1000
        }
    }
});

// Chunk data is in extensions.chunking
console.log(response.extensions?.chunking?.semantic);
console.log(response.extensions?.chunking?.page);
curl -X POST https://api.runpulse.com/extract \
  -H "x-api-key: YOUR_API_KEY" \
  -F "file=@document.pdf" \
  -F "pages=1-5,10" \
  -F 'extensions={"chunking": {"chunkTypes": ["semantic", "page"], "chunkSize": 1000}}'

Footnote References

Enable extensions.footnote_references to detect footnote markers (e.g. *, , 1) in body text and link them to the footnote explanation paragraphs at the bottom of the page. Each result item includes the marker symbol, the bounding-box text ID of the footnote, and the bounding-box text IDs of all body-text paragraphs that reference it.
from pulse.types import ExtractRequestExtensions

response = client.extract(
    file_url="https://example.com/research-paper.pdf",
    extensions=ExtractRequestExtensions(
        footnote_references=True,
    ),
)

# Footnote links are in extensions.footnote_references
for ref in response.extensions.footnote_references:
    print(f"Marker: {ref.symbol}")
    print(f"  Footnote: {ref.footnote_text_id}")
    print(f"  Referenced by: {ref.reference_text_ids}")
const response = await client.extract({
    fileUrl: "https://example.com/research-paper.pdf",
    extensions: {
        footnoteReferences: true
    }
});

// Footnote links are in extensions.footnoteReferences
for (const ref of response.extensions?.footnoteReferences ?? []) {
    console.log(`Marker: ${ref.symbol}`);
    console.log(`  Footnote: ${ref.footnoteTextId}`);
    console.log(`  Referenced by: ${ref.referenceTextIds}`);
}
curl -X POST https://api.runpulse.com/extract \
  -H "x-api-key: YOUR_API_KEY" \
  -F "file=@research-paper.pdf" \
  -F 'extensions={"footnoteReferences": true}'

Example Response

{
  "markdown": "...",
  "bounding_boxes": { ... },
  "extensions": {
    "footnoteReferences": [
      {
        "symbol": "*",
        "footnoteTextId": "txt-11",
        "referenceTextIds": ["txt-4", "txt-5", "txt-6", "txt-7", "txt-8"]
      },
      {
        "symbol": "†",
        "footnoteTextId": "txt-12",
        "referenceTextIds": ["txt-8"]
      },
      {
        "symbol": "4",
        "footnoteTextId": "txt-48",
        "referenceTextIds": ["txt-45"]
      }
    ]
  }
}

Footnote Reference Fields

FieldTypeDescription
symbolstringThe footnote marker symbol as detected in the document (e.g. *, , , 1, #).
footnoteTextIdstringThe bounding-box text ID (e.g. txt-11) of the footnote explanation paragraph. Cross-reference with bounding_boxes.Footer to get the footnote’s content and position.
referenceTextIdsstring[]Bounding-box text IDs of body-text paragraphs that contain a reference to this footnote. Cross-reference with bounding_boxes.Text to get each paragraph’s content and position.
Footnote reference detection uses Azure Document Intelligence for paragraph classification, supplemented by PyMuPDF native text extraction for accurate symbol identification. This handles common OCR confusion between visually similar symbols like /+ and /#. Supported marker types include numbered (1, 2, 3), symbolic (*, , , §, #), and lettered (a, b, c) footnotes.

Excel Spreadsheet Options

from pulse import Pulse
from pulse.types import ExtractRequestSpreadsheet

client = Pulse(api_key="YOUR_API_KEY")

# Extract from Excel with hidden content included
response = client.extract(
    file=open("financials.xlsx", "rb"),
    spreadsheet=ExtractRequestSpreadsheet(
        include_hidden_rows=True,
        include_hidden_cols=True,
        include_hidden_sheets=False,
    ),
)

print(response.markdown)
import { PulseClient } from 'pulse-ts-sdk';

const client = new PulseClient({
    headers: { 'x-api-key': 'YOUR_API_KEY' }
});

const response = await client.extract({
    file: fs.createReadStream("financials.xlsx"),
    spreadsheet: {
        includeHiddenRows: true,
        includeHiddenCols: true,
        includeHiddenSheets: false
    }
});

console.log(response.markdown);
curl -X POST https://api.runpulse.com/extract \
  -H "x-api-key: YOUR_API_KEY" \
  -F "file=@financials.xlsx" \
  -F 'spreadsheet={"includeHiddenRows": true, "includeHiddenCols": true, "includeHiddenSheets": false}'
Workbooks exported from claims systems, ERPs, and other automated pipelines often declare a “used range” that extends hundreds of thousands of rows past where the data actually ends. Set spreadsheet.only_data_rows: true and spreadsheet.only_data_cols: true to have Pulse trim those trailing empty “phantom” rows and columns before parsing. Surviving cells keep their original A1 coordinates, so any citation or bounding box that references a specific cell remains stable. Both flags default to false. See the extraction options above for the full reference.

Excel Charts and Embedded Images

When you set figure_processing.show_images: true on an Excel workbook, every embedded chart and image is collected from the workbook directly and returned under bounding_boxes.Images[]. Each entry carries a Pulse-hosted image_url you can fetch via results.getImage (or any HTTP client with your API key) to get the raw PNG/JPEG bytes.
import re
from pulse import Pulse
from pulse.types import ExtractRequestFigureProcessing

client = Pulse(api_key="YOUR_API_KEY")

# 1) Extract the workbook with show_images enabled.
response = client.extract(
    file=open("financials.xlsx", "rb"),
    figure_processing=ExtractRequestFigureProcessing(
        show_images=True,
        description=False,
    ),
)

# 2) Walk the typed Images array.
for img in response.bounding_boxes.images or []:
    print(f"{img.id}: {img.visual_type} '{img.chart_title}' @ {img.excel_range}")
    print(f"    url: {img.image_url}")

# 3) Fetch the bytes for one chart.
img = response.bounding_boxes.images[0]
m = re.search(r"/results/([^/]+)/images/([^/?#]+)", img.image_url)
job_id, filename = m.group(1), m.group(2)

chunks = list(client.results.get_image(job_id=job_id, filename=filename))
with open("chart.png", "wb") as f:
    f.write(b"".join(chunks))
import { PulseClient } from "pulse-ts-sdk";
import * as fs from "node:fs";

const client = new PulseClient({ apiKey: "YOUR_API_KEY" });

// 1) Extract the workbook with show_images enabled.
const response = await client.extract({
    file: fs.createReadStream("financials.xlsx"),
    figureProcessing: { showImages: true, description: false },
});

// 2) Walk the typed Images array.
for (const img of response.boundingBoxes?.Images ?? []) {
    console.log(
        `${img.id}: ${img.visualType} '${img.chartTitle}' @ ${img.excelRange}`,
    );
    console.log(`    url: ${img.imageUrl}`);
}

// 3) Fetch the bytes for one chart.
const url = response.boundingBoxes?.Images?.[0]?.imageUrl;
const m = url?.match(/\/results\/([^/]+)\/images\/([^/?#]+)/);
const [, jobId, filename] = m!;
const image = await client.results.getImage({ jobId, filename });
// Persist `image` per your runtime (e.g. `await image.bytes()`).
# Step 1: extract and capture an image_url from the response.
curl -sS -X POST https://api.runpulse.com/extract \
  -H "x-api-key: YOUR_API_KEY" \
  -F "file=@financials.xlsx" \
  -F 'figure_processing={"show_images": true}' \
  | jq -r '.bounding_boxes.Images[0].image_url'

# Step 2: fetch the PNG bytes.
curl -sS -X GET "https://api.runpulse.com/results/$JOB_ID/images/excel_image_1_1.png" \
  -H "x-api-key: YOUR_API_KEY" \
  -o chart.png

Example bounding_boxes.Images Entry

{
  "id": "excel_image_1_1",
  "visual_type": "chart",
  "page_number": 1,
  "bounding_box": [],
  "image_url": "https://api.runpulse.com/results/13e3e75f-.../images/excel_image_1_1.png",
  "sheet_name": "Charts",
  "excel_range": "D2",
  "chart_type": "BarChart",
  "chart_title": "Revenue",
  "source_ranges": ["'Charts'!$A$2:$A$5", "'Charts'!$B$2:$B$5"],
  "description": "Bar chart showing revenue by quarter."
}
See Bounding Boxes — Images Array for the full field reference and Get Result Image for the auth requirement on image_url.

Disable Storage

response = client.extract(
    file_url="https://platform.runpulse.com/api/examples/637e5678-30b1-45fa-acc4-877f2d636419/pdf",
    storage={"enabled": False}
)
const response = await client.extract({
    fileUrl: "https://platform.runpulse.com/api/examples/637e5678-30b1-45fa-acc4-877f2d636419/pdf",
    storage: { enabled: false }
});
curl -X POST https://api.runpulse.com/extract \
  -H "x-api-key: YOUR_API_KEY" \
  -F "file=@document.pdf" \
  -F 'storage={"enabled": false}'

Authorizations

x-api-key
string
header
required

Body

multipart/form-data

Input schema for extraction requests. Provide either file (direct upload) or fileUrl (remote URL).

file
file

Document to upload directly. Required unless fileUrl is provided.

fileUrl
string<uri>

Public or pre-signed URL that Pulse will download and extract. Required unless file is provided.

model
enum<string>

Extraction model to use. When set to pulse-ultra-2, routes the request through Pulse Ultra 2 (self-hosted VPC model) instead of the default cloud-based service. If omitted or set to default, the default model is used.

Available options:
default,
pulse-ultra-2
detectSelections
boolean

Pulse Ultra 2 only. Enables a specialized selection-mark detection pass that improves selected/unselected state accuracy for forms, checkboxes, radio buttons, handwritten checkmarks, X marks, and similar controls. Enabled by default when model is pulse-ultra-2; set to false to skip this pass. Passing true without model: pulse-ultra-2 returns a validation error.

extractionConfigId
string<uuid>

UUID of a saved extraction configuration (a "preset"). When provided, the server loads the saved configuration and applies its options on top of any inline parameters supplied in this request. Inline parameters always take precedence over preset values for the same field. Saved configs are managed via the platform UI or the input_extractions admin endpoints.

pages
string

Page range filter supporting segments such as 1-2 or mixed ranges like 1-2,5.

Pattern: ^[0-9]+(-[0-9]+)?(,[0-9]+(-[0-9]+)?)*$
figureProcessing
object

Settings that control how figures and embedded visuals are processed. Applies to both PDFs/images (where figures are detected from layout) and spreadsheets (where charts and embedded images are read directly from the workbook). These options affect the markdown output and the bounding_boxes.Images[] array; they do not produce additional output fields elsewhere in the response.

extensions
object

Settings that enable additional processing passes or alternate output formats. Each enabled extension produces a corresponding output field under response.extensions.*.

spreadsheet
object

Settings for Excel/spreadsheet extraction. Controls handling of hidden rows, columns, and sheets, whether numeric cells are rendered using their display format or underlying raw value, and optional trimming of empty phantom rows/columns past the last data-bearing cell. Applies to .xlsx, .xlsm, and .xls files. Accepts both camelCase and snake_case field names.

storage
object

Options for persisting extraction artifacts. When enabled (default), artifacts are saved to storage and a database record is created.

async
boolean
default:false

If true, returns immediately with a job_id for polling via GET /job/{jobId}. Otherwise processes synchronously.

structuredOutput
object
deprecated

⚠️ DEPRECATED — Use the /schema endpoint after extraction instead. Pass the extraction_id from the extract response to /schema with your schema_config. This parameter still works for backward compatibility but will be removed in a future version.

schema
deprecated

(Deprecated) JSON schema describing structured data to extract. Use structuredOutput instead. Accepts either a JSON object or a stringified JSON representation.

schemaPrompt
string
deprecated

(Deprecated) Natural language prompt for schema-guided extraction. Use structuredOutput.schemaPrompt instead.

customPrompt
string
deprecated

(Deprecated) Custom instructions that augment the default extraction behaviour. Use figureProcessing or extensions instead.

chunking
string
deprecated

⚠️ DEPRECATED — Use extensions.chunking.chunkTypes instead. Comma-separated list of chunking strategies to apply (for example semantic,header,page,recursive). Still accepted for backward compatibility.

chunkSize
integer
deprecated

⚠️ DEPRECATED — Use extensions.chunking.chunkSize instead. Override for maximum characters per chunk when chunking is enabled.

Required range: x >= 1
extractFigure
boolean
default:false
deprecated

⚠️ DEPRECATED — Toggle to enable figure extraction in results.

figureDescription
boolean
default:false
deprecated

⚠️ DEPRECATED — Use figureProcessing.description instead. Toggle to generate descriptive captions for extracted figures.

showImages
boolean
default:false
deprecated

⚠️ DEPRECATED — Use figureProcessing.showImages instead. Embed base64-encoded images inline in figure tags in the output. Increases response size.

returnHtml
boolean
default:false
deprecated

⚠️ DEPRECATED — Use extensions.altOutputs.returnHtml instead. Whether to include HTML representation alongside markdown in the response.

thinking
boolean
default:false
deprecated

(Deprecated) Enables expanded rationale output for debugging.

Response

Extraction result. For documents under 70 pages the full result is returned inline. For larger documents the response contains is_url: true and a single-use url to download the full result via GET /large_results/{jobId}.

Full extraction result returned by the synchronous /extract endpoint. Inherits all core fields and adds deprecated backward-compatibility fields.

markdown
string

Primary markdown content extracted from the document. Always present in the new format.

extensions
object

Output from enabled extensions. Each key corresponds to an extension that was enabled in the request under extensions.*. Only keys for enabled extensions are present.

bounding_boxes
object

Positional bounding-box data for text, titles, headers, footers, images, and tables. Images carries chart/image visuals (with image_url when figure_processing.show_images is enabled), Tables the detected tables, and Text/Title/Footer the paragraph/title/footer regions. Additional keys (e.g. markdown_with_ids, defined_names) round-trip without being typed.

extraction_id
string<uuid>

Persisted extraction ID. Present when storage is enabled (default). Use this ID with /split and /schema endpoints.

extraction_url
string

URL to view the extraction on the Pulse platform. Present when storage is enabled.

page_count
integer

Number of pages processed.

Required range: x >= 1
plan_info
object

Billing tier and cumulative usage information. Includes total_credits_used (primary billing metric) and pages_used (legacy compatibility).

warnings
string[]

Non-fatal warnings generated during extraction. Includes deprecation notices when legacy input parameters are used, as well as processing warnings (e.g. word-level bounding box limitations).

credits_used
number<float> | null

Number of credits consumed by this request. Only present when the organization has the credit billing system enabled.

html
string
deprecated

Deprecated — Use extensions.altOutputs.html instead. HTML representation of the extracted content. Present when the legacy returnHtml input was used.

chunks
object
deprecated

Deprecated — Use extensions.chunking instead. Document content split into chunks. Present when the legacy chunking input was used.

structured_output
object
deprecated

Deprecated — Only present when the deprecated structuredOutput input parameter was used. Use the /schema endpoint after extraction instead.

input_schema
object
deprecated

Deprecated — Echo of the schema that was applied. Only present when the deprecated structuredOutput input parameter was used.

schema_error
string
deprecated

Deprecated — Error message if schema processing failed via the deprecated structuredOutput input parameter.

content
string
deprecated

Deprecated — Alias for markdown. Included for backward compatibility with older SDK versions. Prefer markdown.

job_id
string
deprecated

Deprecated — Identifier assigned to the extraction job. Retained for backward compatibility.

metadata
object
deprecated

Deprecated — Additional metadata supplied by the backend. Retained for backward compatibility.