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
Metadata
Release files for pydelhivery 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pydelhivery-0.1.2.tar.gz | 20.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pydelhivery-0.1.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 39.6 kB
Release files / pydelhivery-0.1.2.tar.gz
| Download URL | pydelhivery-0.1.2.tar.gz |
|---|---|
| Size | 20.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
252eeed5e6a33541e6f8ee4aec64aaf8f23e79afe9c298fc3eaaf29f34e9feee
|
|
BLAKE2b-256 checksum How to use checksums |
0faa518cebaf548a511f5979bdde47814a2e629e6207d5065934d6eedacd2c9a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jan 13, 2026.
Transparency logRelease files / pydelhivery-0.1.2-py3-none-any.whl
| Download URL | pydelhivery-0.1.2-py3-none-any.whl |
|---|---|
| Size | 18.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7548d22fb286387bb2019c1394aa48de241c8d2eb3f685a433dfcbd31658c32d
|
|
BLAKE2b-256 checksum How to use checksums |
4d49b6faf9ad1e132d22edfe4e9750c314653bedaa24cd59b5422aaf84f28d57
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jan 13, 2026.
Transparency log