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

# Retrieve Corpus

> Fetch the latest metadata for a single corpus by ID.

## Overview

Fetch detailed metadata for a single corpus by its unique identifier. This endpoint returns the same comprehensive information as the list endpoint but scoped to one record. Only the corpus owner can retrieve this data.

<Info>
  **Use this for**: Checking indexing status after creation, refreshing UI state after updates, validating corpus existence before operations.
</Info>

## Authentication

Requires valid JWT token or session authentication. You must own the target corpus.

## Path Parameters

<ParamField path="id" type="UUID" required>
  The corpus identifier returned during creation or from the list endpoint.

  **Example**: `8d0f0a5d-4b5e-4c09-9db6-0e9d2aa8a9fd`
</ParamField>

## Example request

```bash theme={null}
curl -X GET https://{your-host}/api/corpora/8d0f0a5d-4b5e-4c09-9db6-0e9d2aa8a9fd/ \
  -H "Authorization: Bearer $SOAR_LABS_TOKEN"
```

## Example response

```json theme={null}
{
  "id": "8d0f0a5d-4b5e-4c09-9db6-0e9d2aa8a9fd",
  "created_at": "2024-09-01T10:05:03.291Z",
  "updated_at": "2024-09-01T10:08:11.522Z",
  "corpora_name": "support_playbooks",
  "description": "Runbooks feeding LlamaIndex",
  "size_on_disk": 4194304.0,
  "index_location": "qdrant_free_collection",
  "is_published": false,
  "index_type": "VSI",
  "indexing_status": "IND",
  "creator": "eb81c1d5-78fe-4f35-b58e-0ff6a3ad5d12"
}
```

## Response Structure

<ResponseField name="id" type="UUID">
  Unique corpus identifier.
</ResponseField>

<ResponseField name="created_at" type="timestamp">
  ISO 8601 timestamp when the corpus was created.
</ResponseField>

<ResponseField name="updated_at" type="timestamp">
  Last modification timestamp. Updates when metadata changes or resources are added.
</ResponseField>

<ResponseField name="corpora_name" type="string">
  Normalized corpus name (lowercase with underscores).
</ResponseField>

<ResponseField name="description" type="string">
  User-provided description of the corpus purpose.
</ResponseField>

<ResponseField name="size_on_disk" type="float">
  Storage size in bytes consumed by this corpus and its resources.
</ResponseField>

<ResponseField name="index_location" type="string">
  Vector database collection identifier where embeddings are stored.
</ResponseField>

<ResponseField name="is_published" type="boolean">
  Public visibility flag. `true` makes the corpus discoverable by other users.
</ResponseField>

<ResponseField name="index_type" type="string">
  Indexing strategy: `VSI` (Vector Store Index), `SMI` (Summary Index), or `DSI` (Document Summary Index).
</ResponseField>

<ResponseField name="indexing_status" type="string">
  Current processing state:

  * `PND` - Pending (waiting for resources)
  * `PRS` - Processing (indexing in progress)
  * `IND` - Indexed (ready for queries)
  * `ERR` - Error (indexing failed)
</ResponseField>

<ResponseField name="creator" type="UUID">
  User ID of the corpus owner.
</ResponseField>

## Common Use Cases

<AccordionGroup>
  <Accordion title="Poll for Indexing Completion" icon="clock-rotate-left">
    After creating a corpus and uploading resources, poll this endpoint to check when indexing completes:

    ```python theme={null}
    import time
    import requests

    def wait_for_indexing(base_url, token, corpus_id, timeout=300):
        start = time.time()
        while time.time() - start < timeout:
            response = requests.get(
                f"{base_url}/api/corpora/{corpus_id}/",
                headers={"Authorization": f"Bearer {token}"}
            )
            corpus = response.json()

            if corpus["indexing_status"] == "IND":
                print("Corpus ready for queries!")
                return corpus
            elif corpus["indexing_status"] == "ERR":
                raise Exception("Indexing failed")

            time.sleep(5)  # Poll every 5 seconds

        raise TimeoutError("Indexing did not complete in time")
    ```
  </Accordion>

  <Accordion title="Verify Update Success" icon="check-circle">
    After modifying corpus settings, fetch the latest state to confirm changes:

    ```python theme={null}
    # Update the corpus
    requests.patch(
        f"{base_url}/api/corpora/{corpus_id}/",
        headers=headers,
        json={"is_published": True}
    )

    # Verify the change
    corpus = requests.get(
        f"{base_url}/api/corpora/{corpus_id}/",
        headers=headers
    ).json()

    assert corpus["is_published"] == True
    ```
  </Accordion>

  <Accordion title="Check Storage Usage" icon="hard-drive">
    Monitor storage consumption before adding more resources:

    ```python theme={null}
    corpus = requests.get(
        f"{base_url}/api/corpora/{corpus_id}/",
        headers=headers
    ).json()

    size_mb = corpus["size_on_disk"] / (1024 * 1024)
    print(f"Current storage: {size_mb:.2f} MB")

    # Warn if approaching limits
    if size_mb > 500:
        print("Warning: Large corpus size may affect query performance")
    ```
  </Accordion>

  <Accordion title="Validate Before Operations" icon="shield-check">
    Ensure corpus exists and is ready before performing operations:

    ```python theme={null}
    try:
        corpus = requests.get(
            f"{base_url}/api/corpora/{corpus_id}/",
            headers=headers
        ).json()

        # Check if ready for queries
        if corpus["indexing_status"] != "IND":
            raise ValueError("Corpus not fully indexed yet")

        # Proceed with operation
        query_corpus(corpus_id)
    except requests.HTTPError as e:
        if e.response.status_code == 404:
            print("Corpus not found or access denied")
    ```
  </Accordion>
</AccordionGroup>

<Note>
  **Security Note**: Requests return `404 Not Found` if the corpus belongs to another user. This prevents leaking corpus existence to unauthorized users.
</Note>

## Client examples

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    import os
    import requests

    BASE_URL = "https://your-soar-instance.com"
    TOKEN = os.environ["SOAR_LABS_TOKEN"]
    CORPUS_ID = "8d0f0a5d-4b5e-4c09-9db6-0e9d2aa8a9fd"

    response = requests.get(
        f"{BASE_URL}/api/corpora/{CORPUS_ID}/",
        headers={"Authorization": f"Bearer {TOKEN}"},
        timeout=30,
    )
    response.raise_for_status()
    corpus = response.json()
    ```
  </Tab>

  <Tab title="TypeScript / JavaScript">
    ```ts theme={null}
    const BASE_URL = "https://your-soar-instance.com";
    const token = process.env.SOAR_LABS_TOKEN!;

    async function getCorpus(corpusId: string) {
      const response = await fetch(`${BASE_URL}/api/corpora/${corpusId}/`, {
        headers: {
          Authorization: `Bearer ${token}`,
        },
      });

      if (!response.ok) {
        throw new Error(`Retrieve corpus failed: ${response.status}`);
      }

      return response.json();
    }
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    import java.net.URI;
    import java.net.http.HttpClient;
    import java.net.http.HttpRequest;
    import java.net.http.HttpResponse;

    var BASE_URL = "https://your-soar-instance.com";
    var token = System.getenv("SOAR_LABS_TOKEN");
    var corpusId = "8d0f0a5d-4b5e-4c09-9db6-0e9d2aa8a9fd";

    var request = HttpRequest.newBuilder(URI.create(BASE_URL + "/api/corpora/" + corpusId + "/"))
        .header("Authorization", "Bearer " + token)
        .GET()
        .build();

    var response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());

    if (response.statusCode() >= 400) {
        throw new RuntimeException("Retrieve corpus failed: " + response.statusCode());
    }

    var body = response.body();
    ```
  </Tab>
</Tabs>


## OpenAPI

````yaml GET /api/corpora/{id}/
openapi: 3.0.3
info:
  title: Soar Labs API - Insider Dev preview
  version: 0.1.0
  description: <b>Soar Labs Advanced RAG platform</b>
servers: []
security: []
paths:
  /api/corpora/{id}/:
    get:
      tags:
        - Corpora
      description: >-
        Corpora creation API using Django Rest Framework.


        This viewset provides CRUD operations for Corpora objects.


        ### Responses


        - **201 Created**: Returned on successful creation of a Corpora.

        - **400 Bad Request**: Returned if the request data is invalid.

        - **401 Unauthorized**: Returned if the user is not authenticated.

        - **403 Forbidden**: Returned if the user is not authorized to perform
        the operation.

        - **404 Not Found**: Returned if the requested Corpora does not exist.


        ### Permissions

        - `IsAuthenticated`: Users must be authenticated to access this
        endpoint.
      operationId: api_corpora_retrieve
      parameters:
        - in: path
          name: id
          schema:
            type: string
            format: uuid
          description: A UUID string identifying this Corpora.
          required: true
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Corpora'
          description: ''
      security:
        - jwtHeaderAuth: []
        - jwtCookieAuth: []
        - cookieAuth: []
        - basicAuth: []
components:
  schemas:
    Corpora:
      type: object
      properties:
        id:
          type: string
          format: uuid
          readOnly: true
        created_at:
          type: string
          format: date-time
          readOnly: true
          description: The date and time the organization was created
        updated_at:
          type: string
          format: date-time
          readOnly: true
          description: Last updated time
        corpora_name:
          type: string
          description: Name of the corpora
          maxLength: 100
        description:
          type: string
          nullable: true
          description: Description of the corpora
        size_on_disk:
          type: number
          format: double
          readOnly: true
          title: Size
          description: Size of the corpora on disk (in bytes)
        index_location:
          type: string
          readOnly: true
          nullable: true
          title: Location of Index
          description: Location of the index on Remote Storage
        is_published:
          type: boolean
          title: Publishing Status
          description: Is the corpora Visible to all users?
        index_type:
          allOf:
            - $ref: '#/components/schemas/IndexTypeEnum'
          description: |-
            Type of index to be used for the corpora

            * `VSI` - VectorStoreIndex
            * `SMI` - SummaryIndex
            * `DSI` - DocumentSummaryIndex
        indexing_status:
          allOf:
            - $ref: '#/components/schemas/IndexingStatusEnum'
          title: Index Processing Status
          description: |-
            Status of the corpora processing

            * `PND` - Pending
            * `IQE` - In Queue
            * `PRS` - Processing
            * `DEX` - Data Extracted Successfully
            * `DER` - Data Extraction Error
            * `IND` - Indexed
            * `CMP` - Completed
            * `ERR` - Error
        creator:
          type: string
          format: uuid
          readOnly: true
      required:
        - corpora_name
        - created_at
        - creator
        - id
        - index_location
        - size_on_disk
        - updated_at
    IndexTypeEnum:
      enum:
        - VSI
        - SMI
        - DSI
      type: string
      description: |-
        * `VSI` - VectorStoreIndex
        * `SMI` - SummaryIndex
        * `DSI` - DocumentSummaryIndex
    IndexingStatusEnum:
      enum:
        - PND
        - IQE
        - PRS
        - DEX
        - DER
        - IND
        - CMP
        - ERR
      type: string
      description: |-
        * `PND` - Pending
        * `IQE` - In Queue
        * `PRS` - Processing
        * `DEX` - Data Extracted Successfully
        * `DER` - Data Extraction Error
        * `IND` - Indexed
        * `CMP` - Completed
        * `ERR` - Error
  securitySchemes:
    jwtHeaderAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
    jwtCookieAuth:
      type: apiKey
      in: cookie
      name: soar-app-auth
    cookieAuth:
      type: apiKey
      in: cookie
      name: sessionid
    basicAuth:
      type: http
      scheme: basic

````