Skip to content
This repository was archived by the owner on Jan 9, 2026. It is now read-only.

konadmin/odyn

Repository files navigation

Konspec Logo

Odyn

A modern, typed, and robust Python client for the Microsoft Dynamics 365 Business Central OData V4 API

GitHub Python 3.12+ License Documentation Tests codecov Code style: ruff

PyPI version


PyPi link

Odyn provides a convenient and feature-rich interface for interacting with Microsoft Dynamics 365 Business Central, including automatic retry mechanisms, pagination handling, and pluggable authentication sessions.

Features

  • Type Safety: Fully typed with comprehensive type annotations for better IDE support and runtime safety.
  • Automatic Retry Logic: Built-in exponential backoff retry mechanism for handling transient network failures.
  • Smart Pagination: Automatic handling of OData pagination with transparent multi-page data retrieval.
  • Flexible Authentication: Pluggable requests.Session based authentication. Comes with BearerAuthSession and BasicAuthSession out of the box.
  • Comprehensive Logging: Detailed logging with loguru integration for easy debugging and monitoring.
  • Production Ready: Robust error handling, validation, and timeout management.
  • Extensible Design: Easily extendable to support custom authentication strategies or other session-level features.

Quick Install

pip install odyn

Or see full installation instructions for pip, uv, and poetry.

Quick Start

from odyn import Odyn, BearerAuthSession

# Create an authenticated session
session = BearerAuthSession("your-access-token")

# Initialize the client
client = Odyn(
    base_url="https://your-tenant.businesscentral.dynamics.com/api/v2.0/",
    session=session
)

# Fetch data with automatic pagination
customers = client.get("customers")
print(f"Retrieved {len(customers)} customers")

# Use OData query parameters
filtered_customers = client.get(
    "customers",
    params={
        "$top": 10,
        "$filter": "contains(name, 'Adventure')",
        "$select": "id,name,phoneNumber"
    }
)

Requirements

  • Python 3.12+
  • requests (≥2.32.4)
  • loguru (≥0.7.3)

Documentation

Getting Started

Usage Guides

Advanced Topics

  • Configuration - Timeouts, retries, and advanced settings
  • Logging - Logging behavior and customization

Reference

Examples

Bearer Token Authentication

from odyn import Odyn, BearerAuthSession

# Create a session with your bearer token
session = BearerAuthSession(token="your-access-token")

# Initialize the client
client = Odyn(
    base_url="https://api.businesscentral.dynamics.com/v2.0/your-tenant-id/production/",
    session=session,
)

# Get all customers with automatic pagination handling
customers = client.get("customers")
print(f"Retrieved {len(customers)} customers")

# Get the top 10 items, filtering by name and selecting specific fields
items = client.get(
    "items",
    params={
        "$top": 10,
        "$filter": "contains(displayName, 'Desk')",
        "$select": "id,displayName,itemCategoryCode",
    },
)
print(f"Filtered items: {items}")

Basic Authentication

from odyn import Odyn, BasicAuthSession

# Create a session with your username and web service access key
session = BasicAuthSession(username="your-username", password="your-web-service-access-key")

# Initialize the client
client = Odyn(
    base_url="https://api.businesscentral.dynamics.com/v2.0/your-tenant-id/production/",
    session=session,
)

# Get all vendors
vendors = client.get("vendors")
print(f"Retrieved {len(vendors)} vendors")

Advanced Configuration

from odyn import Odyn, BearerAuthSession
from loguru import logger

# Bind a custom component to the logger for easy filtering
custom_logger = logger.bind(component="business-central-client")

# Create a session with custom retry settings
# This example uses a more aggressive retry strategy than the default.
session = BearerAuthSession(
    token="your-token",
    retries=10,
    backoff_factor=0.5,
    status_forcelist=[408, 429, 500, 502, 503, 504],
)

# Initialize a client with a custom timeout and the custom logger
client = Odyn(
    base_url="https://api.businesscentral.dynamics.com/v2.0/your-tenant-id/production/",
    session=session,
    logger=custom_logger,
    timeout=(10, 60),  # 10s connect timeout, 60s read timeout
)

Error Handling

from odyn import (
    Odyn,
    BearerAuthSession,
    InvalidURLError,
    InvalidSessionError,
    InvalidTimeoutError,
    InvalidLoggerError,
)
import requests

try:
    # Intentionally create an invalid session
    session = BearerAuthSession(token=None) # type: ignore
    client = Odyn(base_url="not-a-valid-url", session=session)
    client.get("customers")

except InvalidURLError as e:
    print(f"Invalid URL: {e}")
except InvalidSessionError as e:
    print(f"Invalid session: {e}")
except InvalidTimeoutError as e:
    print(f"Invalid timeout configuration: {e}")
except InvalidLoggerError as e:
    print(f"Invalid logger object provided: {e}")
except requests.exceptions.HTTPError as e:
    # Handle HTTP errors (e.g., 401 Unauthorized, 404 Not Found)
    print(f"HTTP Error: {e.response.status_code} - {e.response.text}")
except requests.exceptions.RequestException as e:
    # Handle network-related errors (e.g., connection refused)
    print(f"Network Error: {e}")
except Exception as e:
    print(f"An unexpected error occurred: {e}")

Contributing

We welcome contributions! Please see our Contributing Guide for details.

Development Setup

# Clone the repository
git clone https://github.com/konspec/odyn.git
cd odyn

# Install dependencies (we recommend using uv)
uv pip install -e .[dev]

# Run tests
pytest

# Run linting
ruff check .

License

This project is licensed under the MIT License - see the LICENSE file for details.

Support

Related


Konkan Speciality Polyproducts Pvt Ltd.

About

Python adapter for MS Dynamics 365 Business Central OData V4 API.

Topics

Resources

Contributing

Stars

2 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors

Languages