# MinerU SDK for Rust ## Introduction The MinerU SDK for Rust is a comprehensive client library for interacting with the MinerU document extraction API service. MinerU provides intelligent document parsing capabilities that can extract structured content from various file formats including PDF, DOCX, PPTX, PNG, JPG, JPEG, and HTML. The service uses advanced machine learning models (pipeline and VLM versions) to accurately extract text, tables, formulas, and images while preserving the document structure and layout. This SDK wraps the MinerU REST API in an idiomatic Rust interface, providing type-safe async operations built on the Tokio runtime. It supports single file extraction, batch processing workflows, task status polling, and result retrieval. The SDK handles authentication, request serialization, response parsing, and error handling, making it straightforward to integrate document extraction capabilities into Rust applications. The project also includes a CLI tool for command-line usage and testing. ## API Functions ### Create Single Document Extraction Task Creates an extraction task for a single document by providing a URL to the file. Returns a task ID that can be used to poll for results. ```rust use mineru_sdk::{MineruClient, ExtractTaskRequest}; #[tokio::main] async fn main() -> Result<(), Box> { let client = MineruClient::new("your-api-token-here".to_string()); let request = ExtractTaskRequest { url: "https://cdn-mineru.openxlab.org.cn/demo/example.pdf".to_string(), is_ocr: false, enable_formula: true, enable_table: true, language: "ch".to_string(), data_id: Some("my-custom-id-123".to_string()), callback: None, seed: None, extra_formats: Some(vec!["docx".to_string(), "html".to_string()]), page_ranges: Some("1-10".to_string()), model_version: "vlm".to_string(), }; match client.create_extract_task(request).await { Ok(response) => { if response.code == 0 { println!("Task created successfully!"); println!("Task ID: {}", response.data.task_id); println!("Trace ID: {}", response.trace_id); } else { println!("API error: {}", response.msg); } } Err(e) => { eprintln!("Request failed: {}", e); } } Ok(()) } ``` ### Query Task Results Retrieves the status and results of a previously created extraction task using its task ID. The response includes task state, progress information, and download URLs when complete. ```rust use mineru_sdk::MineruClient; #[tokio::main] async fn main() -> Result<(), Box> { let client = MineruClient::new("your-api-token-here".to_string()); let task_id = "a90e6ab6-44f3-4554-b459-b62fe4c6b436"; match client.get_task_result(task_id).await { Ok(response) => { if response.code == 0 { let data = &response.data; println!("Task ID: {}", data.task_id); println!("State: {}", data.state); match data.state.as_str() { "done" => { if let Some(url) = &data.full_zip_url { println!("Download URL: {}", url); } } "running" => { if let Some(progress) = &data.extract_progress { println!("Progress: {}/{} pages", progress.extracted_pages, progress.total_pages); println!("Started: {}", progress.start_time); } } "failed" => { if let Some(err) = &data.err_msg { println!("Error: {}", err); } } _ => println!("Status: {}", data.state), } } } Err(e) => { eprintln!("Failed to get task result: {}", e); } } Ok(()) } ``` ### Batch File Upload Processing Requests pre-signed upload URLs for batch file processing. After uploading files to the returned URLs, the system automatically creates extraction tasks. ```rust use mineru_sdk::{MineruClient, BatchFileRequest, BatchFileItem}; #[tokio::main] async fn main() -> Result<(), Box> { let client = MineruClient::new("your-api-token-here".to_string()); let request = BatchFileRequest { files: vec![ BatchFileItem { name: "document1.pdf".to_string(), data_id: Some("doc1".to_string()), }, BatchFileItem { name: "document2.docx".to_string(), data_id: Some("doc2".to_string()), }, ], model_version: "vlm".to_string(), }; match client.batch_file_upload_urls(request).await { Ok(response) => { if response.code == 0 { println!("Batch ID: {}", response.data.batch_id); println!("Upload URLs:"); for (i, url) in response.data.files.iter().enumerate() { println!(" File {}: {}", i + 1, url); // Upload file using PUT request // Example: reqwest::Client::new().put(url).body(file_bytes).send().await?; } println!("\nAfter uploading files, use batch_id to check results"); } } Err(e) => { eprintln!("Failed to get upload URLs: {}", e); } } Ok(()) } ``` ### Batch URL Processing Creates extraction tasks for multiple documents by providing URLs. All files are processed in a single batch operation. ```rust use mineru_sdk::{MineruClient, BatchUrlRequest, BatchUrlItem}; #[tokio::main] async fn main() -> Result<(), Box> { let client = MineruClient::new("your-api-token-here".to_string()); let request = BatchUrlRequest { files: vec![ BatchUrlItem { url: "https://cdn-mineru.openxlab.org.cn/demo/example.pdf".to_string(), data_id: Some("batch-doc-1".to_string()), }, BatchUrlItem { url: "https://example.com/documents/report.docx".to_string(), data_id: Some("batch-doc-2".to_string()), }, ], model_version: "pipeline".to_string(), }; match client.batch_url_upload(request).await { Ok(response) => { if response.code == 0 { println!("Batch extraction started!"); println!("Batch ID: {}", response.data.batch_id); println!("Message: {}", response.msg); println!("Trace ID: {}", response.trace_id); } else { eprintln!("API returned error code: {}", response.code); } } Err(e) => { eprintln!("Batch submission failed: {}", e); } } Ok(()) } ``` ### Get Batch Results Retrieves the status and results for all files in a batch extraction operation using the batch ID. ```rust use mineru_sdk::MineruClient; #[tokio::main] async fn main() -> Result<(), Box> { let client = MineruClient::new("your-api-token-here".to_string()); let batch_id = "2bb2f0ec-a336-4a0a-b61a-241afaf9cc87"; match client.get_batch_results(batch_id).await { Ok(response) => { if response.code == 0 { println!("Batch ID: {}", response.data.batch_id); println!("Total files: {}\n", response.data.extract_result.len()); for (i, result) in response.data.extract_result.iter().enumerate() { println!("File {}:", i + 1); if let Some(name) = &result.file_name { println!(" Name: {}", name); } println!(" State: {}", result.state); if result.state == "done" { if let Some(url) = &result.full_zip_url { println!(" Download: {}", url); } } else if result.state == "running" { if let Some(progress) = &result.extract_progress { println!(" Progress: {}/{} pages", progress.extracted_pages, progress.total_pages); } } else if result.state == "failed" { if let Some(err) = &result.err_msg { println!(" Error: {}", err); } } println!(); } } } Err(e) => { eprintln!("Failed to get batch results: {}", e); } } Ok(()) } ``` ### CLI Usage The included command-line tool provides direct access to all SDK functions for testing and scripting. ```bash # Set API token as environment variable export MINERU_TOKEN="your-api-token-here" # Create a single extraction task mineru-cli extract --url "https://cdn-mineru.openxlab.org.cn/demo/example.pdf" \ --model-version vlm \ --enable-formula \ --enable-table \ --language ch # Check task status and results mineru-cli get-task --task-id "a90e6ab6-44f3-4554-b459-b62fe4c6b436" # Request batch file upload URLs mineru-cli batch-file --name "document.pdf" --model-version pipeline # Create batch URL extraction tasks mineru-cli batch-url --url "https://example.com/document.pdf" --model-version vlm # Get batch processing results mineru-cli get-batch --batch-id "2bb2f0ec-a336-4a0a-b61a-241afaf9cc87" # Pass token directly instead of environment variable mineru-cli --token "your-token" extract --url "https://example.com/file.pdf" ``` ### Error Handling The SDK provides a custom error type that wraps common error scenarios including HTTP errors, JSON serialization issues, and API-level errors. ```rust use mineru_sdk::{MineruClient, MineruError, ExtractTaskRequest}; #[tokio::main] async fn main() { let client = MineruClient::new("your-api-token".to_string()); let request = ExtractTaskRequest { url: "https://example.com/document.pdf".to_string(), is_ocr: false, enable_formula: true, enable_table: true, language: "ch".to_string(), data_id: None, callback: None, seed: None, extra_formats: None, page_ranges: None, model_version: "pipeline".to_string(), }; match client.create_extract_task(request).await { Ok(response) => { // Check API-level status code match response.code { 0 => println!("Success: {}", response.data.task_id), -500 => eprintln!("Parameter error: {}", response.msg), -10001 => eprintln!("Service exception: {}", response.msg), -60005 => eprintln!("File size exceeds 200MB limit"), _ => eprintln!("API error {}: {}", response.code, response.msg), } } Err(MineruError::Http(e)) => { eprintln!("HTTP request failed: {}", e); } Err(MineruError::Json(e)) => { eprintln!("JSON parsing failed: {}", e); } Err(MineruError::Api(msg)) => { eprintln!("API error: {}", msg); } } } ``` ### Polling for Task Completion A common pattern is to poll a task until it reaches a terminal state (done or failed). ```rust use mineru_sdk::{MineruClient, ExtractTaskRequest}; use tokio::time::{sleep, Duration}; #[tokio::main] async fn main() -> Result<(), Box> { let client = MineruClient::new("your-api-token".to_string()); // Create task let request = ExtractTaskRequest { url: "https://cdn-mineru.openxlab.org.cn/demo/example.pdf".to_string(), is_ocr: false, enable_formula: true, enable_table: true, language: "ch".to_string(), data_id: None, callback: None, seed: None, extra_formats: None, page_ranges: None, model_version: "vlm".to_string(), }; let response = client.create_extract_task(request).await?; let task_id = response.data.task_id; println!("Task created: {}", task_id); // Poll until complete loop { sleep(Duration::from_secs(5)).await; let result = client.get_task_result(&task_id).await?; println!("Status: {}", result.data.state); match result.data.state.as_str() { "done" => { println!("Task completed!"); if let Some(url) = result.data.full_zip_url { println!("Download: {}", url); } break; } "failed" => { eprintln!("Task failed: {:?}", result.data.err_msg); break; } "running" => { if let Some(progress) = result.data.extract_progress { println!(" Progress: {}/{}", progress.extracted_pages, progress.total_pages); } } _ => println!(" Waiting..."), } } Ok(()) } ``` ## Summary The MinerU SDK for Rust provides a complete solution for integrating document extraction capabilities into Rust applications. The primary use cases include automated document processing pipelines, batch extraction workflows for large document collections, content management systems that need to extract structured data from uploaded files, and research tools that analyze document content. The SDK supports both synchronous single-file processing and asynchronous batch operations with up to 200 files per batch. Integration patterns typically involve creating tasks asynchronously, polling for completion, and downloading the resulting ZIP files containing extracted content in multiple formats (Markdown, JSON, DOCX, HTML, LaTeX). For production systems, the callback mechanism allows for event-driven architectures where the MinerU service notifies your application when processing completes, eliminating the need for polling. The SDK's type-safe API, comprehensive error handling, and async-first design make it straightforward to build robust document processing systems. The included CLI tool serves both as a reference implementation and a practical utility for testing, debugging, and scripting batch operations.