Getting Started
Use the client SDK to classify documents with natural-language rules, including file uploads, job polling, and reading results.
This guide shows how to classify documents using the SDK. You will:
- Create classification rules
- Upload files
- Submit a classify job
- Read predictions (type, confidence, reasoning)
The SDK is available in llama-parse-py, llama-parse-ts, llama-parse-go, and llama-parse-java, plus the llama-parse-cli command-line tool.
First, get an API key and record it for safe keeping.
You can set this as an environment variable LLAMA_CLOUD_API_KEY or pass it directly to the SDK at runtime.
Then, install dependencies:
pip install llama-cloud>=2.8npm install @llamaindex/llama-cloudgo get github.com/run-llama/llama-parse-goimplementation("ai.llamaindex:llama-cloud:1.3.0")go install github.com/run-llama/llama-parse-cli/cmd/llp@latestQuick start
Section titled “Quick start”Using the classify API consists of a few main steps:
- Upload a file and get its ID
- Create a classify job with your rules, passing that ID as
file_input - Wait for the job to finish
- Read the result
file_input also accepts a parse job ID, so a document you have already parsed can be classified without uploading or re-parsing it.
The SDK provides a convenience method that handles all of these steps in one call:
import osfrom llama_cloud import LlamaCloud, AsyncLlamaCloud
# For async usage, use `AsyncLlamaCloud()`client = LlamaCloud(api_key=os.environ["LLAMA_CLOUD_API_KEY"])
# Upload a filefile_obj = client.files.create(file="/path/to/doc1.pdf", purpose="classify")
# Classify and wait for completionjob = client.classify.run( file_input=file_obj.id, configuration={ "rules": [ { "type": "invoice", "description": "Documents that contain an invoice number, invoice date, bill-to section, and line items with totals.", }, { "type": "receipt", "description": "Short purchase receipts, typically from POS systems, with merchant, items and total, often a single page.", }, ], "parsing_configuration": { "lang": "en", "max_pages": 5, # optional, parse at most 5 pages # "target_pages": "1,3", # optional, parse only specific pages (1-based) }, },)
# `run` raises PollingError if the job fails, so reaching here means it succeededprint(f"Classified type: {job.result.type}")print(f"Confidence: {job.result.confidence}")print(f"Reasoning: {job.result.reasoning}")import LlamaCloud from '@llamaindex/llama-cloud';import fs from 'fs';
const client = new LlamaCloud({ apiKey: process.env.LLAMA_CLOUD_API_KEY });
// Upload a fileconst fileObj = await client.files.create({ file: fs.createReadStream('/path/to/doc1.pdf'), purpose: "classify",});
// Classify and wait for completionconst job = await client.classify.run({ file_input: fileObj.id, configuration: { rules: [ { type: 'invoice', description: 'Documents that contain an invoice number, invoice date, bill-to section, and line items with totals.', }, { type: 'receipt', description: 'Short purchase receipts, typically from POS systems, with merchant, items and total, often a single page.', }, ], parsing_configuration: { lang: 'en', max_pages: 5, // target_pages: "1,3", // Optional: specific pages (1-based) }, },});
// `run` throws if the job fails, so reaching here means it succeededconsole.log(`Classified type: ${job.result!.type}`);console.log(`Confidence: ${job.result!.confidence}`);console.log(`Reasoning: ${job.result!.reasoning}`);package main
import ( "context" "fmt" "log" "os" "time"
llamacloud "github.com/run-llama/llama-parse-go")
func main() { ctx := context.Background() client := llamacloud.NewClient()
// Upload a file f, err := os.Open("/path/to/doc1.pdf") if err != nil { log.Fatal(err) } defer f.Close()
fileObj, err := client.Files.New(ctx, llamacloud.FileNewParams{ File: f, Purpose: "classify", }) if err != nil { log.Fatal(err) }
// Create a classify job job, err := client.Classify.New(ctx, llamacloud.ClassifyNewParams{ ClassifyCreateRequest: llamacloud.ClassifyCreateRequestParam{ FileInput: llamacloud.String(fileObj.ID), Configuration: llamacloud.ClassifyConfigurationParam{ Rules: []llamacloud.ClassifyConfigurationRuleParam{ { Type: "invoice", Description: "Documents that contain an invoice number, invoice date, bill-to section, and line items with totals.", }, { Type: "receipt", Description: "Short purchase receipts, typically from POS systems, with merchant, items and total, often a single page.", }, }, ParsingConfiguration: llamacloud.ClassifyConfigurationParsingConfigurationParam{ Lang: llamacloud.String("en"), MaxPages: llamacloud.Int(5), // optional, parse at most 5 pages // TargetPages: llamacloud.String("1,3"), // optional, parse only specific pages (1-based) }, }, }, }) if err != nil { log.Fatal(err) }
// Poll until the job reaches a terminal state result, err := client.Classify.Get(ctx, job.ID, llamacloud.ClassifyGetParams{}) if err != nil { log.Fatal(err) } for result.Status == llamacloud.ClassifyGetResponseStatusPending || result.Status == llamacloud.ClassifyGetResponseStatusRunning { time.Sleep(2 * time.Second) result, err = client.Classify.Get(ctx, job.ID, llamacloud.ClassifyGetParams{}) if err != nil { log.Fatal(err) } }
if !result.JSON.Result.Valid() { log.Fatalf("Classification failed: %s", result.ErrorMessage) } fmt.Printf("Classified type: %s\n", result.Result.Type) fmt.Printf("Confidence: %v\n", result.Result.Confidence) fmt.Printf("Reasoning: %s\n", result.Result.Reasoning)}import ai.llamaindex.llamacloud.client.LlamaCloudClient;import ai.llamaindex.llamacloud.client.okhttp.LlamaCloudOkHttpClient;import ai.llamaindex.llamacloud.models.classify.ClassifyConfiguration;import ai.llamaindex.llamacloud.models.classify.ClassifyCreateRequest;import ai.llamaindex.llamacloud.models.classify.ClassifyCreateResponse;import ai.llamaindex.llamacloud.models.classify.ClassifyGetResponse;import ai.llamaindex.llamacloud.models.files.FileCreateParams;import ai.llamaindex.llamacloud.models.files.FileCreateResponse;import java.nio.file.Paths;import java.util.Arrays;
public class ClassifyQuickStart { public static void main(String[] args) throws Exception { LlamaCloudClient client = LlamaCloudOkHttpClient.fromEnv();
// Upload a file FileCreateResponse fileObj = client.files().create( FileCreateParams.builder() .file(Paths.get("/path/to/doc1.pdf")) .purpose("classify") .build());
// Create a classify job ClassifyCreateResponse job = client.classify().create( ClassifyCreateRequest.builder() .fileInput(fileObj.id()) .configuration(ClassifyConfiguration.builder() .rules(Arrays.asList( ClassifyConfiguration.Rule.builder() .type("invoice") .description("Documents that contain an invoice number, invoice date, bill-to section, and line items with totals.") .build(), ClassifyConfiguration.Rule.builder() .type("receipt") .description("Short purchase receipts, typically from POS systems, with merchant, items and total, often a single page.") .build())) .parsingConfiguration(ClassifyConfiguration.ParsingConfiguration.builder() .lang("en") .maxPages(5L) // optional, parse at most 5 pages // .targetPages("1,3") // optional, parse only specific pages (1-based) .build()) .build()) .build());
// Poll until the job reaches a terminal state ClassifyGetResponse result = client.classify().get(job.id()); while (result.status().equals(ClassifyGetResponse.Status.PENDING) || result.status().equals(ClassifyGetResponse.Status.RUNNING)) { Thread.sleep(2000); result = client.classify().get(job.id()); }
if (!result.result().isPresent()) { System.out.println("Classification failed: " + result.errorMessage().orElse("")); } else { System.out.println("Classified type: " + result.result().get().type().orElse("")); System.out.println("Confidence: " + result.result().get().confidence()); System.out.println("Reasoning: " + result.result().get().reasoning()); } }}export LLAMA_CLOUD_API_KEY="llx-..."
# Upload a fileFILE_ID=$(llp files create --file /path/to/doc1.pdf --purpose classify | jq -r '.id')
# Create a classify jobJOB_ID=$(llp classify create \ --file-input "$FILE_ID" \ --configuration '{rules: [{type: invoice, description: "Documents that contain an invoice number, invoice date, bill-to section, and line items with totals."}, {type: receipt, description: "Short purchase receipts, typically from POS systems, with merchant, items and total, often a single page."}], parsing_configuration: {lang: en, max_pages: 5}}' \ | jq -r '.id')
# Poll until the job reaches a terminal statewhile true; do RESULT=$(llp classify get "$JOB_ID") STATUS=$(echo "$RESULT" | jq -r '.status') [ "$STATUS" = "PENDING" ] || [ "$STATUS" = "RUNNING" ] || break sleep 2done
echo "$RESULT" | jq -r '.result.type, .result.confidence, .result.reasoning'Step-by-step (manual polling)
Section titled “Step-by-step (manual polling)”You can also run each step individually if you need more control:
import osimport timefrom llama_cloud import LlamaCloud
client = LlamaCloud(api_key=os.environ["LLAMA_CLOUD_API_KEY"])
# Upload a filefile_obj = client.files.create(file="/path/to/doc1.pdf", purpose="classify")
# Create a classify jobjob = client.classify.create( file_input=file_obj.id, configuration={ "rules": [ { "type": "invoice", "description": "Documents that contain an invoice number, invoice date, bill-to section, and line items with totals.", }, { "type": "receipt", "description": "Short purchase receipts, typically from POS systems, with merchant, items and total, often a single page.", }, ], },)
# Poll until the job reaches a terminal stateresult = client.classify.get(job.id)while result.status in ("PENDING", "RUNNING"): time.sleep(2) result = client.classify.get(job.id)
# `get` returns the result inline once the job is COMPLETEDif result.result is None: print(f"Classification failed: {result.error_message}")else: print(f"Classified type: {result.result.type}") print(f"Confidence: {result.result.confidence}") print(f"Reasoning: {result.result.reasoning}")import LlamaCloud from '@llamaindex/llama-cloud';import fs from 'fs';
const client = new LlamaCloud({ apiKey: process.env.LLAMA_CLOUD_API_KEY });
// Upload a fileconst fileObj = await client.files.create({ file: fs.createReadStream('/path/to/doc1.pdf'), purpose: "classify",});
// Create a classify jobconst job = await client.classify.create({ file_input: fileObj.id, configuration: { rules: [ { type: 'invoice', description: 'Documents that contain an invoice number, invoice date, bill-to section, and line items with totals.', }, { type: 'receipt', description: 'Short purchase receipts, typically from POS systems, with merchant, items and total, often a single page.', }, ], },});
// Poll until the job reaches a terminal statelet result = await client.classify.get(job.id);while (result.status === 'PENDING' || result.status === 'RUNNING') { await new Promise((r) => setTimeout(r, 2000)); result = await client.classify.get(job.id);}
// `get` returns the result inline once the job is COMPLETEDif (!result.result) { console.log(`Classification failed: ${result.error_message}`);} else { console.log(`Classified type: ${result.result.type}`); console.log(`Confidence: ${result.result.confidence}`); console.log(`Reasoning: ${result.result.reasoning}`);}package main
import ( "context" "fmt" "log" "os" "time"
llamacloud "github.com/run-llama/llama-parse-go")
func main() { ctx := context.Background() client := llamacloud.NewClient()
// Upload a file f, err := os.Open("/path/to/doc1.pdf") if err != nil { log.Fatal(err) } defer f.Close()
fileObj, err := client.Files.New(ctx, llamacloud.FileNewParams{ File: f, Purpose: "classify", }) if err != nil { log.Fatal(err) }
// Create a classify job job, err := client.Classify.New(ctx, llamacloud.ClassifyNewParams{ ClassifyCreateRequest: llamacloud.ClassifyCreateRequestParam{ FileInput: llamacloud.String(fileObj.ID), Configuration: llamacloud.ClassifyConfigurationParam{ Rules: []llamacloud.ClassifyConfigurationRuleParam{ { Type: "invoice", Description: "Documents that contain an invoice number, invoice date, bill-to section, and line items with totals.", }, { Type: "receipt", Description: "Short purchase receipts, typically from POS systems, with merchant, items and total, often a single page.", }, }, }, }, }) if err != nil { log.Fatal(err) }
// Poll until the job reaches a terminal state result, err := client.Classify.Get(ctx, job.ID, llamacloud.ClassifyGetParams{}) if err != nil { log.Fatal(err) } for result.Status == llamacloud.ClassifyGetResponseStatusPending || result.Status == llamacloud.ClassifyGetResponseStatusRunning { time.Sleep(2 * time.Second) result, err = client.Classify.Get(ctx, job.ID, llamacloud.ClassifyGetParams{}) if err != nil { log.Fatal(err) } }
// `Get` returns the result inline once the job is COMPLETED if !result.JSON.Result.Valid() { fmt.Printf("Classification failed: %s\n", result.ErrorMessage) } else { fmt.Printf("Classified type: %s\n", result.Result.Type) fmt.Printf("Confidence: %v\n", result.Result.Confidence) fmt.Printf("Reasoning: %s\n", result.Result.Reasoning) }}import ai.llamaindex.llamacloud.client.LlamaCloudClient;import ai.llamaindex.llamacloud.client.okhttp.LlamaCloudOkHttpClient;import ai.llamaindex.llamacloud.models.classify.ClassifyConfiguration;import ai.llamaindex.llamacloud.models.classify.ClassifyCreateRequest;import ai.llamaindex.llamacloud.models.classify.ClassifyCreateResponse;import ai.llamaindex.llamacloud.models.classify.ClassifyGetResponse;import ai.llamaindex.llamacloud.models.files.FileCreateParams;import ai.llamaindex.llamacloud.models.files.FileCreateResponse;import java.nio.file.Paths;import java.util.Arrays;
public class ClassifyStepByStep { public static void main(String[] args) throws Exception { LlamaCloudClient client = LlamaCloudOkHttpClient.fromEnv();
// Upload a file FileCreateResponse fileObj = client.files().create( FileCreateParams.builder() .file(Paths.get("/path/to/doc1.pdf")) .purpose("classify") .build());
// Create a classify job ClassifyCreateResponse job = client.classify().create( ClassifyCreateRequest.builder() .fileInput(fileObj.id()) .configuration(ClassifyConfiguration.builder() .rules(Arrays.asList( ClassifyConfiguration.Rule.builder() .type("invoice") .description("Documents that contain an invoice number, invoice date, bill-to section, and line items with totals.") .build(), ClassifyConfiguration.Rule.builder() .type("receipt") .description("Short purchase receipts, typically from POS systems, with merchant, items and total, often a single page.") .build())) .build()) .build());
// Poll until the job reaches a terminal state ClassifyGetResponse result = client.classify().get(job.id()); while (result.status().equals(ClassifyGetResponse.Status.PENDING) || result.status().equals(ClassifyGetResponse.Status.RUNNING)) { Thread.sleep(2000); result = client.classify().get(job.id()); }
// `get` returns the result inline once the job is COMPLETED if (!result.result().isPresent()) { System.out.println("Classification failed: " + result.errorMessage().orElse("")); } else { System.out.println("Classified type: " + result.result().get().type().orElse("")); System.out.println("Confidence: " + result.result().get().confidence()); System.out.println("Reasoning: " + result.result().get().reasoning()); } }}export LLAMA_CLOUD_API_KEY="llx-..."
# Upload a fileFILE_ID=$(llp files create --file /path/to/doc1.pdf --purpose classify | jq -r '.id')
# Create a classify jobJOB_ID=$(llp classify create \ --file-input "$FILE_ID" \ --configuration.rules '[{type: invoice, description: "Documents that contain an invoice number, invoice date, bill-to section, and line items with totals."}, {type: receipt, description: "Short purchase receipts, typically from POS systems, with merchant, items and total, often a single page."}]' \ | jq -r '.id')
# Poll until the job reaches a terminal statewhile true; do RESULT=$(llp classify get "$JOB_ID") STATUS=$(echo "$RESULT" | jq -r '.status') [ "$STATUS" = "PENDING" ] || [ "$STATUS" = "RUNNING" ] || break sleep 2done
# `get` returns the result inline once the job is COMPLETEDif [ "$(echo "$RESULT" | jq -r '.result')" = "null" ]; then echo "Classification failed: $(echo "$RESULT" | jq -r '.error_message')"else echo "$RESULT" | jq -r '.result.type, .result.confidence, .result.reasoning'fi- Each rule requires a
type(the label to assign) and adescription(natural-language description of what content matches). Rule types must be unique within a configuration. parsing_configurationis optional. Uselang,max_pages, ortarget_pagesto control how documents are parsed before classification.target_pagesis a comma-separated string of 1-based page numbers or ranges (e.g.,"1,3,5-7").- Each job classifies a single document. To classify several files, submit one job per file.
- A failed or cancelled job has no
result— checkstatusbefore reading it, and useerror_messagefor the reason. - Job statuses:
PENDING,RUNNING,COMPLETED,FAILED,CANCELLED. - Instead of passing
configurationinline, you can pass aconfiguration_idto reuse a saved configuration.
Tips for writing good rules
Section titled “Tips for writing good rules”- Be specific about content features that distinguish the type.
- Include key fields the document usually contains (e.g., invoice number, total amount).
- Add multiple rules when needed to cover distinct patterns.
- Start simple, test on a small set, then refine.