distru-sdk


Namedistru-sdk JSON
Version 1.0.0 PyPI version JSON
download
home_pagehttps://github.com/DistruApp/distru-api-sdk
SummaryOfficial Python SDK for the Distru API - Cannabis supply chain management
upload_time2025-10-06 21:15:56
maintainerNone
docs_urlNone
authorDistru Inc.
requires_python>=3.8
licenseMIT
keywords distru api sdk cannabis supply-chain inventory compliance
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Distru Python SDK

Official Python SDK for the [Distru API](https://distru.com) - Cannabis supply chain management platform.

[![PyPI version](https://badge.fury.io/py/distru-sdk.svg)](https://badge.fury.io/py/distru-sdk)
[![Python versions](https://img.shields.io/pypi/pyversions/distru-sdk.svg)](https://pypi.org/project/distru-sdk/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

## Installation

```bash
pip install distru-sdk
```

## Quick Start

```python
from distru_sdk import DistruClient

# Initialize the client with your API token
client = DistruClient(api_token="your_api_token_here")

# List products
products = client.products.list()
for product in products.auto_paginate():
    print(f"{product['name']} - ${product['sale_price']}")

# Create an order
order = client.orders.create(
    company_relationship_id=123,
    order_date="2025-10-06T12:00:00Z",
    order_items=[
        {
            "product_id": "prod-uuid-123",
            "quantity": 10,
            "unit_price": "15.00"
        }
    ]
)
print(f"Order created: {order['order_number']}")
```

## Authentication

The Distru API uses JWT Bearer token authentication. To get an API token:

1. Log into your Distru account
2. Navigate to **Settings** → **API Keys**
3. Click **Create API Key**
4. Copy the generated token
5. Store it securely (never commit to source control!)

```python
# Initialize client
client = DistruClient(api_token="your_api_token_here")

# Optional: Configure timeout and retries
client = DistruClient(
    api_token="your_api_token_here",
    timeout=60.0,  # Request timeout in seconds
    max_retries=5   # Maximum retry attempts
)
```

## Usage

### Products

```python
# List all products
products = client.products.list()

# Auto-paginate through all results
for product in products.auto_paginate():
    print(product['name'])

# Search products
products = client.products.list(search="Blue Dream")

# Get a specific product
product = client.products.get("prod-uuid-123")

# Create a product
product = client.products.create(
    name="Blue Dream 1g",
    sku="BD-1G",
    unit_type_id=1,
    inventory_tracking_method="BATCH",
    sale_price="15.00",
    wholesale_price="10.00"
)

# Update a product
product = client.products.update(
    "prod-uuid-123",
    sale_price="17.00",
    wholesale_price="11.00"
)

# Delete a product
client.products.delete("prod-uuid-123")
```

### Orders

```python
# List orders
orders = client.orders.list()

# Filter orders
orders = client.orders.list(
    status="Submitted",
    customer_id=123,
    from_date="2025-01-01",
    to_date="2025-12-31"
)

# Get a specific order
order = client.orders.get("order-uuid-123")

# Create an order
order = client.orders.create(
    company_relationship_id=123,
    order_date="2025-10-06T12:00:00Z",
    due_date="2025-10-20T12:00:00Z",
    order_items=[
        {
            "product_id": "prod-uuid-1",
            "quantity": 10,
            "unit_price": "15.00"
        },
        {
            "product_id": "prod-uuid-2",
            "quantity": 5,
            "unit_price": "25.00"
        }
    ]
)
```

### Invoices

```python
# List invoices
invoices = client.invoices.list()

# Filter invoices
invoices = client.invoices.list(
    status="Not Paid",
    customer_id=123
)

# Get a specific invoice
invoice = client.invoices.get(456)

# Create an invoice
invoice = client.invoices.create(
    order_id="order-uuid-123",
    invoice_date="2025-10-06T12:00:00Z",
    due_date="2025-10-20T12:00:00Z",
    invoice_items=[
        {
            "order_item_id": "order-item-uuid-1",
            "quantity": 10
        }
    ]
)

# Add a payment to an invoice
payment = client.invoices.add_payment(
    456,
    amount="150.00",
    payment_date="2025-10-06T12:00:00Z",
    payment_method_id=1
)
```

### Inventory

```python
# Get current inventory
inventory = client.inventory.list()

# Include cost information
inventory = client.inventory.list(include_costs=True)

# Filter by location
inventory = client.inventory.list(location_id=1)

# Filter by product
inventory = client.inventory.list(product_id="prod-uuid-123")
```

### Companies (Customers/Vendors)

```python
# List all companies
companies = client.companies.list()

# Search companies
companies = client.companies.list(search="Acme")

# Filter by state
companies = client.companies.list(us_state="CA")

# Get a specific company
company = client.companies.get(123)
```

### Batches

```python
# List batches
batches = client.batches.list()

# Filter by product
batches = client.batches.list(product_id="prod-uuid-123")

# Create a batch
batch = client.batches.create(
    product_id="prod-uuid-123",
    batch_number="BATCH-001",
    harvest_date="2025-09-01T00:00:00Z",
    expiration_date="2026-09-01T00:00:00Z"
)
```

### Purchases

```python
# List purchases
purchases = client.purchases.list()

# Create a purchase order
purchase = client.purchases.create(
    company_relationship_id=456,
    purchase_date="2025-10-06T12:00:00Z",
    purchase_items=[
        {
            "product_id": "prod-uuid-1",
            "quantity": 100,
            "unit_cost": "8.00"
        }
    ]
)

# Add a payment
payment = client.purchases.add_payment(
    789,
    amount="800.00",
    payment_date="2025-10-06T12:00:00Z"
)
```

## Pagination

All list endpoints return paginated results. The SDK provides helper methods for easy pagination:

### Auto-Pagination

```python
# Automatically fetch all pages
products = client.products.list()
for product in products.auto_paginate():
    print(product['name'])
```

### Manual Pagination

```python
# Iterate page by page
response = client.products.list()
for page in response.iter_pages():
    print(f"Processing page with {len(page)} items")
    for product in page:
        print(product['name'])
```

### Page-by-Page

```python
# Fetch specific pages
page_1 = client.products.list(page=1, limit=100)
page_2 = client.products.list(page=2, limit=100)
```

## Error Handling

The SDK provides specific exception classes for different error types:

```python
from distru_sdk.exceptions import (
    DistruAPIError,
    AuthenticationError,
    AuthorizationError,
    NotFoundError,
    ValidationError,
    RateLimitError,
    ServerError,
    NetworkError,
    TimeoutError,
)

try:
    order = client.orders.get("invalid-uuid")
except NotFoundError as e:
    print(f"Order not found: {e.message}")
except AuthenticationError as e:
    print(f"Invalid API token: {e.message}")
except RateLimitError as e:
    print(f"Rate limited, retry after {e.retry_after} seconds")
except ValidationError as e:
    print(f"Validation error: {e.message}")
    print(f"Details: {e.details}")
except ServerError as e:
    print(f"Server error: {e.message}")
except NetworkError as e:
    print(f"Network error: {e.message}")
except TimeoutError as e:
    print(f"Request timed out: {e.message}")
except DistruAPIError as e:
    print(f"API error: {e.message}")
```

## Webhooks (Beta)

Handle webhook events from Distru:

```python
from distru_sdk.webhooks import WebhookHandler

# Create webhook handler
handler = WebhookHandler()

# Register event handlers
@handler.on('ORDER')
def handle_order_event(event):
    if not event.before_changes:  # New order
        print(f"New order: {event.after_changes['order_number']}")
    elif not event.after_changes:  # Deleted order
        print(f"Order deleted: {event.before_changes['order_number']}")
    else:  # Updated order
        print(f"Order updated: {event.after_changes['order_number']}")

@handler.on('INVOICE')
def handle_invoice_event(event):
    print(f"Invoice event: {event.type}")

# In your web framework (Flask, FastAPI, Django, etc.)
from flask import Flask, request

app = Flask(__name__)

@app.route('/webhooks', methods=['POST'])
def webhook_endpoint():
    payload = request.get_json()
    handler.process(payload)
    return {'status': 'ok'}
```

## Data Consistency

The Distru API uses eventual consistency. Changes may take up to **1 second** to propagate to GET endpoints.

**Best Practices:**
- Use the returned data from create/update operations immediately
- For critical operations, add a small delay before fetching updated data
- Implement idempotency using unique identifiers

```python
import time

# Create an order
order = client.orders.create(...)

# The response contains the created order immediately
print(order['order_number'])  # Available immediately

# If you need to fetch it again, wait briefly
time.sleep(1.5)
order = client.orders.get(order['id'])  # Now guaranteed to be available
```

## Rate Limiting

The SDK automatically handles rate limiting with exponential backoff:

- Automatic retry on 429 (rate limit) and 5xx errors
- Exponential backoff: 1s, 2s, 4s, 8s, 10s (max)
- Maximum 3 retries by default (configurable)
- Respects `Retry-After` headers

```python
# Configure retry behavior
client = DistruClient(
    api_token="your_token",
    max_retries=5,  # Increase max retries
    timeout=60.0     # Increase timeout
)
```

## Advanced Usage

### Context Manager

```python
# Automatically close connection
with DistruClient(api_token="your_token") as client:
    products = client.products.list()
    for product in products.auto_paginate():
        print(product['name'])
# Connection closed automatically
```

### Custom HTTP Client

```python
import httpx

# Use custom httpx client
http_client = httpx.Client(
    timeout=60.0,
    limits=httpx.Limits(max_keepalive_connections=5)
)

client = DistruClient(
    api_token="your_token",
    http_client=http_client
)
```

## Requirements

- Python 3.8+
- httpx >= 0.25.0
- pydantic >= 2.0.0

## Development

### Setup

```bash
# Clone repository
git clone https://github.com/DistruApp/distru-api-sdk.git
cd distru-api-sdk/python

# Install in development mode
pip install -e ".[dev]"
```

### Running Tests

```bash
# Run all tests
pytest

# Run with coverage
pytest --cov=distru_sdk --cov-report=html

# Run specific test file
pytest tests/test_products.py
```

### Code Quality

```bash
# Format code
black distru_sdk tests

# Sort imports
isort distru_sdk tests

# Type checking
mypy distru_sdk

# Linting
flake8 distru_sdk tests
```

## Support

- **Documentation**: [GitHub Repository](https://github.com/DistruApp/distru-api-sdk)
- **Issues**: [GitHub Issues](https://github.com/DistruApp/distru-api-sdk/issues)
- **Email**: [support@distru.com](mailto:support@distru.com)

## License

MIT License - see [LICENSE](../LICENSE) file for details.

## Changelog

See [CHANGELOG.md](CHANGELOG.md) for version history and changes.

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/DistruApp/distru-api-sdk",
    "name": "distru-sdk",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": null,
    "keywords": "distru, api, sdk, cannabis, supply-chain, inventory, compliance",
    "author": "Distru Inc.",
    "author_email": "\"Distru Inc.\" <support@distru.com>",
    "download_url": "https://files.pythonhosted.org/packages/97/d2/364256ef7901cd6ee939040e21e81c653c69fa75fcdcf3110bc7322f5614/distru_sdk-1.0.0.tar.gz",
    "platform": null,
    "description": "# Distru Python SDK\n\nOfficial Python SDK for the [Distru API](https://distru.com) - Cannabis supply chain management platform.\n\n[![PyPI version](https://badge.fury.io/py/distru-sdk.svg)](https://badge.fury.io/py/distru-sdk)\n[![Python versions](https://img.shields.io/pypi/pyversions/distru-sdk.svg)](https://pypi.org/project/distru-sdk/)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\n## Installation\n\n```bash\npip install distru-sdk\n```\n\n## Quick Start\n\n```python\nfrom distru_sdk import DistruClient\n\n# Initialize the client with your API token\nclient = DistruClient(api_token=\"your_api_token_here\")\n\n# List products\nproducts = client.products.list()\nfor product in products.auto_paginate():\n    print(f\"{product['name']} - ${product['sale_price']}\")\n\n# Create an order\norder = client.orders.create(\n    company_relationship_id=123,\n    order_date=\"2025-10-06T12:00:00Z\",\n    order_items=[\n        {\n            \"product_id\": \"prod-uuid-123\",\n            \"quantity\": 10,\n            \"unit_price\": \"15.00\"\n        }\n    ]\n)\nprint(f\"Order created: {order['order_number']}\")\n```\n\n## Authentication\n\nThe Distru API uses JWT Bearer token authentication. To get an API token:\n\n1. Log into your Distru account\n2. Navigate to **Settings** \u2192 **API Keys**\n3. Click **Create API Key**\n4. Copy the generated token\n5. Store it securely (never commit to source control!)\n\n```python\n# Initialize client\nclient = DistruClient(api_token=\"your_api_token_here\")\n\n# Optional: Configure timeout and retries\nclient = DistruClient(\n    api_token=\"your_api_token_here\",\n    timeout=60.0,  # Request timeout in seconds\n    max_retries=5   # Maximum retry attempts\n)\n```\n\n## Usage\n\n### Products\n\n```python\n# List all products\nproducts = client.products.list()\n\n# Auto-paginate through all results\nfor product in products.auto_paginate():\n    print(product['name'])\n\n# Search products\nproducts = client.products.list(search=\"Blue Dream\")\n\n# Get a specific product\nproduct = client.products.get(\"prod-uuid-123\")\n\n# Create a product\nproduct = client.products.create(\n    name=\"Blue Dream 1g\",\n    sku=\"BD-1G\",\n    unit_type_id=1,\n    inventory_tracking_method=\"BATCH\",\n    sale_price=\"15.00\",\n    wholesale_price=\"10.00\"\n)\n\n# Update a product\nproduct = client.products.update(\n    \"prod-uuid-123\",\n    sale_price=\"17.00\",\n    wholesale_price=\"11.00\"\n)\n\n# Delete a product\nclient.products.delete(\"prod-uuid-123\")\n```\n\n### Orders\n\n```python\n# List orders\norders = client.orders.list()\n\n# Filter orders\norders = client.orders.list(\n    status=\"Submitted\",\n    customer_id=123,\n    from_date=\"2025-01-01\",\n    to_date=\"2025-12-31\"\n)\n\n# Get a specific order\norder = client.orders.get(\"order-uuid-123\")\n\n# Create an order\norder = client.orders.create(\n    company_relationship_id=123,\n    order_date=\"2025-10-06T12:00:00Z\",\n    due_date=\"2025-10-20T12:00:00Z\",\n    order_items=[\n        {\n            \"product_id\": \"prod-uuid-1\",\n            \"quantity\": 10,\n            \"unit_price\": \"15.00\"\n        },\n        {\n            \"product_id\": \"prod-uuid-2\",\n            \"quantity\": 5,\n            \"unit_price\": \"25.00\"\n        }\n    ]\n)\n```\n\n### Invoices\n\n```python\n# List invoices\ninvoices = client.invoices.list()\n\n# Filter invoices\ninvoices = client.invoices.list(\n    status=\"Not Paid\",\n    customer_id=123\n)\n\n# Get a specific invoice\ninvoice = client.invoices.get(456)\n\n# Create an invoice\ninvoice = client.invoices.create(\n    order_id=\"order-uuid-123\",\n    invoice_date=\"2025-10-06T12:00:00Z\",\n    due_date=\"2025-10-20T12:00:00Z\",\n    invoice_items=[\n        {\n            \"order_item_id\": \"order-item-uuid-1\",\n            \"quantity\": 10\n        }\n    ]\n)\n\n# Add a payment to an invoice\npayment = client.invoices.add_payment(\n    456,\n    amount=\"150.00\",\n    payment_date=\"2025-10-06T12:00:00Z\",\n    payment_method_id=1\n)\n```\n\n### Inventory\n\n```python\n# Get current inventory\ninventory = client.inventory.list()\n\n# Include cost information\ninventory = client.inventory.list(include_costs=True)\n\n# Filter by location\ninventory = client.inventory.list(location_id=1)\n\n# Filter by product\ninventory = client.inventory.list(product_id=\"prod-uuid-123\")\n```\n\n### Companies (Customers/Vendors)\n\n```python\n# List all companies\ncompanies = client.companies.list()\n\n# Search companies\ncompanies = client.companies.list(search=\"Acme\")\n\n# Filter by state\ncompanies = client.companies.list(us_state=\"CA\")\n\n# Get a specific company\ncompany = client.companies.get(123)\n```\n\n### Batches\n\n```python\n# List batches\nbatches = client.batches.list()\n\n# Filter by product\nbatches = client.batches.list(product_id=\"prod-uuid-123\")\n\n# Create a batch\nbatch = client.batches.create(\n    product_id=\"prod-uuid-123\",\n    batch_number=\"BATCH-001\",\n    harvest_date=\"2025-09-01T00:00:00Z\",\n    expiration_date=\"2026-09-01T00:00:00Z\"\n)\n```\n\n### Purchases\n\n```python\n# List purchases\npurchases = client.purchases.list()\n\n# Create a purchase order\npurchase = client.purchases.create(\n    company_relationship_id=456,\n    purchase_date=\"2025-10-06T12:00:00Z\",\n    purchase_items=[\n        {\n            \"product_id\": \"prod-uuid-1\",\n            \"quantity\": 100,\n            \"unit_cost\": \"8.00\"\n        }\n    ]\n)\n\n# Add a payment\npayment = client.purchases.add_payment(\n    789,\n    amount=\"800.00\",\n    payment_date=\"2025-10-06T12:00:00Z\"\n)\n```\n\n## Pagination\n\nAll list endpoints return paginated results. The SDK provides helper methods for easy pagination:\n\n### Auto-Pagination\n\n```python\n# Automatically fetch all pages\nproducts = client.products.list()\nfor product in products.auto_paginate():\n    print(product['name'])\n```\n\n### Manual Pagination\n\n```python\n# Iterate page by page\nresponse = client.products.list()\nfor page in response.iter_pages():\n    print(f\"Processing page with {len(page)} items\")\n    for product in page:\n        print(product['name'])\n```\n\n### Page-by-Page\n\n```python\n# Fetch specific pages\npage_1 = client.products.list(page=1, limit=100)\npage_2 = client.products.list(page=2, limit=100)\n```\n\n## Error Handling\n\nThe SDK provides specific exception classes for different error types:\n\n```python\nfrom distru_sdk.exceptions import (\n    DistruAPIError,\n    AuthenticationError,\n    AuthorizationError,\n    NotFoundError,\n    ValidationError,\n    RateLimitError,\n    ServerError,\n    NetworkError,\n    TimeoutError,\n)\n\ntry:\n    order = client.orders.get(\"invalid-uuid\")\nexcept NotFoundError as e:\n    print(f\"Order not found: {e.message}\")\nexcept AuthenticationError as e:\n    print(f\"Invalid API token: {e.message}\")\nexcept RateLimitError as e:\n    print(f\"Rate limited, retry after {e.retry_after} seconds\")\nexcept ValidationError as e:\n    print(f\"Validation error: {e.message}\")\n    print(f\"Details: {e.details}\")\nexcept ServerError as e:\n    print(f\"Server error: {e.message}\")\nexcept NetworkError as e:\n    print(f\"Network error: {e.message}\")\nexcept TimeoutError as e:\n    print(f\"Request timed out: {e.message}\")\nexcept DistruAPIError as e:\n    print(f\"API error: {e.message}\")\n```\n\n## Webhooks (Beta)\n\nHandle webhook events from Distru:\n\n```python\nfrom distru_sdk.webhooks import WebhookHandler\n\n# Create webhook handler\nhandler = WebhookHandler()\n\n# Register event handlers\n@handler.on('ORDER')\ndef handle_order_event(event):\n    if not event.before_changes:  # New order\n        print(f\"New order: {event.after_changes['order_number']}\")\n    elif not event.after_changes:  # Deleted order\n        print(f\"Order deleted: {event.before_changes['order_number']}\")\n    else:  # Updated order\n        print(f\"Order updated: {event.after_changes['order_number']}\")\n\n@handler.on('INVOICE')\ndef handle_invoice_event(event):\n    print(f\"Invoice event: {event.type}\")\n\n# In your web framework (Flask, FastAPI, Django, etc.)\nfrom flask import Flask, request\n\napp = Flask(__name__)\n\n@app.route('/webhooks', methods=['POST'])\ndef webhook_endpoint():\n    payload = request.get_json()\n    handler.process(payload)\n    return {'status': 'ok'}\n```\n\n## Data Consistency\n\nThe Distru API uses eventual consistency. Changes may take up to **1 second** to propagate to GET endpoints.\n\n**Best Practices:**\n- Use the returned data from create/update operations immediately\n- For critical operations, add a small delay before fetching updated data\n- Implement idempotency using unique identifiers\n\n```python\nimport time\n\n# Create an order\norder = client.orders.create(...)\n\n# The response contains the created order immediately\nprint(order['order_number'])  # Available immediately\n\n# If you need to fetch it again, wait briefly\ntime.sleep(1.5)\norder = client.orders.get(order['id'])  # Now guaranteed to be available\n```\n\n## Rate Limiting\n\nThe SDK automatically handles rate limiting with exponential backoff:\n\n- Automatic retry on 429 (rate limit) and 5xx errors\n- Exponential backoff: 1s, 2s, 4s, 8s, 10s (max)\n- Maximum 3 retries by default (configurable)\n- Respects `Retry-After` headers\n\n```python\n# Configure retry behavior\nclient = DistruClient(\n    api_token=\"your_token\",\n    max_retries=5,  # Increase max retries\n    timeout=60.0     # Increase timeout\n)\n```\n\n## Advanced Usage\n\n### Context Manager\n\n```python\n# Automatically close connection\nwith DistruClient(api_token=\"your_token\") as client:\n    products = client.products.list()\n    for product in products.auto_paginate():\n        print(product['name'])\n# Connection closed automatically\n```\n\n### Custom HTTP Client\n\n```python\nimport httpx\n\n# Use custom httpx client\nhttp_client = httpx.Client(\n    timeout=60.0,\n    limits=httpx.Limits(max_keepalive_connections=5)\n)\n\nclient = DistruClient(\n    api_token=\"your_token\",\n    http_client=http_client\n)\n```\n\n## Requirements\n\n- Python 3.8+\n- httpx >= 0.25.0\n- pydantic >= 2.0.0\n\n## Development\n\n### Setup\n\n```bash\n# Clone repository\ngit clone https://github.com/DistruApp/distru-api-sdk.git\ncd distru-api-sdk/python\n\n# Install in development mode\npip install -e \".[dev]\"\n```\n\n### Running Tests\n\n```bash\n# Run all tests\npytest\n\n# Run with coverage\npytest --cov=distru_sdk --cov-report=html\n\n# Run specific test file\npytest tests/test_products.py\n```\n\n### Code Quality\n\n```bash\n# Format code\nblack distru_sdk tests\n\n# Sort imports\nisort distru_sdk tests\n\n# Type checking\nmypy distru_sdk\n\n# Linting\nflake8 distru_sdk tests\n```\n\n## Support\n\n- **Documentation**: [GitHub Repository](https://github.com/DistruApp/distru-api-sdk)\n- **Issues**: [GitHub Issues](https://github.com/DistruApp/distru-api-sdk/issues)\n- **Email**: [support@distru.com](mailto:support@distru.com)\n\n## License\n\nMIT License - see [LICENSE](../LICENSE) file for details.\n\n## Changelog\n\nSee [CHANGELOG.md](CHANGELOG.md) for version history and changes.\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Official Python SDK for the Distru API - Cannabis supply chain management",
    "version": "1.0.0",
    "project_urls": {
        "Documentation": "https://github.com/DistruApp/distru-api-sdk/tree/main/python",
        "Homepage": "https://distru.com",
        "Issues": "https://github.com/DistruApp/distru-api-sdk/issues",
        "Repository": "https://github.com/DistruApp/distru-api-sdk"
    },
    "split_keywords": [
        "distru",
        " api",
        " sdk",
        " cannabis",
        " supply-chain",
        " inventory",
        " compliance"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "42bfff308079db94a5620cb28cbce1c189a4fa6aab11de97afc19bc0edaed213",
                "md5": "d67d0c5b380e331bce14c7f0abf44961",
                "sha256": "0319204b6a019c241e690d6c1a8c6eec11b0e8b81673e8ecd142aed65368f3fe"
            },
            "downloads": -1,
            "filename": "distru_sdk-1.0.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "d67d0c5b380e331bce14c7f0abf44961",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 32319,
            "upload_time": "2025-10-06T21:15:55",
            "upload_time_iso_8601": "2025-10-06T21:15:55.262905Z",
            "url": "https://files.pythonhosted.org/packages/42/bf/ff308079db94a5620cb28cbce1c189a4fa6aab11de97afc19bc0edaed213/distru_sdk-1.0.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "97d2364256ef7901cd6ee939040e21e81c653c69fa75fcdcf3110bc7322f5614",
                "md5": "87f32de0d9b44493b82898bffc815b34",
                "sha256": "e11d0dcad90feb8e6ffc5dd1a01f216867470f8d2919b994e1905fe6e8dd3f6e"
            },
            "downloads": -1,
            "filename": "distru_sdk-1.0.0.tar.gz",
            "has_sig": false,
            "md5_digest": "87f32de0d9b44493b82898bffc815b34",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 28467,
            "upload_time": "2025-10-06T21:15:56",
            "upload_time_iso_8601": "2025-10-06T21:15:56.417501Z",
            "url": "https://files.pythonhosted.org/packages/97/d2/364256ef7901cd6ee939040e21e81c653c69fa75fcdcf3110bc7322f5614/distru_sdk-1.0.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-10-06 21:15:56",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "DistruApp",
    "github_project": "distru-api-sdk",
    "github_not_found": true,
    "lcname": "distru-sdk"
}
        
Elapsed time: 2.19327s