Three steps to make a document searchable:
- Create a vault (once per case)
- Upload your file
- Process it (we call this “ingest”)
After processing, the document is fully searchable by meaning.
Step 1: Create a vault
A vault is a container for your documents. Create one per case or matter.
import Casedev from 'casedev';
const client = new Casedev({ apiKey: 'sk_case_YOUR_API_KEY' });
const vault = await client.vault.create({
name: 'Smith v. Hospital 2024',
description: 'Discovery and depositions'
});
console.log(vault.id); // Save this—you'll use it for everything
{
"id": "vault_abc123xyz",
"name": "Smith v. Hospital 2024",
"description": "Discovery and depositions",
"createdAt": "2025-01-15T10:30:00Z"
}
Step 2: Upload a file
Uploading is two parts: get a secure URL, then PUT your file to it.
// Get an upload URL
const upload = await client.vault.upload(vault.id, {
filename: 'deposition-johnson.pdf',
contentType: 'application/pdf',
metadata: {
witness: 'Dr. Sarah Johnson',
date: '2024-11-04'
}
});
// Upload the file directly to S3
await fetch(upload.uploadUrl, {
method: 'PUT',
headers: { 'Content-Type': 'application/pdf' },
body: fileBuffer
});
console.log(upload.objectId); // Use this for the next step
Why two steps?
Security and speed. Your file goes directly to encrypted storage—we’re never a bottleneck for large uploads.
Supported file types
| Type | Extensions |
|---|
| Documents | .pdf, .doc, .docx, .txt, .rtf, .xml |
| Images | .png, .jpg, .jpeg, .tiff, .bmp |
| Audio | .mp3, .m4a, .wav, .flac, .ogg |
| Video | .mp4, .webm, .mov |
| Court recordings | .ftr |
Step 3: Process the file
This is where the magic happens. Processing (we call it “ingest”) does different things based on file type:
| File type | What we do |
|---|
| Scanned PDF, images | OCR to extract text |
| Audio, video | Transcribe with speaker labels |
| FTR recordings | Convert → Transcribe |
| Digital PDF, DOCX, TXT, RTF, XML | Extract text directly |
Then for all files: split into chunks, convert to vectors, index for search.
POST /vault/:vaultId/ingest/:objectId
const result = await client.vault.ingest(vault.id, upload.objectId);
console.log(result.status); // 'processing'
Processing time
| File | Time |
|---|
| 10-page clean PDF | ~10 seconds |
| 50-page scanned PDF | ~2-3 minutes |
| 300-page scanned PDF | ~12-15 minutes |
| 1-hour audio/video | ~5-10 minutes |
Processing is async—you get an immediate response while we work in the background.
Check status
// Poll until complete
let obj = await client.vault.objects.retrieve(vault.id, objectId);
while (obj.ingestionStatus === 'processing') {
await new Promise(r => setTimeout(r, 5000));
obj = await client.vault.objects.retrieve(vault.id, objectId);
}
if (obj.ingestionStatus === 'completed') {
console.log('Ready to search!');
}
Complete example
Upload an entire folder of discovery documents:
import Casedev from 'casedev';
import fs from 'fs';
import path from 'path';
const client = new Casedev({ apiKey: process.env.CASEDEV_API_KEY });
async function uploadDiscovery(folderPath: string) {
// 1. Create vault
const vault = await client.vault.create({
name: 'Matter 2024-1234 Discovery'
});
// 2. Upload each file
const files = fs.readdirSync(folderPath);
for (const file of files) {
const filePath = path.join(folderPath, file);
if (!fs.statSync(filePath).isFile()) continue;
// Get upload URL
const upload = await client.vault.upload(vault.id, {
filename: file,
contentType: 'application/pdf'
});
// Upload to S3
await fetch(upload.uploadUrl, {
method: 'PUT',
body: fs.readFileSync(filePath)
});
// Process
await client.vault.ingest(vault.id, upload.objectId);
console.log(`✓ ${file}`);
}
console.log(`\nVault ready: ${vault.id}`);
return vault.id;
}
uploadDiscovery('./discovery_documents');
Metadata matters. Add metadata like witness, document_type, or date when uploading—you can filter search results by these fields later.
Next: Search your documents
Now that your documents are processed, learn how to search them →