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

# Partition

### Introduction

`partitions.create` groups a document into repeated chunks using a key such as `invoice_number`, `policy_id`, or `claim_number`.

This is a separate primitive from `split`.

* `split` answers: "What subdocument type is on these pages?"
* `partition` answers: "Which pages belong to each key value?"

Use `partition` when one document contains many records of the same conceptual type and you want one result per detected key.

Common use cases include:

1. **Invoice batches**: Group one PDF into one chunk per invoice number.
2. **Claim packets**: Group pages by claim ID inside a large insurance packet.
3. **Policy exports**: Break a carrier export into one chunk per policy number.
4. **Repeated forms**: Segment a homogeneous packet into one chunk per repeated identifier.

```mermaid theme={null}
flowchart LR
    A[Document with repeated records] --> B

    subgraph Retab["Retab Partition API"]
        B[1. Read document]
        B --> C[2. Detect key values]
        C --> D[3. Group pages by key]
    end

    D --> E

    subgraph Output["Partition output"]
        E[INV-001: pages 1-2]
        F[INV-002: pages 3-4]
    end
```

Key features of the Partition API:

* **Key-based grouping**: Separate repeated records by business identifier.
* **Canonical resource**: Returns a stored `Partition` with `id`, `file`, `model`, `output`, `consensus`, and `usage`.
* **Page-level mapping**: Each chunk includes the 1-indexed pages assigned to it.
* **Consensus support**: Increase `n_consensus` to inspect `consensus.likelihoods` and `consensus.choices`.

## Partition API

<ParamField body="PartitionRequest" type="PartitionRequest">
  <Expandable title="properties">
    <ParamField body="document" type="MIMEData" required>
      The document to partition. The HTTP API accepts `MIMEData`. The SDKs also
      accept convenient local inputs such as file paths, file-like objects, images,
      buffers, and URLs, then convert them for you.
    </ParamField>

    <ParamField body="key" type="string" required>
      The field or concept used to separate the document into chunks, such as
      `invoice_number`, `policy_id`, or `claim_number`.
    </ParamField>

    <ParamField body="instructions" type="string" required>
      Natural-language guidance describing how the document should be partitioned.
    </ParamField>

    <ParamField body="model" type="string" default="retab-small">
      The model used for partitioning.
    </ParamField>

    <ParamField body="n_consensus" type="integer" default="1">
      Number of partitioning runs to use for consensus voting.
    </ParamField>

    <ParamField body="allow_overlap" type="boolean" default="true">
      When `true`, partition chunks may share pages. Set to `false` for exclusive
      chunks.
    </ParamField>

    <ParamField body="bust_cache" type="boolean" default="false">
      When `true`, bypass the cache and force a fresh partition run.
    </ParamField>
  </Expandable>
</ParamField>

<ResponseField name="Returns" type="Partition">
  The stored partition record with its grouped chunks and metadata.

  <Expandable title="properties">
    <ResponseField name="id" type="string">
      Unique identifier of the partition run (prefix `prtn_`).
    </ResponseField>

    <ResponseField name="file" type="FileRef">
      Reference to the source document (`id`, `filename`, `mime_type`).
    </ResponseField>

    <ResponseField name="model" type="string">
      Model used for partitioning.
    </ResponseField>

    <ResponseField name="key" type="string">
      Partition key used for the run.
    </ResponseField>

    <ResponseField name="instructions" type="string">
      Instructions supplied with the partition request.
    </ResponseField>

    <ResponseField name="n_consensus" type="integer">
      Number of consensus votes used.
    </ResponseField>

    <ResponseField name="allow_overlap" type="boolean">
      Whether partition chunks were allowed to share pages.
    </ResponseField>

    <ResponseField name="output" type="array[PartitionChunk]">
      One chunk per detected key value, each containing: - `key`: The detected
      partition key value - `pages`: The 1-indexed pages assigned to that chunk
    </ResponseField>

    <ResponseField name="consensus" type="PartitionConsensus">
      Present for all responses and populated when `n_consensus > 1`: -
      `likelihoods`: A tree aligned with `output`, with confidence for `key` and
      for each page leaf - `choices`: One entry per consensus run
    </ResponseField>

    <ResponseField name="usage" type="RetabUsage | null">
      Usage information for the partition operation.
    </ResponseField>

    <ResponseField name="created_at" type="datetime | null">
      Timestamp when the partition was created.
    </ResponseField>
  </Expandable>
</ResponseField>

## Use Case: Partitioning an Invoice Batch

Use partitioning when every record is the same general document type, but each record has its own identifier and should become its own chunk.

<CodeGroup>
  ```python Python theme={null}
  from retab import Retab

  client = Retab()

  response = client.partitions.create(
      document="invoice_batch.pdf",
      key="invoice_number",
      instructions="Return one chunk per invoice number and keep all pages for the same invoice together.",
      model="retab-small",
      n_consensus=3,
  )

  for chunk in response.output:
      print(chunk.key, chunk.pages)

  print(response.consensus.likelihoods)

  ```

  ```typescript TypeScript theme={null}
  import { Retab } from '@retab/node';

  const client = new Retab({ apiKey: process.env.RETAB_API_KEY });

  const response = await client.partitions.create("invoice_batch.pdf", "invoice_number", "Return one chunk per invoice number and keep all pages for the same invoice together.", "retab-small", 3);

  for (const chunk of response.output) {
    console.log(chunk.key, chunk.pages);
  }

  console.log(response.consensus.likelihoods);
  ```

  ```go Go theme={null}
  package main

  import (
  	"context"
  	"fmt"
  	"log"

  	retab "github.com/retab-dev/retab/clients/go"
  )

  func main() {
  	ctx := context.Background()

  	client, err := retab.NewClient("")
  	if err != nil {
  		log.Fatal(err)
  	}

  	model := "retab-small"
  	nConsensus := 3
  	response, err := client.Partitions.Create(ctx, &retab.PartitionsCreateParams{
  		Document:     "invoice_batch.pdf",
  		Key:          "invoice_number",
  		Instructions: "Return one chunk per invoice number and keep all pages for the same invoice together.",
  		Model:        &model,
  		NConsensus:   &nConsensus,
  	})
  	if err != nil {
  		log.Fatal(err)
  	}

  	for _, chunk := range response.Output {
  		fmt.Println(chunk.Key, chunk.Pages)
  	}

  	if response.Consensus != nil {
  		fmt.Println(response.Consensus.Likelihoods)
  	}
  }
  ```

  ```ruby Ruby theme={null}
  require 'retab'

  client = Retab::Client.new(api_key: ENV['RETAB_API_KEY'])

  response = client.partitions.create(
    document: 'invoice_batch.pdf',
    key: 'invoice_number',
    instructions: 'Return one chunk per invoice number and keep all pages for the same invoice together.',
    model: 'retab-small',
    n_consensus: 3,
  )

  response.output.each do |chunk|
    puts "#{chunk.key} #{chunk.pages}"
  end

  puts response.consensus&.likelihoods
  ```

  ```php PHP theme={null}
  <?php
  require 'vendor/autoload.php';

  use Retab\Client;

  $client = new Client();

  $response = $client->partitions()->create(
      document: 'invoice_batch.pdf',
      key: 'invoice_number',
      instructions: 'Return one chunk per invoice number and keep all pages for the same invoice together.',
      model: 'retab-small',
      nConsensus: 3,
  );

  foreach ($response->output as $chunk) {
      echo $chunk->key . ': ' . implode(', ', $chunk->pages) . PHP_EOL;
  }

  print_r($response->consensus?->likelihoods);
  ```

  ```csharp C# theme={null}
  using System;
  using System.Collections.Generic;
  using System.IO;
  using Retab;
  using RetabClient = Retab.Retab;

  var client = new RetabClient("YOUR_API_KEY");

  var response = await client.Partitions.CreateAsync(
      new PartitionsCreateOptions
      {
          Document = new FileInfo("invoice_batch.pdf"),
          Key = "invoice_number",
          Instructions = "Return one chunk per invoice number and keep all pages for the same invoice together.",
          Model = "retab-small",
          NConsensus = 3,
      }
  );

  foreach (var chunk in response.Output ?? new List<PartitionChunk>())
  {
      Console.WriteLine($"{chunk.Key}: {string.Join(",", chunk.Pages ?? new List<long>())}");
  }

  if (response.Consensus?.Likelihoods != null)
  {
      Console.WriteLine(response.Consensus.Likelihoods);
  }
  ```

  ```rust Rust theme={null}
  use retab::resources::partitions::CreateParams;
  use retab::Retab;
  use std::path::PathBuf;

  #[tokio::main]
  async fn main() -> Result<(), Box<dyn std::error::Error>> {
      let client = Retab::new(std::env::var("RETAB_API_KEY")?);

      let mut params = CreateParams::new(
          PathBuf::from("invoice_batch.pdf"),
          "invoice_number",
          "Return one chunk per invoice number and keep all pages for the same invoice together.",
      );
      params.body.model = Some("retab-small".into());
      params.body.n_consensus = Some(3);

      let response = client.partitions().create(params).await?;

      if let Some(output) = &response.output {
          for chunk in output {
              println!("{} {:?}", chunk.key, chunk.pages);
          }
      }

      if let Some(consensus) = &response.consensus {
          println!("{:?}", consensus.likelihoods);
      }
      Ok(())
  }
  ```

  ```java Java theme={null}
  import com.retab.RetabClient;

  public final class Example {
    public static void main(String[] args) throws Exception {
      RetabClient client = new RetabClient(System.getenv("RETAB_API_KEY"));

      var result = client.partitions().create(null, null, "Extract the invoice fields", "retab-1.5", 10L, null, null, null);
      System.out.println(result);
    }
  }
  ```
</CodeGroup>

## When to Use Partition vs Split

* Use `partitions.create` when every record is conceptually the same kind of document and you want one chunk per repeated key value.
* Use `splits.create` when you need to classify a document into different subdocument types such as `invoice`, `receipt`, and `contract`.
* Use `partitions.create` after `splits.create` when you first need to isolate a subdocument type and then group that subset by a key.

## Best Practices

* Make the `key` semantically precise: `invoice_number`, `claim_id`, `policy_number`.
* Write `instructions` as grouping guidance, not as extraction schema guidance.
* Use `partition` only when the packet is homogeneous or when you have already isolated the relevant subdocument pages.
* Raise `n_consensus` when key assignment quality is important enough to inspect disagreements.

## Pricing

Partition is billed at the same rate as split:

```
credits_per_page = n_consensus × model_multiplier
total_credits    = credits_per_page × page_count
```

Model multipliers: `retab-micro = 0.2`, `retab-small = 1.0`, `retab-large = 3.0`.

Examples (1 page):

| Model         | n\_consensus = 1 | n\_consensus = 3 |
| ------------- | ---------------- | ---------------- |
| `retab-micro` | 0.2              | 0.6              |
| `retab-small` | 1.0              | 3.0              |
| `retab-large` | 3.0              | 9.0              |

No separate preprocessing charge applies to partition operations.
