> ## Documentation Index
> Fetch the complete documentation index at: https://docs.case.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Discovery Search

> Search thousands of documents in seconds

**The problem:** You have 5,000 documents from discovery. Finding the relevant ones takes weeks of manual review.

**The solution:** Upload to a Vault. We OCR, chunk, and index everything. Search by meaning in seconds.

## 1. Create a vault

Vaults are secure containers for your users' documents. Each vault gets automatic OCR, chunking, and vector indexing.

<CodeGroup>
  ```bash title="cURL" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  curl -X POST https://api.case.dev/vault \
    -H "Authorization: Bearer $CASEDEV_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "Case Documents - User 12345",
      "description": "Discovery documents for case review"
    }'
  ```

  ```bash title="CLI" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  casedev vault create --name "Case Documents - User 12345"
  ```

  ```typescript title="Typescript" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  import Casedev from 'casedev';

  const client = new Casedev({ apiKey: process.env.CASEDEV_API_KEY });

  // Create a vault for your user's documents
  const vault = await client.vault.create({
    name: 'Case Documents - User 12345',
    description: 'Discovery documents for case review'
  });

  console.log(`Vault created: ${vault.id}`);
  ```

  ```python title="Python" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  import casedev
  import os

  client = casedev.Casedev(api_key=os.environ['CASEDEV_API_KEY'])

  # Create a vault for your user's documents
  vault = client.vault.create(
      name='Case Documents - User 12345',
      description='Discovery documents for case review'
  )

  print(f'Vault created: {vault.id}')
  ```

  ```go title="Go" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  vault, _ := client.Vault.New(ctx, casedev.VaultNewParams{
  	Name: casedev.F("Case Documents - User 12345"),
  	Description: casedev.F("Discovery documents for case review"),
  })
  fmt.Println(vault.ID)
  ```
</CodeGroup>

## 2. Upload documents

Handle file uploads from your users and trigger automatic processing:

<CodeGroup>
  ```bash title="cURL" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  # 1. Get upload URL
  UPLOAD=$(curl -s -X POST "https://api.case.dev/vault/$VAULT_ID/upload" \
    -H "Authorization: Bearer $CASEDEV_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"filename": "document.pdf", "contentType": "application/pdf"}')

  UPLOAD_URL=$(echo $UPLOAD | jq -r '.uploadUrl')
  OBJECT_ID=$(echo $UPLOAD | jq -r '.objectId')

  # 2. Upload file
  curl -X PUT "$UPLOAD_URL" \
    -H "Content-Type: application/pdf" \
    --data-binary "@document.pdf"

  # 3. Trigger ingestion
  curl -X POST "https://api.case.dev/vault/$VAULT_ID/ingest/$OBJECT_ID" \
    -H "Authorization: Bearer $CASEDEV_API_KEY"
  ```

  ```bash title="CLI" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  casedev vault upload \
    --id $VAULT_ID \
    --filename "document.pdf" \
    --content-type "application/pdf"
  ```

  ```typescript title="Typescript" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  import fs from 'fs';

  async function uploadDocument(vaultId: string, filePath: string) {
    // Get presigned upload URL
    const upload = await client.vault.upload(vaultId, {
      filename: filePath.split('/').pop()!,
      contentType: 'application/pdf'
    });

    // Upload file to S3
    const file = fs.readFileSync(filePath);
    await fetch(upload.uploadUrl, {
      method: 'PUT',
      headers: { 'Content-Type': 'application/pdf' },
      body: file
    });

    // Trigger OCR + embedding pipeline
    await client.vault.ingest(vaultId, upload.objectId);

    return upload.objectId;
  }

  // Process uploads from your user
  const files = fs.readdirSync('./uploads');
  for (const file of files) {
    await uploadDocument(vault.id, `./uploads/${file}`);
    console.log(`Processed: ${file}`);
  }
  ```

  ```python title="Python" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  import os
  import requests

  def upload_document(vault_id: str, file_path: str) -> str:
      # Get presigned upload URL
      upload = client.vault.upload(vault_id,
          filename=os.path.basename(file_path),
          content_type='application/pdf'
      )

      # Upload file to S3
      with open(file_path, 'rb') as f:
          requests.put(upload.upload_url, data=f,
              headers={'Content-Type': 'application/pdf'})

      # Trigger OCR + embedding pipeline
      client.vault.ingest(upload.object_id, id=vault_id)

      return upload.object_id

  # Process uploads from your user
  for file in os.listdir('./uploads'):
      upload_document(vault.id, f'./uploads/{file}')
      print(f'Processed: {file}')
  ```

  ```go title="Go" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  upload, _ := client.Vault.Upload(ctx, vaultID, casedev.VaultUploadParams{
  	Filename:    casedev.F("document.pdf"),
  	ContentType: casedev.F("application/pdf"),
  })
  // PUT file to upload.UploadURL via net/http
  fmt.Println(upload.ObjectID)
  ```
</CodeGroup>

## 3. Search by meaning

Enable your users to search by meaning, not just keywords:

<CodeGroup>
  ```bash title="cURL" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  curl -X POST "https://api.case.dev/vault/$VAULT_ID/search" \
    -H "Authorization: Bearer $CASEDEV_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "query": "communications about equipment failure",
      "method": "hybrid",
      "topK": 10
    }'
  ```

  ```bash title="CLI" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  casedev vault search \
    --id $VAULT_ID \
    --query "search query"
  ```

  ```typescript title="Typescript" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  // In your search endpoint or UI handler
  const results = await client.vault.search(vault.id, {
    query: userQuery, // e.g., "communications about equipment failure"
    method: 'hybrid',
    topK: 10
  });

  // Return results to your user
  for (const chunk of results.chunks) {
    console.log(`📄 ${chunk.filename} (score: ${chunk.hybridScore.toFixed(2)})`);
    console.log(`"${chunk.text.substring(0, 200)}..."`);
  }
  ```

  ```python title="Python" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  # In your search endpoint or UI handler
  results = client.vault.search(vault.id,
      query=user_query,  # e.g., "communications about equipment failure"
      method='hybrid',
      top_k=10
  )

  # Return results to your user
  for chunk in results.chunks:
      print(f'📄 {chunk.filename} (score: {chunk.hybrid_score:.2f})')
      print(f'"{chunk.text[:200]}..."')
  ```

  ```go title="Go" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  results, _ := client.Vault.Search(ctx, vaultID, casedev.VaultSearchParams{
  	Query: casedev.F("search query"),
  	Method: casedev.F(casedev.VaultSearchParamsMethodHybrid),
  })
  for _, chunk := range results.Chunks {
  	fmt.Println(chunk.Text)
  }
  ```
</CodeGroup>

## 4. Summarize findings

Enhance results with AI-generated summaries for your users:

<CodeGroup>
  ```bash title="cURL" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  curl -X POST https://api.case.dev/llm/v1/chat/completions \
    -H "Authorization: Bearer $CASEDEV_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "anthropic/claude-sonnet-4.5",
      "messages": [
        {"role": "system", "content": "Summarize these search results concisely."},
        {"role": "user", "content": "User searched for: [QUERY]\n\nResults:\n\n[SEARCH RESULTS]"}
      ],
      "max_tokens": 500
    }'
  ```

  ```bash title="CLI" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  casedev llm:v1:chat create-completion \
    --model anthropic/claude-sonnet-4.5 \
    --message '{role: system, content: "Summarize these search results concisely. Highlight the most relevant findings."}' \
    --message '{role: user, content: "User searched for: <query>\n\nResults:\n\n<search results>"}' \
    --max-tokens 500
  ```

  ```typescript title="Typescript" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  const context = results.chunks.map(c => c.text).join('\n\n---\n\n');

  const summary = await client.llm.v1.chat.createCompletion({
    model: 'anthropic/claude-sonnet-4.5',
    messages: [
      {
        role: 'system',
        content: 'Summarize these search results concisely. Highlight the most relevant findings.'
      },
      {
        role: 'user',
        content: `User searched for: "${userQuery}"\n\nResults:\n\n${context}`
      }
    ],
    max_tokens: 500
  });

  // Return summary along with search results
  console.log(summary.choices[0].message.content);
  ```

  ```python title="Python" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  context = '\n\n---\n\n'.join([c.text for c in results.chunks])

  summary = client.llm.v1.chat.create_completion(
      model='anthropic/claude-sonnet-4.5',
      messages=[
          {
              'role': 'system',
              'content': 'Summarize these search results concisely. Highlight the most relevant findings.'
          },
          {
              'role': 'user',
              'content': f'User searched for: "{user_query}"\n\nResults:\n\n{context}'
          }
      ],
      max_tokens=500
  )

  # Return summary along with search results
  print(summary.choices[0].message.content)
  ```

  ```go title="Go" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  // Summarize search results for your user
  resp, _ := client.Llm.V1.Chat.NewCompletion(ctx, casedev.LlmV1ChatNewCompletionParams{
  	Model: casedev.F("anthropic/claude-sonnet-4.5"),
  	Messages: casedev.F([]casedev.LlmV1ChatNewCompletionParamsMessage{
  		{
  			Role:    casedev.F(casedev.LlmV1ChatNewCompletionParamsMessagesRoleSystem),
  			Content: casedev.F("Summarize these search results concisely. Highlight the most relevant findings."),
  		},
  		{
  			Role:    casedev.F(casedev.LlmV1ChatNewCompletionParamsMessagesRoleUser),
  			Content: casedev.F("User searched for: " + query + "\n\nResults:\n\n" + searchResultsText),
  		},
  	}),
  	MaxTokens: casedev.F(int64(500)),
  })
  fmt.Println(resp.Choices[0].Message.Content)
  ```
</CodeGroup>

<Info>
  **Time saved:** What used to take weeks of manual review now takes minutes. The AI finds relevant passages even when documents use different terminology.
</Info>
