Thin Python Wrapper for India's Biggest 3rd Party Logistics Service Provider
Project description
pydelhivery
A Python wrapper for Delhivery's B2C API, providing a clean and type-safe interface for integrating with India's largest third-party logistics service provider.
This library is based on the Delhivery Developer Portal Documentation.
Note: This is an independent, open-source project. The author is not affiliated with Delhivery in any way. This project is provided as-is in the hope that others find it helpful for integrating with Delhivery's APIs.
Features
- ✅ Pincode Serviceability Check - Verify if a location is serviceable for delivery
- ✅ Warehouse Management - Create and update warehouse configurations
- ✅ Shipping Cost Calculation - Calculate shipping charges before creating orders
- ✅ Order Management - Create, update, and cancel shipments
- ✅ Pickup Scheduling - Schedule pickups for your shipments
- ✅ Tracking - Track shipments using waybill numbers
- ✅ Label Generation - Generate packing slips and shipping labels
- ✅ Type-Safe - Built with Pydantic for robust data validation
- ✅ Comprehensive Logging - Built-in logging for debugging and monitoring
Installation
pip install pydelhivery
Or using uv:
uv add pydelhivery
Configuration
Set up your Delhivery API credentials using environment variables:
# Required
DELHIVERY_AUTH_TOKEN=your_auth_token_here
# Optional (defaults to https://track.delhivery.com)
DELHIVERY_API_BASE_URL=https://track.delhivery.com
You can use a .env file in your project root:
DELHIVERY_AUTH_TOKEN=your_auth_token_here
DELHIVERY_API_BASE_URL=https://track.delhivery.com
Quick Start
from pydelhivery import DelhiveryIntegration
from pydelhivery.models.DelhiveryModels import (
DelhiveryShippingCostRequest,
DelhiveryOrderTrackingRequest,
)
# Initialize the client
client = DelhiveryIntegration()
# Check pincode serviceability
pincode_response = client.check_pincode_serviceability("560001")
print(f"Serviceable: {pincode_response.is_serviceable}")
print(f"COD Supported: {pincode_response.supports_cod}")
# Calculate shipping cost
cost_request = DelhiveryShippingCostRequest(
md="E", # Express
cgm=500, # 500 grams
o_pin=560001, # Origin pincode
d_pin=110053, # Destination pincode
ss="Delivered",
pt="Pre-paid"
)
shipping_cost = client.calculate_shipping_cost(cost_request)
print(f"Shipping cost: {shipping_cost.total_amount}")
# Track an order
tracking_request = DelhiveryOrderTrackingRequest(waybills=["WB1234567890"])
tracking_response = client.track_orders(tracking_request)
print(f"Status: {tracking_response.latest_status}")
API Reference
DelhiveryIntegration
The main client class for interacting with Delhivery APIs.
Methods
check_pincode_serviceability(pincode: str, filter_codes: Optional[str] = None) -> DelhiveryPincodeResponse
Check if a pincode is serviceable for delivery.
Parameters:
pincode(str): The pincode to check (6-digit)filter_codes(str, optional): Optional filter parameter
Returns: DelhiveryPincodeResponse with serviceability information
Example:
response = client.check_pincode_serviceability("560001")
if response.is_serviceable:
print(f"COD: {response.supports_cod}, Prepaid: {response.supports_prepaid}")
create_warehouse(warehouse: DelhiveryWarehouseCreateRequest) -> bool
Create a new warehouse in Delhivery system.
Parameters:
warehouse: Warehouse configuration (Pydantic model)
Returns: bool - True if successful
Example:
from pydelhivery.models.WareHouseModels import DelhiveryWarehouseCreateRequest
warehouse = DelhiveryWarehouseCreateRequest(
name="My Warehouse",
registered_name="My Company Pvt Ltd",
address="123 Main Street",
city="Bangalore",
pin="560001",
phone="9876543210",
email="warehouse@example.com",
return_address="123 Main Street",
return_city="Bangalore",
return_state="Karnataka",
return_pin="560001"
)
client.create_warehouse(warehouse)
update_warehouse(warehouse_update: DelhiveryWarehouseUpdateRequest) -> bool
Update an existing warehouse configuration.
Parameters:
warehouse_update: Warehouse update payload
Returns: bool - True if successful
calculate_shipping_cost(request_data: DelhiveryShippingCostRequest) -> DelhiveryInvoiceChargeItem
Calculate shipping cost for a shipment.
Parameters:
request_data: Shipping cost request with origin, destination, weight, etc.
Returns: DelhiveryInvoiceChargeItem with cost breakdown
Example:
from pydelhivery.models.DelhiveryModels import DelhiveryShippingCostRequest
request = DelhiveryShippingCostRequest(
md="E", # Express or Surface
cgm=1000, # Weight in grams
o_pin=560001,
d_pin=110053,
ss="Delivered", # Status
pt="Pre-paid" # Payment type
)
cost = client.calculate_shipping_cost(request)
print(f"Total: {cost.total_amount}")
create_order(shipment_config: ShipmentConfig, order_id: UUID) -> DelhiveryCMUCreateResponse
Create a new shipment order.
Parameters:
shipment_config: Shipment configurationorder_id: Unique order identifier (UUID)
Returns: DelhiveryCMUCreateResponse with waybill numbers
update_order(order_update: DelhiveryOrderUpdateRequest) -> Dict[str, Any]
Update an existing order.
Parameters:
order_update: Order update payload
Returns: API response dictionary
schedule_pickup(pickup_request: DelhiveryPickupRequest) -> DelhiveryPickupSuccessResponse
Schedule a pickup for shipments.
Parameters:
pickup_request: Pickup request with date, time, and location
Returns: DelhiveryPickupSuccessResponse with pickup details
Example:
from pydelhivery.models.DelhiveryModels import DelhiveryPickupRequest
pickup = DelhiveryPickupRequest(
pickup_date="2025-12-31",
pickup_time="11:00:00",
pickup_location="My Warehouse",
expected_package_count=5
)
response = client.schedule_pickup(pickup)
generate_shipping_label(label_request: DelhiveryPackingSlipRequest) -> DelhiveryPackingSlipResponse
Generate packing slip/shipping label for waybills.
Parameters:
label_request: Label request with waybill number and format options
Returns: DelhiveryPackingSlipResponse with PDF links
Example:
from pydelhivery.models.DelhiveryModels import DelhiveryPackingSlipRequest
label_request = DelhiveryPackingSlipRequest(
waybill="WB1234567890",
pdf=True,
pdf_size="A4"
)
response = client.generate_shipping_label(label_request)
print(f"PDF URL: {response.pdf_links[0]}")
track_orders(tracking_request: DelhiveryOrderTrackingRequest) -> DelhiveryTrackingResponse
Track one or more shipments.
Parameters:
tracking_request: Tracking request with waybill numbers
Returns: DelhiveryTrackingResponse with tracking details
Example:
from pydelhivery.models.DelhiveryModels import DelhiveryOrderTrackingRequest
request = DelhiveryOrderTrackingRequest(waybills=["WB1234567890", "WB0987654321"])
response = client.track_orders(request)
print(f"Latest Status: {response.latest_status}")
print(f"Location: {response.latest_status_location}")
cancelShipment(waybill: str) -> None
Cancel a shipment.
Parameters:
waybill: Waybill number to cancel
Example:
client.cancelShipment("WB1234567890")
Error Handling
The library uses standard Python exceptions:
ValueError: Raised for invalid input or missing configurationrequests.exceptions.HTTPError: Raised for HTTP errors from the APIrequests.exceptions.RequestException: Raised for network/request errors
All errors are logged using the built-in logger.
Example:
try:
response = client.check_pincode_serviceability("560001")
except ValueError as e:
print(f"Invalid input: {e}")
except requests.exceptions.HTTPError as e:
print(f"API error: {e.response.status_code} - {e.response.text}")
Logging
The library uses Python's logging module. Logs are automatically configured when you import the package.
from pydelhivery import logger
logger.info("Custom log message")
logger.debug("Debug information")
logger.error("Error occurred")
Development
Prerequisites
- Python >= 3.12
uv(recommended) orpip
Setup
- Clone the repository:
git clone <repository-url>
cd pydelhivery
- Install dependencies:
uv sync
Or with pip:
pip install -e ".[dev]"
- Set up environment variables:
cp .env.example .env
# Edit .env with your credentials
Project Structure
pydelhivery/
├── src/
│ └── pydelhivery/
│ ├── __init__.py
│ ├── DelhiveryApis.py # Main API client
│ ├── models/ # Pydantic models
│ │ ├── DelhiveryModels.py
│ │ ├── ShippingCostModel.py
│ │ ├── ShippingCreateRequest.py
│ │ ├── Tracking.py
│ │ └── WareHouseModels.py
│ └── utils/ # Utilities
│ ├── constants.py
│ └── logger.py
├── tests/ # Test suite
├── pyproject.toml # Project configuration
└── README.md
Developer Guidelines
Code Style
- Follow PEP 8 style guidelines
- Use type hints for all function parameters and return types
- Use Pydantic models for all API request/response data
- Maximum line length: 100 characters (where reasonable)
Adding New API Methods
-
Create Pydantic Models (if needed):
- Add request models in the appropriate file under
models/ - Add response models if the API returns structured data
- Use field validators for input validation
- Add request models in the appropriate file under
-
Add API Method:
- Add the method to
DelhiveryIntegrationclass inDelhiveryApis.py - Follow the existing pattern:
def new_method(self, request: RequestModel) -> ResponseModel: """ Brief description of what the method does. Args: request: Description of request parameter Returns: Description of return value Raises: ValueError: When auth token is missing requests.exceptions.HTTPError: For API errors """ if not self.auth_token: raise ValueError("DELHIVERY_AUTH_TOKEN is not configured") url = f"{self.base_url}/api/endpoint" headers = self._get_headers() payload = request.model_dump() try: logger.info("Description of action") response = requests.post(url, headers=headers, json=payload, timeout=20) response.raise_for_status() logger.info("Action successful") parsed = self._parse_response(response, ResponseModel) return parsed except requests.exceptions.HTTPError as e: logger.error(f"Action failed | Status: {e.response.status_code}") raise except requests.exceptions.RequestException as e: logger.error(f"Request error: {e}") raise
- Add the method to
-
Use Existing Helpers:
- Use
_get_headers()for authentication headers - Use
_parse_response()for parsing API responses into Pydantic models - Always use the logger for important events
- Use
-
Error Handling:
- Always check for
auth_tokenat the start of public methods - Use
response.raise_for_status()to handle HTTP errors - Log errors with context (status code, response text)
- Re-raise exceptions to allow caller to handle them
- Always check for
-
Logging:
- Use
logger.info()for successful operations - Use
logger.debug()for detailed information (response bodies, etc.) - Use
logger.error()for errors - Include relevant context in log messages (pincodes, waybills, etc.)
- Use
Testing
- Write tests for new functionality in the
tests/directory - Use the
scratch/main.pyfile for manual testing and experimentation - Ensure all tests pass before submitting changes
Documentation
- Update this README when adding new features
- Include docstrings for all public methods
- Add usage examples for new APIs
- Document any breaking changes
Pull Request Process
- Create a feature branch from
main - Make your changes following the guidelines above
- Ensure all tests pass
- Update documentation
- Submit a pull request with a clear description
Model Design Guidelines
- Use Pydantic
BaseModelfor all data structures - Use
Fieldfor field descriptions and validation - Use
field_validatorfor custom validation logic - Use appropriate types (
str,int,float,bool,Optional,List, etc.) - Use
Literaltypes for enum-like string values - Include descriptions for all fields using
Field(..., description="...") - Use
exclude_none=Trueinmodel_dump()when updating existing resources
API Response Handling
- Always use
_parse_response()for structured responses - Handle XML responses separately (e.g.,
DelhiveryInvoiceChargeItem.from_xml()) - Validate responses using Pydantic models
- Raise meaningful errors when validation fails
Environment Configuration
- Use
dotenvfor loading environment variables - Provide sensible defaults where appropriate
- Document all required and optional environment variables
- Use
os.getenv()with defaults for optional configuration
Resources
- Delhivery Developer Portal Documentation - Official API documentation and reference
- Delhivery Official Website
License
See LICENSE file for details.
Contributing
Contributions are welcome! Please read the developer guidelines above and submit a pull request.
Support
For issues and questions:
- Check existing issues in the repository
- Create a new issue with details about your problem
- Include relevant error messages and code snippets
- Refer to the Delhivery Developer Portal Documentation for API details
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pydelhivery-0.1.2.tar.gz.
File metadata
- Download URL: pydelhivery-0.1.2.tar.gz
- Upload date:
- Size: 20.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
252eeed5e6a33541e6f8ee4aec64aaf8f23e79afe9c298fc3eaaf29f34e9feee
|
|
| MD5 |
3dc9a7755999d07f50d1d76cc9a4dcf3
|
|
| BLAKE2b-256 |
0faa518cebaf548a511f5979bdde47814a2e629e6207d5065934d6eedacd2c9a
|
Provenance
The following attestation bundles were made for pydelhivery-0.1.2.tar.gz:
Publisher:
python-publish.yml on tejastee/pydelhivery
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pydelhivery-0.1.2.tar.gz -
Subject digest:
252eeed5e6a33541e6f8ee4aec64aaf8f23e79afe9c298fc3eaaf29f34e9feee - Sigstore transparency entry: 819831218
- Sigstore integration time:
-
Permalink:
tejastee/pydelhivery@df2ee4e4de247ba914bc8893e2df59b6f58735f9 -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/tejastee
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@df2ee4e4de247ba914bc8893e2df59b6f58735f9 -
Trigger Event:
release
-
Statement type:
File details
Details for the file pydelhivery-0.1.2-py3-none-any.whl.
File metadata
- Download URL: pydelhivery-0.1.2-py3-none-any.whl
- Upload date:
- Size: 18.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7548d22fb286387bb2019c1394aa48de241c8d2eb3f685a433dfcbd31658c32d
|
|
| MD5 |
077ec91af5836efa56aa502600b1710e
|
|
| BLAKE2b-256 |
4d49b6faf9ad1e132d22edfe4e9750c314653bedaa24cd59b5422aaf84f28d57
|
Provenance
The following attestation bundles were made for pydelhivery-0.1.2-py3-none-any.whl:
Publisher:
python-publish.yml on tejastee/pydelhivery
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pydelhivery-0.1.2-py3-none-any.whl -
Subject digest:
7548d22fb286387bb2019c1394aa48de241c8d2eb3f685a433dfcbd31658c32d - Sigstore transparency entry: 819831230
- Sigstore integration time:
-
Permalink:
tejastee/pydelhivery@df2ee4e4de247ba914bc8893e2df59b6f58735f9 -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/tejastee
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@df2ee4e4de247ba914bc8893e2df59b6f58735f9 -
Trigger Event:
release
-
Statement type: