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

# Get Started with the Kodexa SDK

> Get started with the Kodexa Document SDK: create, load, manipulate, and save Kodexa Documents using essential operations for document processing apps.

This guide covers the essential operations for working with Kodexa Documents: creating, loading, manipulating, and saving documents.

## Installation

<CodeGroup>
  ```bash Python theme={null}
  pip install kodexa-document
  ```

  ```bash TypeScript theme={null}
  npm install @kodexa-ai/document-wasm-ts
  ```
</CodeGroup>

## Initialization

<CodeGroup>
  ```python Python theme={null}
  from kodexa_document import Document

  # Python SDK is ready to use immediately after import
  # Use context managers for automatic cleanup
  with Document() as doc:
      # Your code here
      pass
  ```

  ```typescript TypeScript theme={null}
  import { Kodexa } from '@kodexa-ai/document-wasm-ts';

  async function main() {
    // Initialize once at application start
    await Kodexa.init();

    // Your code here...
  }

  main();
  ```
</CodeGroup>

## Creating Documents

### Empty Document

Create a new document and build its structure:

<CodeGroup>
  ```python Python theme={null}
  from kodexa_document import Document

  with Document() as doc:
      # Create the root node
      root = doc.create_node("document", "My Document")
      doc.content_node = root

      # Add child nodes
      section = doc.create_node("section", "Introduction", parent=root)
      para1 = doc.create_node("paragraph", "First paragraph.", parent=section)
      para2 = doc.create_node("paragraph", "Second paragraph.", parent=section)

      print(f"Created document with {len(root.get_children())} sections")
  ```

  ```typescript TypeScript theme={null}
  import { Kodexa } from '@kodexa-ai/document-wasm-ts';

  async function createDocument() {
    await Kodexa.init();
    const doc = await Kodexa.createDocument();

    try {
      // Create root node
      const root = await doc.createNode('document');
      await root.setContent('My Document');

      // Add child nodes
      const section = await doc.createNode('section');
      await section.setContent('Introduction');
      await root.addChild(section);

      const para1 = await doc.createNode('paragraph');
      await para1.setContent('First paragraph.');
      await section.addChild(para1);

      const para2 = await doc.createNode('paragraph');
      await para2.setContent('Second paragraph.');
      await section.addChild(para2);

      const children = await root.getChildren();
      console.log(`Created document with ${children.length} sections`);
    } finally {
      doc.dispose();
    }
  }
  ```
</CodeGroup>

### From Text

Automatically parse text into paragraphs:

<CodeGroup>
  ```python Python theme={null}
  text = """First paragraph of content.
  Second paragraph with more details.
  Third paragraph to conclude."""

  with Document.from_text(text, separator="\n") as doc:
      paragraphs = doc.select("//paragraph")
      print(f"Created {len(paragraphs)} paragraphs from text")
  ```

  ```typescript TypeScript theme={null}
  async function fromText() {
    await Kodexa.init();

    const text = 'First paragraph.\nSecond paragraph.\nThird paragraph.';
    const doc = await Kodexa.fromText(text);

    try {
      const paragraphs = await doc.select('//paragraph');
      console.log(`Created ${paragraphs.length} paragraphs from text`);
    } finally {
      doc.dispose();
    }
  }
  ```
</CodeGroup>

### With Metadata

Initialize documents with metadata:

<CodeGroup>
  ```python Python theme={null}
  with Document(metadata={
      "title": "Invoice Analysis",
      "author": "Processing System",
      "created": "2024-01-15"
  }) as doc:
      title = doc.get_metadata("title")
      print(f"Document title: {title}")
  ```

  ```typescript TypeScript theme={null}
  async function withMetadata() {
    await Kodexa.init();
    const doc = await Kodexa.createDocument();

    try {
      await doc.setMetadataValue('title', 'Invoice Analysis');
      await doc.setMetadataValue('author', 'Processing System');
      await doc.setMetadataValue('created', '2024-01-15');

      const title = await doc.getMetadataValue('title');
      console.log(`Document title: ${title}`);
    } finally {
      doc.dispose();
    }
  }
  ```
</CodeGroup>

## Loading Documents

### From KDDB File / Blob

<CodeGroup>
  ```python Python theme={null}
  # Load into memory for fast processing (creates a copy)
  with Document.from_kddb("document.kddb", detached=True) as doc:
      print(f"Loaded document: {doc.uuid}")
      nodes = doc.select("//*")
      print(f"Total nodes: {len(nodes)}")

  # Load from bytes (e.g., API response)
  import requests
  response = requests.get("https://api.example.com/documents/123")
  with Document.from_kddb(response.content) as doc:
      print(f"Loaded from API: {doc.uuid}")
  ```

  ```typescript TypeScript theme={null}
  // From file input (browser)
  async function loadFromFile() {
    await Kodexa.init();

    const fileInput = document.getElementById('file') as HTMLInputElement;
    const file = fileInput.files?.[0];

    if (file) {
      const doc = await Kodexa.fromBlob(file);
      try {
        const nodes = await doc.select('//*');
        console.log(`Total nodes: ${nodes.length}`);
      } finally {
        doc.dispose();
      }
    }
  }

  // From fetch response
  async function loadFromApi() {
    await Kodexa.init();

    const response = await fetch('https://api.example.com/documents/123');
    const blob = await response.blob();
    const doc = await Kodexa.fromBlob(blob);

    try {
      console.log('Loaded from API');
    } finally {
      doc.dispose();
    }
  }
  ```
</CodeGroup>

### From JSON

<CodeGroup>
  ```python Python theme={null}
  json_data = '{"uuid": "...", "metadata": {"title": "Test"}}'
  with Document.from_json(json_data) as doc:
      print(f"Loaded from JSON: {doc.uuid}")
  ```

  ```typescript TypeScript theme={null}
  async function fromJson() {
    await Kodexa.init();

    const jsonData = JSON.stringify({
      uuid: 'example-uuid',
      metadata: { title: 'Test Document' }
    });

    const doc = await Kodexa.fromJson(jsonData);

    try {
      console.log('Loaded from JSON');
    } finally {
      doc.dispose();
    }
  }
  ```
</CodeGroup>

## Working with Content Nodes

### Navigation

Traverse the document tree:

<CodeGroup>
  ```python Python theme={null}
  with Document.from_kddb("document.kddb") as doc:
      root = doc.content_node

      for child in root.get_children():
          parent = child.get_parent()       # Back to root
          siblings = child.get_siblings()   # Other children
          next_node = child.next_node()     # Next sibling
          depth = child.get_depth()         # Depth in tree

          print(f"Node type: {child.type}, depth: {depth}")
  ```

  ```typescript TypeScript theme={null}
  async function navigateTree() {
    await Kodexa.init();
    const doc = await Kodexa.fromText('Para 1\nPara 2\nPara 3');

    try {
      const root = await doc.getRoot();

      if (root) {
        const children = await root.getChildren();

        for (const child of children) {
          console.log(`Type: ${child.type}`);
          console.log(`Content: ${child.content}`);

          const parent = await child.getParent();
          const nextNode = await child.nextNode();
          const depth = await child.getDepth();
        }
      }
    } finally {
      doc.dispose();
    }
  }
  ```
</CodeGroup>

### Content Access

Read and modify node content:

<CodeGroup>
  ```python Python theme={null}
  with Document() as doc:
      root = doc.create_node("document")
      doc.content_node = root

      para = doc.create_node("paragraph", "Initial content", parent=root)

      # Read content
      print(f"Content: {para.content}")

      # Update content
      para.content = "Updated content"

      # Multi-part content
      para.set_content_parts(["Part 1", "Part 2", "Part 3"])
      parts = para.get_content_parts()

      # Get all content from node and descendants
      all_text = root.get_all_content(separator=" ")
  ```

  ```typescript TypeScript theme={null}
  async function workWithContent() {
    await Kodexa.init();
    const doc = await Kodexa.createDocument();

    try {
      const node = await doc.createNode('paragraph');

      // Set content
      await node.setContent('Initial content');

      // Read content
      const content = await node.getContent();
      console.log(`Content: ${content}`);

      // Synchronous access (after first async call)
      console.log(`Direct access: ${node.content}`);
    } finally {
      doc.dispose();
    }
  }
  ```
</CodeGroup>

## Querying with Selectors

Use XPath-like selectors to find nodes:

<CodeGroup>
  ```python Python theme={null}
  with Document.from_text("Para 1\nPara 2\nPara 3", separator="\n") as doc:
      # Select all nodes of a type
      all_paragraphs = doc.select("//paragraph")

      # Select first match only
      first_para = doc.select_first("//paragraph")

      # Filter by content
      matching = doc.select("//paragraph[contains(@content, 'Para 2')]")

      # Select tagged nodes
      tagged = doc.select("//*[@tag='important']")

      # Select with variables
      variables = {"search_term": "Para 1"}
      results = doc.select("//paragraph[contains(@content, $search_term)]", variables)

      print(f"Found {len(all_paragraphs)} paragraphs")
  ```

  ```typescript TypeScript theme={null}
  async function queryDocument() {
    await Kodexa.init();
    const doc = await Kodexa.fromText('Important note\nRegular text\nAnother note');

    try {
      // Select all nodes of a type
      const allParagraphs = await doc.select('//paragraph');
      console.log(`Found ${allParagraphs.length} paragraphs`);

      // Select first match
      const firstPara = await doc.selectFirst('//paragraph');
      if (firstPara) {
        console.log(`First paragraph: ${firstPara.content}`);
      }

      // Filter by content
      const noteParagraphs = await doc.select("//paragraph[contains(@content, 'note')]");

      // Select by tag
      const tagged = await doc.select("//*[@tag='important']");
    } finally {
      doc.dispose();
    }
  }
  ```
</CodeGroup>

### Common Selector Patterns

| Selector                                  | Description                         |
| ----------------------------------------- | ----------------------------------- |
| `//*`                                     | All nodes                           |
| `//paragraph`                             | All paragraphs                      |
| `//section/paragraph`                     | Direct child paragraphs of sections |
| `//paragraph[1]`                          | First paragraph                     |
| `//*[@tag='important']`                   | Nodes with 'important' tag          |
| `//paragraph[contains(@content, 'text')]` | Paragraphs containing 'text'        |

## Adding Features

Attach metadata to nodes:

<CodeGroup>
  ```python Python theme={null}
  with Document() as doc:
      root = doc.create_node("document")
      doc.content_node = root
      para = doc.create_node("paragraph", "Styled text", parent=root)

      # Add features (type, name, value)
      para.add_feature("style", "font-family", "Arial")
      para.add_feature("style", "font-size", "12pt")
      para.add_feature("analysis", "word-count", 2)
      para.add_feature("position", "bbox", {"x": 100, "y": 200, "w": 300, "h": 50})

      # Retrieve features
      font = para.get_feature("style", "font-family")
      if font:
          print(f"Font: {font.get_value()}")

      # Get all features of a type
      style_features = para.get_features_of_type("style")
  ```

  ```typescript TypeScript theme={null}
  async function addFeatures() {
    await Kodexa.init();
    const doc = await Kodexa.createDocument();

    try {
      const node = await doc.createNode('paragraph');
      await node.setContent('Styled text');

      // Add features (type, name, value)
      await node.setFeature('style', 'font-family', 'Arial');
      await node.setFeature('style', 'font-size', '12pt');
      await node.setFeature('analysis', 'word-count', 2);
      await node.setFeature('position', 'bbox', { x: 100, y: 200, w: 300, h: 50 });

      // Retrieve features
      const fontValue = await node.getFeatureValue('style', 'font-family');
      console.log(`Font: ${fontValue}`);

      // Get features by type
      const styleFeatures = await node.getFeaturesOfType('style');
    } finally {
      doc.dispose();
    }
  }
  ```
</CodeGroup>

## Adding Tags

Annotate nodes with tags:

<CodeGroup>
  ```python Python theme={null}
  with Document() as doc:
      root = doc.create_node("document")
      doc.content_node = root
      para = doc.create_node("paragraph", "Invoice total: $1,234.56", parent=root)

      # Simple tag
      para.tag("important")

      # Tag with confidence and value
      para.tag("invoice-total", confidence=0.95, value="$1,234.56")

      # Check for tags
      if para.has_tag("important"):
          print("This paragraph is marked as important")

      # Get tag details
      tag = para.get_tag("invoice-total")
      if tag:
          confidence = tag.get("Confidence")
          value = tag.get("Value")
          print(f"Invoice total: {value} (confidence: {confidence})")

      # List all tags
      all_tags = para.get_tags()
  ```

  ```typescript TypeScript theme={null}
  async function tagNodes() {
    await Kodexa.init();
    const doc = await Kodexa.fromText('Invoice total: $500.00');

    try {
      const firstPara = await doc.selectFirst('//paragraph');

      if (firstPara) {
        // Simple tag
        await firstPara.tag('important');

        // Tag with options
        await firstPara.tagWithOptions('invoice-total', {
          confidence: 0.95,
          value: '500.00'
        });

        // Check for tags
        const hasTag = await firstPara.hasTag('important');
        console.log(`Has 'important' tag: ${hasTag}`);

        // Get all tags
        const tags = await firstPara.getTags();
        console.log(`Tags: ${tags.join(', ')}`);

        // Remove a tag
        await firstPara.removeTag('important');
      }
    } finally {
      doc.dispose();
    }
  }
  ```
</CodeGroup>

## Saving Documents

### To KDDB File / Blob

<CodeGroup>
  ```python Python theme={null}
  with Document() as doc:
      root = doc.create_node("document", "Content to save")
      doc.content_node = root

      # Save to file
      doc.save("output.kddb")

      # Get as bytes (for API responses)
      kddb_bytes = doc.to_kddb()
  ```

  ```typescript TypeScript theme={null}
  async function saveDocument() {
    await Kodexa.init();
    const doc = await Kodexa.fromText('Content for download');

    try {
      // Export as KDDB blob
      const blob = await doc.toBlob();

      // Download in browser
      const url = URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = 'document.kddb';
      a.click();
      URL.revokeObjectURL(url);
    } finally {
      doc.dispose();
    }
  }
  ```
</CodeGroup>

### To JSON

<CodeGroup>
  ```python Python theme={null}
  with Document() as doc:
      root = doc.create_node("document", "Debug output")
      doc.content_node = root

      # Pretty-printed JSON
      json_str = doc.to_json(indent=2)
      print(json_str)

      # As dictionary
      doc_dict = doc.to_dict()
  ```

  ```typescript TypeScript theme={null}
  async function saveToJson() {
    await Kodexa.init();
    const doc = await Kodexa.fromText('Content to save');

    try {
      const json = await doc.toJson();
      console.log(json);

      // Send to server
      await fetch('/api/documents', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: json
      });
    } finally {
      doc.dispose();
    }
  }
  ```
</CodeGroup>

## Memory Management

<Warning>
  Both SDKs use native code (Go via CFFI for Python, WebAssembly for TypeScript). Proper cleanup prevents memory leaks.
</Warning>

<CodeGroup>
  ```python Python theme={null}
  # Python: Use context managers (recommended)
  with Document() as doc:
      # Document automatically closed when exiting the block
      root = doc.create_node("document", "Safe content")

  # Manual cleanup if needed
  doc = Document()
  try:
      # Work with document
      pass
  finally:
      doc.close()
  ```

  ```typescript TypeScript theme={null}
  // TypeScript: Use try-finally pattern
  async function safeDocumentHandling() {
    await Kodexa.init();
    const doc = await Kodexa.createDocument();

    try {
      // All document operations here
      const root = await doc.createNode('document');
      await root.setContent('Safe content');
    } finally {
      // Always dispose, even if an error occurred
      doc.dispose();
    }
  }

  // Application cleanup
  window.addEventListener('beforeunload', () => {
    Kodexa.cleanup();
  });
  ```
</CodeGroup>

## Complete Example

A full invoice processing workflow:

<CodeGroup>
  ```python Python theme={null}
  from kodexa_document import Document

  def process_document():
      with Document() as doc:
          # Set document metadata
          doc.set_metadata("title", "Invoice Processing Result")
          doc.add_label("invoice")

          # Build document structure
          root = doc.create_node("document", "Invoice #12345")
          doc.content_node = root

          # Add header section
          header = doc.create_node("section", "Header", parent=root)
          doc.create_node("paragraph", "Vendor: Acme Corp", parent=header)
          doc.create_node("paragraph", "Date: 2024-01-15", parent=header)

          # Add line items
          items = doc.create_node("section", "Line Items", parent=root)

          for i, (desc, amount) in enumerate([
              ("Widget A", 100.00),
              ("Widget B", 250.00),
              ("Service Fee", 50.00)
          ]):
              item = doc.create_node("paragraph", f"{desc}: ${amount:.2f}", parent=items)
              item.add_feature("line-item", "amount", amount)
              item.tag("line-item", value=str(amount))

          # Add total
          total = doc.create_node("paragraph", "Total: $400.00", parent=root)
          total.tag("invoice-total", confidence=1.0, value="400.00")

          # Query the document
          line_items = doc.select("//*[@tag='line-item']")
          print(f"Found {len(line_items)} line items")

          total_node = doc.select_first("//*[@tag='invoice-total']")
          if total_node:
              print(f"Invoice total: {total_node.content}")

          # Save the result
          doc.save("processed_invoice.kddb")

  if __name__ == "__main__":
      process_document()
  ```

  ```typescript TypeScript theme={null}
  import { Kodexa } from '@kodexa-ai/document-wasm-ts';

  async function processInvoice() {
    await Kodexa.init();
    const doc = await Kodexa.createDocument();

    try {
      // Set document metadata
      await doc.setMetadataValue('title', 'Invoice Processing Result');

      // Build document structure
      const root = await doc.createNode('document');
      await root.setContent('Invoice #12345');

      // Add header section
      const header = await doc.createNode('section');
      await header.setContent('Header');
      await root.addChild(header);

      const vendor = await doc.createNode('paragraph');
      await vendor.setContent('Vendor: Acme Corp');
      await header.addChild(vendor);

      // Add line items
      const items = await doc.createNode('section');
      await items.setContent('Line Items');
      await root.addChild(items);

      const lineItems = [
        { desc: 'Widget A', amount: 100.00 },
        { desc: 'Widget B', amount: 250.00 },
        { desc: 'Service Fee', amount: 50.00 }
      ];

      for (const { desc, amount } of lineItems) {
        const item = await doc.createNode('paragraph');
        await item.setContent(`${desc}: $${amount.toFixed(2)}`);
        await items.addChild(item);

        await item.setFeature('line-item', 'amount', amount);
        await item.tagWithOptions('line-item', { value: String(amount) });
      }

      // Add total
      const total = await doc.createNode('paragraph');
      await total.setContent('Total: $400.00');
      await root.addChild(total);
      await total.tagWithOptions('invoice-total', { confidence: 1.0, value: '400.00' });

      // Query the document
      const taggedItems = await doc.select("//*[@tag='line-item']");
      console.log(`Found ${taggedItems.length} line items`);

      const totalNode = await doc.selectFirst("//*[@tag='invoice-total']");
      if (totalNode) {
        console.log(`Invoice total: ${totalNode.content}`);
      }

      // Export
      const json = await doc.toJson();
      console.log('Document processed successfully');
    } finally {
      doc.dispose();
    }
  }

  processInvoice().catch(console.error);
  ```
</CodeGroup>

## Next Steps

As you become more familiar with the SDK, explore:

* Advanced XPath selectors for complex queries
* Processing steps for workflow tracking
* Integration with Kodexa Platform for cloud processing
