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

# Python SDK

> Official Python SDK for LabTrace blockchain file management

# Python SDK

The LabTrace Python SDK provides a comprehensive interface for integrating blockchain-powered file management into Python applications, data science workflows, and backend services.

## Installation

Install the SDK using pip:

```bash theme={null}
# For local development (navigate to the sdk-py directory first)
cd sdk-py
pip install -e .
```

## Quick Start

### Authentication

```python theme={null}
from labtrace.client import Client

# Initialize client with username and password
client = Client(username="your-email@example.com", password="your-password")

# Or use environment variables
import os
client = Client(
    username=os.getenv("LABTRACE_USERNAME"),
    password=os.getenv("LABTRACE_PASSWORD")
)
```

### Basic File Operations

```python theme={null}
# Upload a public file
result = client.upload_public_file(
    project_id="proj_12pip install requests PyJWT3456",
    content=open("path/to/research_data.pdf", "rb").read(),
    file_type="primary",
    name="research_data.pdf",
    label="research,data,2024"
)

print(f"Upload successful: {result}")

# Upload a private file
result = client.upload_private_file(
    project_id="proj_123456",
    content=open("path/to/sensitive_data.pdf", "rb").read(),
    file_type="primary",
    name="sensitive_data.pdf",
    label="sensitive,confidential"
)

# Get project files
files = client.get_public_project_files(project_id="proj_123456")
for file in files['records']:
    print(f"{file['name']} - {file['uploaded']}")

# Download a file
client.get_public_file(
    project_id="proj_123456",
    file_id="file_789012",
    save_path="./downloads/"
)
```

## Client Configuration

```python theme={null}
# Set custom API base URL (optional)
import os
os.environ['LABTRACE_URL'] = 'https://api.labtrace.io'

client = Client(
    username="your-email@example.com",
    password="your-password"
)

# Get current user ID
user_id = client.get_user_id()
print(f"Current user: {user_id}")
```

## File Management

### Upload Files

<CodeGroup>
  ```python Public File Upload theme={null}
  # Upload a public file
  result = client.upload_public_file(
      project_id="proj_123456",
      content=file_content,
      file_type="primary",
      name="document.pdf",
      label="research,important"
  )
  ```

  ```python Private File Upload theme={null}
  # Upload a private file
  result = client.upload_private_file(
      project_id="proj_123456",
      content=file_content,
      file_type="primary",
      name="confidential.pdf",
      label="sensitive,private"
  )
  ```

  ```python Secondary File Upload theme={null}
  # Upload a secondary file with links
  result = client.upload_public_file(
      project_id="proj_123456",
      content=file_content,
      file_type="secondary",
      name="analysis.pdf",
      label="analysis,results",
      primary_data="file_id_1,file_id_2",
      link_to_procedure="procedure_file_id",
      procedure_description="Statistical analysis of primary data"
  )
  ```

  ```python Upload from File Path theme={null}
  # Upload from file path
  with open("data.xlsx", "rb") as f:
      content = f.read()

  result = client.upload_public_file(
      project_id="proj_123456",
      content=content,
      file_type="primary",
      name="data.xlsx",
      label="spreadsheet,data"
  )
  ```
</CodeGroup>

### Download Files

<CodeGroup>
  ```python Download Public File theme={null}
  # Download a public file
  client.get_public_file(
      project_id="proj_123456",
      file_id="file_789012",
      save_path="./downloads/"
  )
  ```

  ```python Download Certificate theme={null}
  # Download file certificate
  client.get_public_file_certificate(
      project_id="proj_123456",
      file_id="file_789012",
      save_path="./certificates/"
  )
  ```

  ```python Download Private Certificate theme={null}
  # Download private file certificate
  client.get_private_file_certificate(
      project_id="proj_123456",
      file_id="file_789012",
      save_path="./certificates/"
  )
  ```
</CodeGroup>

### List Files

<CodeGroup>
  ```python List Public Files theme={null}
  # Get all public files in a project
  files = client.get_public_project_files("proj_123456")

  for file in files['records']:
      print(f"File: {file['name']}")
      print(f"Owner: {file['ownerName']} {file['ownerLastName']}")
      print(f"Type: {file['type']}")
      print(f"Status: {file['status']}")
      print(f"Uploaded: {file['uploaded']}")
      print("---")
  ```

  ```python List Private Files theme={null}
  # Get all private files in a project
  files = client.get_private_project_files("proj_123456")

  for file in files['records']:
      print(f"File: {file['name']}")
      print(f"Owner: {file['ownerName']} {file['ownerLastName']}")
      print(f"Status: {file['status']}")
      print("---")
  ```
</CodeGroup>

### Delete Files

<CodeGroup>
  ```python Delete Public File theme={null}
  # Delete a public file
  result = client.delete_public_file(
      project_id="proj_123456",
      file_id="file_789012",
      user_id="user_123",
      reason="File no longer needed"
  )
  ```

  ```python Delete Private File theme={null}
  # Delete a private file
  result = client.delete_private_file(
      project_id="proj_123456",
      file_id="file_789012",
      user_id="user_123",
      reason="Data has been processed"
  )
  ```
</CodeGroup>

## Project Management

### Get Projects

<CodeGroup>
  ```python Get All Projects theme={null}
  # Get all projects
  projects = client.get_projects()

  for project in projects['records']:
      print(f"Project: {project['name']}")
      print(f"Leader: {project['leaderFirstName']} {project['leaderLastName']}")
      print(f"Organisation: {project['organisation']}")
      print(f"Location: {project['location']}")
      print("---")
  ```

  ```python Get Single Project theme={null}
  # Get specific project details
  project = client.get_project("proj_123456")

  print(f"Project Name: {project['name']}")
  print(f"Area: {project['area']}")
  print(f"Members: {project['members']['totalRecords']}")
  print(f"Start Date: {project['startDate']}")
  print(f"End Date: {project['endDate']}")
  ```

  ```python Filter Projects theme={null}
  # Filter projects by criteria
  projects = client.get_projects(
      project_name="Research",
      organisation="University",
      location="New York"
  )
  ```
</CodeGroup>

## File Verification

### Verify File Content

```python theme={null}
# Verify if file already exists
with open("document.pdf", "rb") as f:
    content = f.read()

verification = client.verify_file_content(
    content=content,
    name="document.pdf"
)

if verification['exists']:
    print(f"File already exists: {verification['fileName']}")
    print(f"In project: {verification['project']}")
else:
    print("File is unique, safe to upload")
```

## Error Handling

### Exception Handling

```python theme={null}
from labtrace import Client, ResponseException

try:
    client = Client(username="user@example.com", password="wrong-password")
except ResponseException as e:
    print(f"Authentication failed: {e.status_code} - {e.msg}")

try:
    files = client.get_public_project_files("invalid-project-id")
except ResponseException as e:
    if e.status_code == 404:
        print("Project not found")
    elif e.status_code == 403:
        print("Access denied")
    else:
        print(f"Error: {e.status_code} - {e.msg}")
```

### Automatic Token Refresh

The SDK automatically handles JWT token expiration and refreshes tokens when needed:

```python theme={null}
client = Client(username="user@example.com", password="password")

# Token is automatically refreshed if expired
files = client.get_public_project_files("proj_123456")  # Works even if token expired
```

## Advanced Features

### Custom Request Headers

```python theme={null}
# The SDK handles authentication automatically
# Custom headers can be added by modifying the client internals
client = Client(username="user@example.com", password="password")

# All requests will include the proper Authorization header
response = client.get_projects()
```

### Bulk Operations

```python theme={null}
# Upload multiple files
files_to_upload = [
    {"path": "file1.pdf", "label": "document1"},
    {"path": "file2.pdf", "label": "document2"},
    {"path": "file3.pdf", "label": "document3"}
]

for file_info in files_to_upload:
    with open(file_info["path"], "rb") as f:
        content = f.read()
    
    result = client.upload_public_file(
        project_id="proj_123456",
        content=content,
        file_type="primary",
        name=file_info["path"],
        label=file_info["label"]
    )
    print(f"Uploaded {file_info['path']}: {result}")
```

## API Reference

### Client Methods

#### Authentication

* `Client(username, password)` - Initialize client with credentials
* `get_user_id()` - Get current user ID from JWT token

#### Project Operations

* `get_projects(**filters)` - Get all projects with optional filters
* `get_project(project_id)` - Get specific project details

#### Public File Operations

* `upload_public_file(project_id, content, file_type, name, label, **kwargs)` - Upload public file
* `get_public_project_files(project_id)` - Get all public files in project
* `get_public_file(project_id, file_id, save_path)` - Download public file
* `get_public_file_certificate(project_id, file_id, save_path, raw=False)` - Download certificate
* `delete_public_file(project_id, file_id, user_id, reason)` - Delete public file

#### Private File Operations

* `upload_private_file(project_id, content, file_type, name, label, **kwargs)` - Upload private file
* `get_private_project_files(project_id)` - Get all private files in project
* `get_private_file_certificate(project_id, file_id, save_path, raw=False)` - Download certificate
* `delete_private_file(project_id, file_id, user_id, reason)` - Delete private file

#### File Verification

* `verify_file_content(content, name)` - Check if file already exists

### Response Formats

All methods return Python dictionaries with the response data. The SDK automatically handles JSON parsing and error responses.

## Environment Variables

The SDK supports the following environment variables:

* `LABTRACE_URL` - API base URL (default: [https://api.labtrace.io](https://api.labtrace.io))
* `LABTRACE_USERNAME` - Default username for authentication
* `LABTRACE_PASSWORD` - Default password for authentication

## Best Practices

### Security

* Store credentials securely (use environment variables or secure vaults)
* Use different accounts for different environments (dev/staging/prod)
* Regularly rotate passwords and update credentials

### Performance

* Reuse client instances when possible
* Handle large files in chunks for better memory usage
* Use appropriate file types (primary vs secondary) for organization

### Error Handling

* Always wrap SDK calls in try-catch blocks
* Check response status codes for specific error handling
* Implement retry logic for transient network errors

## Examples

### Complete Workflow Example

```python theme={null}
from labtrace import Client
import os

# Initialize client
client = Client(
    username=os.getenv("LABTRACE_USERNAME"),
    password=os.getenv("LABTRACE_PASSWORD")
)

# Get user's projects
projects = client.get_projects()
if not projects['records']:
    print("No projects found")
    exit()

project_id = projects['records'][0]['id']
print(f"Using project: {projects['records'][0]['name']}")

# Upload a file
with open("research_data.pdf", "rb") as f:
    content = f.read()

upload_result = client.upload_public_file(
    project_id=project_id,
    content=content,
    file_type="primary",
    name="research_data.pdf",
    label="research,data,analysis"
)

print(f"File uploaded successfully: {upload_result}")

# List all files
files = client.get_public_project_files(project_id)
print(f"Project has {files['totalRecords']} files")

# Download the first file
if files['records']:
    first_file = files['records'][0]
    client.get_public_file(
        project_id=project_id,
        file_id=first_file['id'],
        save_path="./downloads/"
    )
    print(f"Downloaded: {first_file['name']}")
```
