Official Go SDK for LeapOCR - Transform documents into structured data using AI-powered OCR.
LeapOCR provides enterprise-grade document processing with AI-powered data extraction. This SDK offers a Go-native interface for seamless integration into your applications.
go get github.com/leapocr/leapocr-go- Go 1.21 or higher
- LeapOCR API key (sign up here)
package main
import (
"context"
"fmt"
"log"
"os"
"github.com/leapocr/leapocr-go"
)
func main() {
// Initialize the SDK with your API key
client, err := ocr.New(os.Getenv("LEAPOCR_API_KEY"))
if err != nil {
log.Fatal(err)
}
ctx := context.Background()
// Submit a document for processing
job, err := client.ProcessURL(ctx,
"https://example.com/document.pdf",
ocr.WithFormat(ocr.FormatStructured),
ocr.WithModel(ocr.ModelStandardV2),
ocr.WithSchema(map[string]interface{}{
"type": "object",
"properties": map[string]interface{}{
"title": map[string]interface{}{"type": "string"},
},
"required": []interface{}{"title"},
}),
)
if err != nil {
log.Fatal(err)
}
// Wait for processing to complete
result, err := client.WaitUntilDone(ctx, job.ID)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Extracted data: %+v\n", result.Data)
// Optional: Delete the job to remove sensitive data
if err := client.DeleteJob(ctx, job.ID); err != nil {
log.Printf("Failed to delete job: %v", err)
}
}- Idiomatic Go API - Clean, type-safe interface following Go best practices
- Multiple Processing Formats - Structured data extraction or markdown output
- Flexible Model Selection - Choose from standard, pro, or custom AI models
- Custom Schema Support - Define extraction schemas for your specific use case
- Built-in Retry Logic - Automatic handling of transient failures
- Context Support - Full context.Context integration for timeouts and cancellation
- Direct File Upload - Efficient multipart uploads for local files
- Webhook Verification Helper - Verify incoming
X-R2-Signatureheaders with the raw request body
Use WithModel() to specify a model, or WithModelString() for custom models. Defaults to ModelStandardV2.
ctx := context.Background()
job, err := client.ProcessURL(ctx,
"https://example.com/invoice.pdf",
ocr.WithFormat(ocr.FormatStructured),
ocr.WithModel(ocr.ModelStandardV2),
ocr.WithSchema(map[string]interface{}{
"type": "object",
"properties": map[string]interface{}{
"invoice_number": map[string]interface{}{"type": "string"},
"invoice_date": map[string]interface{}{"type": "string"},
"total_amount": map[string]interface{}{"type": "number"},
},
"required": []interface{}{"invoice_number", "total_amount"},
}),
)
if err != nil {
log.Fatal(err)
}
result, err := client.WaitUntilDone(ctx, job.ID)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Processing completed in %v\n", result.Duration)
fmt.Printf("Credits used: %d\n", result.Credits)
fmt.Printf("Data: %+v\n", result.Data)file, err := os.Open("invoice.pdf")
if err != nil {
log.Fatal(err)
}
defer file.Close()
job, err := client.ProcessFile(ctx, file, "invoice.pdf",
ocr.WithFormat(ocr.FormatStructured),
ocr.WithModel(ocr.ModelProV2),
ocr.WithSchema(map[string]interface{}{
"invoice_number": "string",
"total_amount": "number",
"invoice_date": "string",
"vendor_name": "string",
}),
)Use pre-configured templates for common document types:
// Use an existing template by slug
job, err := client.ProcessFile(ctx, file, "invoice.pdf",
ocr.WithTemplateSlug("invoice-template"),
)Define custom extraction schemas for specific use cases:
schema := map[string]interface{}{
"type": "object",
"properties": map[string]interface{}{
"patient_name": map[string]interface{}{"type": "string"},
"date_of_birth": map[string]interface{}{"type": "string"},
"medications": map[string]interface{}{
"type": "array",
"items": map[string]interface{}{
"type": "object",
"properties": map[string]interface{}{
"name": map[string]interface{}{"type": "string"},
"dosage": map[string]interface{}{"type": "string"},
},
},
},
},
}
job, err := client.ProcessFile(ctx, file, "medical-record.pdf",
ocr.WithFormat(ocr.FormatStructured),
ocr.WithSchema(schema),
)| Format | Description | Use Case |
|---|---|---|
FormatStructured |
Single JSON object | Extract specific fields across entire document |
FormatMarkdown |
Text per page | Convert document to readable text |
// Poll for status updates
ticker := time.NewTicker(2 * time.Second)
defer ticker.Stop()
for {
status, err := client.GetJobStatus(ctx, job.ID)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Status: %s (%.1f%% complete)\n", status.Status, status.Progress)
if status.Status == "completed" {
result, _ := client.GetJobResult(ctx, job.ID)
fmt.Println("Processing complete!")
break
}
<-ticker.C
}Delete jobs to remove sensitive data and free up storage. Jobs and their associated files are automatically deleted after 7 days, but you can delete them immediately after processing:
// Process and delete immediately after retrieving results
result, err := client.WaitUntilDone(ctx, job.ID)
if err != nil {
log.Fatal(err)
}
// Use the result
fmt.Printf("Extracted data: %+v\n", result.Data)
// Delete the job (redacts content and marks as deleted)
err = client.DeleteJob(ctx, job.ID)
if err != nil {
log.Printf("Failed to delete job: %v", err)
}For more examples, see the examples/ directory.
config := &ocr.Config{
APIKey: "your-api-key",
BaseURL: "https://api.leapocr.com",
HTTPClient: &http.Client{Timeout: 60 * time.Second},
UserAgent: "my-app/1.0",
Timeout: 30 * time.Second,
}
client, err := ocr.NewSDK(config)export LEAPOCR_API_KEY="your-api-key"
export OCR_BASE_URL="https://api.leapocr.com" # optionalThe SDK provides typed errors for robust error handling:
result, err := client.WaitUntilDone(ctx, job.ID)
if err != nil {
if sdkErr, ok := err.(*ocr.SDKError); ok {
switch sdkErr.Type {
case ocr.ErrorTypeAuth:
log.Fatal("Authentication failed - check your API key")
case ocr.ErrorTypeValidation:
log.Printf("Validation error: %s", sdkErr.Message)
case ocr.ErrorTypeNetwork:
if sdkErr.IsRetryable() {
// Retry the operation
}
case ocr.ErrorTypeProcessing:
log.Printf("Processing failed: %s", sdkErr.Message)
}
}
}ErrorTypeInvalidConfig- Configuration errorsErrorTypeAuth- Authentication failuresErrorTypeValidation- Input validation errorsErrorTypeNetwork- Network/connectivity issues (retryable)ErrorTypeProcessing- Document processing errorsErrorTypeTimeout- Operation timeouts
Use VerifyWebhookSignature with the raw request body exactly as received. LeapOCR sends customer webhooks with X-Webhook-Signature and X-Webhook-Timestamp, and signs timestamp + "." + rawBody with your webhook secret.
package main
import (
"encoding/json"
"io"
"net/http"
"os"
ocr "github.com/leapocr/leapocr-go"
)
func webhookHandler(w http.ResponseWriter, r *http.Request) {
body, err := io.ReadAll(r.Body)
if err != nil {
http.Error(w, "failed to read request body", http.StatusBadRequest)
return
}
if !ocr.VerifyWebhookSignature(
body,
r.Header.Get("X-Webhook-Signature"),
r.Header.Get("X-Webhook-Timestamp"),
os.Getenv("LEAPOCR_WEBHOOK_SECRET"),
) {
http.Error(w, "invalid signature", http.StatusUnauthorized)
return
}
var payload map[string]any
if err := json.Unmarshal(body, &payload); err != nil {
http.Error(w, "invalid JSON", http.StatusBadRequest)
return
}
w.WriteHeader(http.StatusOK)
}Do not verify against re-serialized JSON. Use the original body bytes and the timestamp header from the HTTP request.
Full API documentation is available at pkg.go.dev/github.com/leapocr/leapocr-go.
// Initialize SDK
New(apiKey string) (*SDK, error)
NewSDK(config *Config) (*SDK, error)
// Process documents
ProcessURL(ctx context.Context, url string, opts ...ProcessingOption) (*Job, error)
ProcessFile(ctx context.Context, file io.Reader, filename string, opts ...ProcessingOption) (*Job, error)
// Job management
GetJobStatus(ctx context.Context, jobID string) (*JobStatus, error)
GetJobResult(ctx context.Context, jobID string) (*OCRResult, error)
WaitUntilDone(ctx context.Context, jobID string) (*OCRResult, error)
DeleteJob(ctx context.Context, jobID string) errorWithFormat(format Format) // Set output format
WithModel(model Model) // Set OCR model
WithModelString(model string) // Set custom model
WithSchema(schema map[string]interface{}) // Define extraction schema
WithInstructions(instructions string) // Add processing instructions
WithTemplateSlug(templateSlug string) // Use existing template- Go 1.21+
- golangci-lint (for linting)
- OpenAPI Generator (for code generation)
# Clone the repository
git clone https://github.com/leapocr/leapocr-go.git
cd leapocr-go
# Install dependencies
make install
# Run tests
make testmake build # Build the SDK
make test # Run unit tests
make test-coverage # Generate coverage report
make test-integration # Run integration tests (requires API key)
make lint # Run linters
make format # Format code
make examples # Build examplesThe SDK is partially generated from the OpenAPI specification:
make generate # Regenerate client from OpenAPI spec
make clean # Remove generated filesWe welcome contributions! Please follow these guidelines:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'feat: add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
See CONTRIBUTING.md for detailed guidelines.
This project is licensed under the MIT License - see the LICENSE file for details.
- Documentation: docs.leapocr.com
- API Reference: pkg.go.dev/github.com/leapocr/leapocr-go
- Issues: GitHub Issues
- Website: leapocr.com
Version: 0.0.5