Skip to navigation

GroundX Ingest for Parsing

Comprehensive Document Parsing for Modern Applications

X-Ray analyzes document layout, text, tables and figures for use in RAG, agents and document summaries.

For structured JSON your application can use directly, see Extract Data from Documents, or Use GroundX With Your Agent if you’d like an agent to draft that schema for you.

X-Ray in a Nutshell

X-Ray combines these processing steps in one API:

  • Models detect document elements.
  • OCR extracts text.
  • Repair and formatting steps make parsed content easier to use.
  • Contextualization adds summaries and surrounding document context.

The result represents document content in a form developers and LLMs can use.

See it for yourself

X-Ray uses a vision model trained on documents from multiple domains. Try the demo with your documents.

Medical billing receipt An example of X-Ray identifying and extracting key elements from a real-world document.

To use X-Ray through the API, follow these steps:

How to use X-Ray

API Key
SDK Version
X-Ray was added to the SDKs in versions Python 1.3.19 and TypeScript 1.3.24. Older versions of the SDKs do not contain X-Ray support.

1) Authenticating

Create a client with your GroundX API key. Use it for the remaining requests.

from groundx import GroundX, Document
import urllib.request, json, time
# authenticating
client = GroundX(
api_key="YOUR_API_KEY",
)

2) Creating a Bucket

Choose an existing bucket with List Buckets, or use Create Bucket to create one.

# creating a new bucket
bucket_response = client.buckets.create(
name="parsed_documents_bucket"
)
# storing the bucket_id
bucket_id = bucket_response.bucket.bucket_id

3) Uploading Documents

Uploading a document with full processing produces X-Ray. This example uploads a local document using Ingest Local.

ingest_response = client.ingest(
documents=[
Document(
bucket_id=bucket_id,
file_name="sample",
file_path="sample.pdf",
file_type="pdf"
)
]
)

4) Querying Upload Status

Ingest returns a process_id. Use Get Processing Status to check progress. These examples poll every 3 seconds until processing completes, fails or is cancelled. For polling guidance and large batches, see Errors and Rate Limits.

while (True):
ingest_response = client.documents.get_processing_status_by_id(
process_id=ingest_response.ingest.process_id,
)
if (ingest_response.ingest.status == "complete" or ingest_response.ingest.status == "cancelled"):
break
if (ingest_response.ingest.status == "error"):
raise ValueError('Error Ingesting Document')
print(ingest_response.ingest.status)
time.sleep(3)

5) Getting X-Ray Results

After processing completes, use Get Document to look up the bucket’s documents. This example assumes the bucket contains only the document just uploaded. It reads that document’s xrayUrl and downloads the X-Ray JSON.

# Getting parsed documents from the bucket
document_response = client.documents.lookup(
id=bucket_id
)
# Getting the X-Ray parsing results for one of the documents
xray_url = document_response.documents[0].xray_url
with urllib.request.urlopen(xray_url) as url:
data = json.loads(url.read().decode())
print(data)

6) Interpreting X-Ray Results

X-Ray includes these fields:

  • fileKeywords: Keywords describing the document.
  • fileSummary: A summary of the document.
  • boundingBoxes: Coordinates of document content.
  • contentType: The chunk’s element types: paragraphs, figures or tables.
  • json: Graphs and figures represented as JSON for LLMs and application code.
  • narrative: Graphs and figures described in text for LLMs.
  • sectionSummary: A summary of the document section.

The following example shows the X-Ray structure:

// Successful lookup response
{
"fileType": "string", // One of the supported file types
"language": "string", // Language detected on the first page of your document during processing
"fileKeywords": "string", // Auto-generated comma-delimited list of keywords describing your document
"fileName": "string", // Name you gave the document when it was uploaded
"fileSummary": "string", // Auto-generated document summary
"chunks": [ // Primary array of all semantic objects for the document — always read content from here, some semantic objects are spread across multiple pages
{
"boundingBoxes": [ // Boxes containing semantic object elements
{
"bottomRightX": number, // X coordinate for lower right corner of semantic object element
"bottomRightY": number, // Y coordinate for lower right corner of semantic object element
"pageNumber": number, // Number of page for semantic object element, starting at 1
"topLeftX": number, // X coordinate for upper left corner of semantic object element
"topLeftY": number, // Y coordinate for upper left corner of semantic object element
}
],
"chunk": "string", // Unique chunk ID for the semantic object, e.g. "bvzx4u-0"
"contentType": [ // Types of elements represented within the semantic object
"string" // "table" | "figure" | "paragraph"
],
"json": [ // Element text, reformatted into JSON format, for "table" and "figure" elements only. json[0] is a metadata object (not a data row); data/visual elements begin at json[1]
"object" // Auto-generated JSON object describing a section of the information within the "table" or "figure"
],
"multimodalUrl": "string", // Element image, for multimodal processing "table" and "figure" elements only
"narrative": [ // Element text, reformatted into narrative format, for "table" and "figure" elements only
"string" // Auto-generated narrative description of a section of the information within the "table" or "figure"
],
"pageNumbers": [ // Pages where semantic object exists
number // Number of page where semantic object exists
],
"sectionSummary": "string", // Auto-generated section summary for the document section containing the semantic object
"suggestedText": "string", // Element text, reformatted for LLM completion
"text": "string" // Element text, extracted and unprocessed. Always populated for "paragraph" and "table" (flattened); usually empty "" for "figure"
}
],
"documentPages": [ // Pages and metadata within the document
{
"chunks": [ // Duplicate of the top-level chunks[] array, filtered to this page — do not use this for content, read from the top-level chunks[] instead
"..."
],
"height": number, // Pixel height of page image
"pageNumber": number, // Number of page, starting at 1
"pageUrl": "string", // Hosted URL for the page image
"width": number // Pixel width of page image
}
],
"sourceUrl": "string", // Hosted URL for your document
}

Next Steps

Protected X-Ray

On a compatible deployment, protected document metadata returns xrayUrl with ?view=links. Fetch it from a trusted server with X-API-Key to get fresh links to the stored source, pages and crops. An MCP token does not authenticate file-host requests.

This view requires GET, rejects Range and returns fresh JSON without raw-file ETags or 304 responses. The URL without ?view=links and an xray share link return stored raw JSON. Sharing that JSON does not grant access to the files it references. Preserve raw bytes for evidence and fixtures. Large protected X-Ray responses use the file gateway to avoid buffered API size limits. See File Access and Sharing.