Skip to navigation

How to split a document bundle

View as Markdown

Split divides a bundle of pages into separate documents. Use it when one file holds several documents, such as a scanned stack of invoices and receipts.

You provideA document (+ a split method)
EndpointPOST /doc-ai/v1/job/split
OutputChild documents, each with its original page numbers and a document_ref
InputPDF, PNG, JPEG, TIFF; up to 500 pages and 512 MB per document

Quick start

Split takes the same document input, plus a method describing where one document ends and the next begins. The result lists the child documents, each with its original page numbers and a document_ref you can reuse in other requests.

import os, time
from sarvamai import SarvamAI
from sarvamai.core.api_error import ApiError
client = SarvamAI(api_subscription_key=os.environ["SARVAM_API_KEY"])
try:
# Create and submit a split job in one call
with open("./sample-document.pdf", "rb") as f:
job = client.doc_ai.split(
file=[("sample-document.pdf", f, "application/pdf")],
request={
"config": {
"method": "fixed_pages",
"pages_per_segment": 2,
"classify_segments": False,
},
},
)
print("job created:", job.job_id, "| status:", job.status)
# Poll until the job reaches a terminal state
TERMINAL = {"completed", "partially_completed", "failed", "rejected"}
while True:
st = client.doc_ai.get_status(job_id=job.job_id)
print(f"status={st.status} phase={st.phase}")
if st.status.lower() in TERMINAL:
break
time.sleep(5)
# Fetch the child documents
if st.status.lower() in ("completed", "partially_completed"):
results = client.doc_ai.get_results(job_id=job.job_id)
for seg in results.result.segments:
print(seg.pages, seg.document_ref, "review:", seg.review_required)
except FileNotFoundError:
print("Document file not found: ./sample-document.pdf")
except ApiError as e:
print(f"API error {e.status_code}: {e.body}")

Send the options as a JSON string in request. Split and Classify read their options from a request form field next to the file. In Python the SDK takes it as a dict (request={...}); with cURL, pass the JSON text. In Python, file takes a list and job_id is passed by name, get_status(job_id=...). In JavaScript, file takes an array, job_id is positional, getStatus(job_id), and request and response fields use the wire names (pages_per_segment, review_required), as for Digitise and Extract.

Split methods

Set config.method to one of:

MethodUse it whenAlso needs
semanticThe model should find where each document starts and ends (default)categories, or classify_segments: false
fixed_pagesEvery document has the same number of pagespages_per_segment
page_rangesYou already know the boundariessegment_ranges
triggersDocuments start at a marker such as a blank page or a line of textsplit_on

Other options:

  • classify_segments: true (the default) labels each child document with one of your categories; false only splits. With true, categories is required. With false, sending categories is rejected.
  • categories: up to 20 entries, each with a type and a description. Names are yours to choose and must be unique.
  • remainder: for fixed_pages, keep (the default) keeps a shorter last group and error rejects the request when the pages do not divide evenly.
  • segment_ranges: 1-based, inclusive ranges, such as [{"start": 1, "end": 5}, {"start": 6, "end": 10}]. They must cover the selected pages exactly once, in order.
  • pages: add "pages": [{"start": 1, "end": 2}] to the request to split only those pages.

Split at markers

With triggers, a new document starts at each page that matches a marker in split_on:

{"config": {"method": "triggers", "split_on": [{"type": "text", "match": {"prefix": "Cover:"}}], "classify_segments": false}}
  • type: blank_page, text, qr_code, barcode, or photo. A photo marker needs a description of the image.
  • match: for text, qr_code, and barcode, exactly one of equals, prefix, or regex. These go inside match, not on the marker itself.
  • Optional: where (anywhere or top_of_page), trigger_page (first_page, separator_exclude, or separator_keep), split_when (every_match or value_changes, for codes only), and formats for barcodes.

A blank separator page is left out of the segments (listed under coverage.excluded_pages). Pages before the first marker form a segment flagged LEADING_PAGES_WITHOUT_TRIGGER, and a file with no marker comes back as one segment flagged the same way. To label the segments, add categories and leave classify_segments on; with classify_segments: false, categories is rejected.

Split results

{
"job_id": "01a17998-07ef-7040-800d-745a95140cf5",
"type": "split",
"status": "completed",
"result": {
"summary": {"documents": 2, "ready": 2, "needs_review": 0, "excluded_pages": 0, "unresolved_pages": 0},
"review_required": false,
"review_reasons": [],
"coverage": {"complete": true, "excluded_pages": [], "unresolved_pages": []},
"segments": [
{
"id": "seg_80d6fa828cfad12c7c13446b16bf81a0",
"document_ref": "doc_80d6fa82...",
"pages": [1, 2],
"role": "document",
"type": null,
"classification_status": "not_requested",
"review_required": false,
"review_reasons": []
}
]
},
"usage": {"pages_processed": 4, "pages_source": 4}
}
  • Each segment is a child document. pages refers to its original page numbers, and document_ref lets you reuse it in another request.
  • With classify_segments: true, type is the matching category and classification_status is matched, or unknown with unknown_reason: "no_matching_type" when none fits.
  • status: "completed" means processing finished, not that every segment passed review. Check review_required on each segment before accepting the result automatically.

Request behaviours

Split and Classify share these request behaviours:

  • Inputs: PDF, PNG, JPEG, or TIFF. Repeat the file field for up to 10 documents with the same config; you get a parent job and a documents list of individual jobs, each with its own status_url and results_url. The parent’s results include each document’s result under documents. You can also upload first with POST /doc-ai/v1/job/upload and send the id as upload_ids. URL input is not available.
  • Retries: add an Idempotency-Key header to retry the same submission without creating another job. A changed request under the same key returns 409.
  • Waiting: send "execution": "auto" in request to wait briefly for a single document. A finished answer returns with HTTP 200; otherwise you get the job to poll.
  • Capabilities: GET /doc-ai/v1/capabilities lists the operations, input formats, split methods, and limits enabled on your deployment.

Next steps