Skip to main content
POST
/
form
/
fill
Fill PDF Form
curl --request POST \
  --url https://api.runpulse.com/form/fill \
  --header 'Content-Type: application/json' \
  --header 'x-api-key: <api-key>' \
  --data '
{
  "instructions": "Fill in patient name as Jane Doe, DOB 01/15/1990.",
  "page_range": "<string>",
  "async": false,
  "form_fields": [
    {
      "page_number": 2,
      "bounding_box": [
        0.5
      ],
      "text": "<string>",
      "type": "text",
      "row": 1,
      "col": 1,
      "table_idx": 1,
      "checkbox_details": [
        {
          "center_coord": [
            0.5
          ],
          "selected": true,
          "text": "<string>"
        }
      ]
    }
  ],
  "form_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
  "file_url": "<string>"
}
'
{
  "form_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
  "page_count": 2,
  "form_fields": [
    {
      "page_number": 2,
      "bounding_box": [
        0.5
      ],
      "text": "<string>",
      "type": "text",
      "row": 1,
      "col": 1,
      "table_idx": 1,
      "checkbox_details": [
        {
          "center_coord": [
            0.5
          ],
          "selected": true,
          "text": "<string>"
        }
      ]
    }
  ],
  "pdf_url": "<string>",
  "fields_filled": 1,
  "fields_cleared": 1,
  "credits_used": 123,
  "plan_info": {
    "tier": "<string>",
    "total_credits_used": 123,
    "pages_used": 1
  }
}

Documentation Index

Fetch the complete documentation index at: https://docs.runpulse.com/llms.txt

Use this file to discover all available pages before exploring further.

Overview

Fill a PDF form from natural-language instructions. Returns a FormResult synchronously by default (with a pdf_url you can GET to download the filled PDF). Set async: true to run in the background and poll GET /jobjobId for the result.
/form/fill writes values into the fields of a PDF form based on a natural-language instructions prompt. It works on both PDFs with native form fields (where the values are written directly into the form) and on flat or scanned PDFs (where the values are placed into the detected fields).

Providing the PDF

Provide the PDF in exactly one of the following ways:
  • form_id: chain off a prior /form/detect, /form/fill, or /form/clear call. The cached PDF and form_fields are reused, so there is no need to re-upload.
  • file_url: public or presigned URL to a PDF.
  • file: direct PDF upload (multipart only).
Sending more than one (or none) returns 400.

Pricing

Billed at 3 credits per page of the PDF being filled. Every response also returns a top-level credits_used for this request and a cumulative plan_info.total_credits_used snapshot for your organization.

Request

Request Body

FieldTypeRequiredDescription
form_idstring (uuid)One of theseReuse a previously processed form. Skips re-upload and re-detection.
file_urlstring (uri)One of thesePublic or presigned URL of a PDF to download and fill.
filebinaryOne of theseDirect PDF upload (multipart only).
instructionsstringYesNatural-language description of what to fill into the form. Example: "Use John Doe, 123 Main St, born 1990-01-01".
form_fieldsarray of FormCellNoOptional override for the cells used when filling. Useful when the caller has hand-edited the cells returned by /form/detect.
page_rangestringNo1-based page filter, for example "1,3-5". Alias pages accepted.
asyncbooleanNoWhen true, returns { job_id, status: "pending" } immediately (HTTP 202) and processes the job in the background. Default false.

Response

Sync (200): FormResult

When async is false (default), the call returns a FormResult body directly.
FieldTypeDescription
form_idstring (uuid)ID of the new form record produced by this run. Pass back via form_id to chain further fills, clears, or detects.
page_countintegerNumber of pages in the output PDF.
pdf_urlstring (uri)URL to download the filled PDF binary. Always points at GET /results/jobId/pdf. Requires the same auth (API key or JWT) as the rest of the API and only serves results owned by the calling organization.
form_fieldsarray of FormCellDetected cells of the resulting (filled) PDF, refreshed after the fill.
fields_filledintegerNumber of cells whose value actually changed during this run (no-op writes are not counted).
credits_usednumberCredits consumed by this request (3 × page_count).
plan_infoobject{ tier, total_credits_used, pages_used } cumulative billing snapshot for your organization (post-request).
{
  "form_id": "00e2c454-4e6f-429b-bd74-320ad94b2153",
  "page_count": 6,
  "pdf_url": "https://api.runpulse.com/results/dab7285d-8a65-4cb6-9d24-d5db64d3798e/pdf",
  "form_fields": [
    {
      "page_number": 1,
      "type": "text",
      "bounding_box": [0.118, 0.226, 0.634, 0.241],
      "text": "Acme Logistics LLC"
    },
    {
      "page_number": 1,
      "type": "checkbox",
      "bounding_box": [0.118, 0.226, 0.634, 0.241],
      "text": "Individual/sole proprietor C corporation S corporation Partnership",
      "checkbox_details": [
        { "center_coord": [0.125, 0.232], "selected": true,  "text": "Individual/sole proprietor" },
        { "center_coord": [0.300, 0.232], "selected": false, "text": "C corporation" },
        { "center_coord": [0.418, 0.232], "selected": false, "text": "S corporation" },
        { "center_coord": [0.535, 0.232], "selected": false, "text": "Partnership" }
      ]
    }
  ],
  "fields_filled": 7,
  "credits_used": 18.0,
  "plan_info": {
    "tier": "pulse_ultra_2",
    "total_credits_used": 1284.0,
    "pages_used": 428
  }
}
All cell coordinates (bounding_box, checkbox_details[].center_coord) are normalized to [0, 1] with a top-left origin. Multiply by your render width / height to convert to pixel coordinates.

Async (202): FormJobAccepted

When async is true:
{
  "job_id": "abc123-def456-ghi789",
  "status": "pending"
}
Poll GET /job/jobId. The job’s result carries the same FormResult shape that the sync flow would have returned inline.

Status Codes

CodeDescription
200Filled FormResult returned synchronously.
202Async job accepted (async: true). Poll /job/{jobId} for the result.
400Missing PDF, more than one PDF source provided, missing instructions, or malformed form_fields.
401Authentication failed or missing API key.
404Referenced form_id not found (or belongs to a different org).
500Internal server error.

Example Usage

Fill From URL

from pulse import Pulse

client = Pulse(api_key="YOUR_API_KEY")

result = client.form.fill(
    file_url="https://example.com/intake-form.pdf",
    instructions="Fill in patient name as Jane Doe, DOB 01/15/1990.",
)

print(f"form_id={result.form_id}")
print(f"fields_filled={result.fields_filled}")
print(f"credits_used={result.credits_used}")
print(f"download: {result.pdf_url}")

File Upload

with open("intake-form.pdf", "rb") as f:
    result = client.form.fill(
        file=f,
        instructions="Fill in patient name as Jane Doe, DOB 01/15/1990.",
    )

Detect First, Then Fill

Run /form/detect to inspect the detected cells, optionally edit them, then chain a fill that reuses the same form_id. There is no need to re-upload the PDF.
detect = client.form.detect(file_url="https://example.com/intake-form.pdf")

# (Optional) edit detected cells locally, e.g. retype a misclassified cell
edited = []
for cell in detect.form_fields or []:
    if cell.text and cell.text.strip().lower() == "signature":
        cell.type = "signature"
    edited.append(cell)

result = client.form.fill(
    form_id=detect.form_id,
    instructions="Fill in patient name as Jane Doe, DOB 01/15/1990.",
    form_fields=edited,  # omit to use the cached cells from detect
)

Async Fill With Polling

Use async: true for long-running jobs (large PDFs, multi-page fills) so the client does not have to keep a connection open.
import time

submission = client.form.fill(
    file_url="https://example.com/big-form.pdf",
    instructions="Fill the form for Jane Doe ...",
    async_=True,  # SDK aliases the reserved keyword
)

while True:
    job = client.jobs.get_job(job_id=submission.job_id)
    if job.status in ("completed", "failed"):
        break
    time.sleep(2)

result = job.result  # same FormResult body as the sync flow
print(f"fields_filled={result['fields_filled']} pdf_url={result['pdf_url']}")

Download The Filled PDF

The pdf_url returned in FormResult points at GET /results/{job_id}/pdf and requires authentication (API key or JWT).
job_id = result.pdf_url.rstrip("/").split("/")[-2]
with open("filled.pdf", "wb") as out:
    for chunk in client.results.get_pdf(job_id=job_id):
        out.write(chunk)

Authorizations

x-api-key
string
header
required

API key for authentication

Body

JSON body for POST /form/fill. Provide exactly one of form_id or file_url (or use the multipart variant to upload a file).

instructions
string
required

Required natural-language description of what to fill into the form (e.g. "Use John Doe, 123 Main St, born 1990-01-01").

Example:

"Fill in patient name as Jane Doe, DOB 01/15/1990."

page_range
string

Restrict the operation to a subset of pages. Accepts comma-separated page numbers and ranges, e.g. "1-3,5". Alias: pages.

async
boolean
default:false

When true, the endpoint returns immediately with { job_id, status: "pending" } (HTTP 202) and processes the job in the background. Poll GET /job/{jobId} for the result.

form_fields
object[]

Optional override for the cells used when filling or clearing. When omitted, Pulse uses the cells stored on the referenced form_id, or detects them from the uploaded PDF.

form_id
string<uuid>

ID returned by a previous /form/detect, /form/fill, or /form/clear call. Reuses the stored PDF and detected fields without re-uploading.

file_url
string<uri>

Public or presigned URL of a PDF to download and fill.

Response

Filled FormResult returned synchronously.

Result body returned by /form/detect, /form/fill, and /form/clear. For async jobs (async: true) the same shape is served back under result on GET /job/{jobId}.

form_id
string<uuid>
required

ID of the form record produced by this run. Pass to a subsequent /form/detect, /form/fill, or /form/clear call as the single input source to iterate without re-uploading the PDF.

page_count
integer
required

Number of pages in the output PDF.

Required range: x >= 1
form_fields
object[]
required

Detected cells of the resulting PDF (refreshed from the filled / cleared output for fill / clear, or freshly detected for /form/detect).

pdf_url
string

URL to download the resulting PDF binary. Always points at GET /results/{jobId}/pdf for the originating job. Requires the same authentication (API key or JWT) as the rest of the API.

fields_filled
integer

Number of cells whose value actually changed during this run. Present on /form/fill responses only.

Required range: x >= 0
fields_cleared
integer

Number of cells whose value actually changed during this run (no-op clears on already-empty fields are not counted). Present on /form/clear responses only.

Required range: x >= 0
credits_used
number<float>

Credits consumed by this request. Detect charges 1 credit per page; fill and clear charge 3 credits per page.

plan_info
object

Cumulative billing snapshot for the calling organization. Includes the in-flight request's contribution, so every response reflects post-request state.