Skip to main content

Async Python wrapper for the ShipStation API

Project description

ShipStation Interaction / Automation

Type-Check Linting Code style: black Validation: Pydantic v2 Python 3.13 PyPI - Version PyPI - License

Async Python client for ShipStation V1 and V2 APIs with full type hints.

Features

  • Full V1 & V2 API Support: Works with both ShipStation API versions
  • Async/Await: Built on httpx for efficient async HTTP requests
  • Type Safety: Complete TypedDict definitions for all request/response types
  • Connection Pooling: Efficient connection reuse for concurrent requests
  • Portal Pattern: Clean, organized API with dedicated portals for each resource

Install

pip

pip install AsyncShipStation

Manual

git clone git@github.com:sudoDeVinci/AsyncShipStation.git
cd AsyncShipStation
pip install -r requirements.txt

Setup

Create a .env file to store your keys. The library supports both V1 and V2 APIs:

# V2 API Key (recommended for most operations)
SHIP_STATION_V2=your_v2_api_key

# V1 API Key and Secret (required for orders endpoint)
SHIP_STATION_V1=your_v1_api_key
SHIP_STATION_SECRET=your_v1_secret

Configuring the Client

from AsyncShipStation import ShipStationClient

# Configure with both V1 and V2 credentials
ShipStationClient.configure(
    v2_key="your_v2_api_key",
    v1_key="your_v1_api_key",
    v1_secret="your_v1_secret",
)

Client Lifecycle

The library uses a shared httpx.AsyncClient under the hood. You have two options for managing it:

Option 1: Let it auto-start (simple)

The client starts automatically on first request. Just remember to close it when done:

import asyncio
import os
from dotenv import load_dotenv
from AsyncShipStation import ShipStationClient, InventoryPortal

load_dotenv()
API_KEY: str | None = os.getenv("API_KEY")

async def main() -> None:
    ShipStationClient.configure(api_key=API_KEY)

    # Connection pool starts on first request
    status, warehouses = await InventoryPortal.list_warehouses(page_size=10)
    print(f"Status: {status}, Warehouses: {warehouses}")
    
    ...

    # Clean up when done
    await ShipStationClient.close()


if __name__ == "__main__":
    asyncio.run(main())

Option 2: Use the async context manager (recommended)

Scoped usage where you want automatic cleanup:

import asyncio
import os
from dotenv import load_dotenv
from AsyncShipStation import ShipStationClient, InventoryPortal

load_dotenv()
API_KEY: str | None = os.getenv("API_KEY")

async def main() -> None:
    ShipStationClient.configure(api_key=API_KEY)

    async with InventoryPortal.scoped_client() as _:
        status, warehouses = await InventoryPortal.list_warehouses(page_size=10)
        print(f"Status: {status}, Warehouses: {warehouses}")
        
        ...
     
        # Client closes automatically when exiting the context

if __name__ == "__main__":
    asyncio.run(main())

Concurrent Requests

The client uses connection pooling, so concurrent requests share connections efficiently:

import asyncio
from AsyncShipStation import (
    BatchPortal,
    InventoryPortal,
    LabelPortal,
    ShipStationClient,
)

        ...

ShipStationClient.configure(api_key=API_KEY)
async with ShipStationClient.scoped_client() as _:
    results = await asyncio.gather(
        InventoryPortal.list_warehouses(),
        InventoryPortal.list(),
        BatchPortal.list(),
        LabelPortal.list(),
    )

for status, data in results:
    if status in (200, 207, 201):
        print(f"Success :: {data}")
    else:
        print(f"Error :: {data}")
    
        ...

Rate Limiting

Accounts that send too many requests in quick succession will receive a 429 Too Many Requests error response and include a Retry-After header with the number of seconds to wait for. By default we get 200 requests per minute. ShipStation has bulk op endpoints. These only count as a single request.

Endpoints

/batches Process labels in bulk and receive a large number of labels and customs forms in bulk responses. Batching is ideal for workflows that need to process hundreds or thousands of labels quickly. 200

/carriers Retreive useful details about the carriers connected to your accounts, including carrier IDs, service IDs, advanced options, and available carrier package types.

/fulfillments Manage fulfillments which represent completed shipments. Create fulfillments to mark orders as shipped with tracking information and notify customers and marketplaces.

/inventory Manage inventory, adjust quantities, and handle warehouses and locations.

/labels Purchase and print shipping labels for any carrier active on your account. The labels endpoint also supports creating return labels, voiding labels, and getting label details like tracking.

/manifests A manifest is a document that provides a list of the day's shipments. It typically contains a barcode that allows the pickup driver to scan a single document to register all shipments, rather than scanning each shipment individually.

/rates (V2) Calculate and estimate shipping rates across multiple carriers. Supports both full rate calculation with shipment details and quick rate estimates.

/shipments (V2) Create, retrieve, and manage shipments. Includes support for getting rates, adding/removing tags, and cancellation.

/tags (V2) Manage tags for organizing shipments and orders. Create, list, and delete tags.

/warehouses (V2) Retrieve warehouse information including origin addresses for shipments.

Workflow Automation Demo

The library includes a workflow demonstration script (workflow_demo.py) that shows how to automate the order-to-label process:

  1. Fetch orders from the V1 API
  2. Group orders by carrier for efficient batch processing
  3. Create shipments in the V2 API
  4. Estimate rates across carriers
  5. Create batches for bulk label processing

Running the Demo

# Ensure your .env file is configured with API keys
python workflow_demo.py

Safety Features

The workflow script includes multiple safety features:

  • DRY-RUN mode (default): Only simulates operations, no actual API modifications
  • SIMULATE mode: Prints what would happen without making any API calls
  • LIVE mode: Actually executes operations (requires explicit confirmation)
  • test_label flag: Use test labels to avoid charges during development
  • Rate confirmation: Pause before purchasing labels for human review
from workflow_demo import WorkflowConfig, ExecuteMode

config = WorkflowConfig(
    execute_mode=ExecuteMode.DRY_RUN,  # Safe default
    use_test_labels=True,               # Use test labels when purchasing
    require_rate_confirmation=True,     # Pause for confirmation
    max_orders_to_process=10,           # Limit orders for safety
)

Production Checklist

Before running in LIVE mode against production:

  • Test with a ShipStation sandbox/test account first
  • Always use test_label=True for initial label purchases
  • Set max_orders_to_process to a small number initially
  • Review rate estimates before confirming purchases
  • Implement proper error handling and logging
  • Set up monitoring for API rate limits (200 requests/minute)

V2 API Portals

RatesPortal

from AsyncShipStation import RatesPortal, ShipStationClient

async with ShipStationClient.scoped_client("v2"):
    # Calculate rates for an existing shipment
    status, rates = await RatesPortal.calculate_rates(
        carrier_ids=["se-123456"],
        shipment_id="se-shipment-id",
    )
    
    # Quick rate estimate without creating a shipment
    status, estimates = await RatesPortal.estimate_rates(
        carrier_ids=["se-123456", "se-789012"],
        from_country_code="US",
        from_postal_code="78701",
        to_country_code="US",
        to_postal_code="90210",
        weight={"value": 1.5, "unit": "pound"},
    )

TagsPortal

from AsyncShipStation import TagsPortal

async with ShipStationClient.scoped_client("v2"):
    # List all tags
    status, tags = await TagsPortal.list()
    
    # Create a new tag
    status, tag = await TagsPortal.create("Priority", color="red")
    
    # Delete a tag
    status, _ = await TagsPortal.delete("Priority")

WarehousePortal

from AsyncShipStation import WarehousePortal

async with ShipStationClient.scoped_client("v2"):
    # List warehouses
    status, warehouses = await WarehousePortal.list()
    
    # Get specific warehouse
    status, warehouse = await WarehousePortal.get_by_id("wh-123456")

ShipmentPortal (Extended)

from AsyncShipStation import ShipmentPortal

async with ShipStationClient.scoped_client("v2"):
    # Create shipments
    status, result = await ShipmentPortal.create([
        {
            "carrier_id": "se-123456",
            "service_code": "usps_priority_mail",
            "ship_to": {...},
            "ship_from": {...},
            "packages": [...],
        }
    ])
    
    # Get rates for a shipment
    status, rates = await ShipmentPortal.get_rates("se-shipment-id")
    
    # Add/remove tags
    await ShipmentPortal.add_tag("se-shipment-id", "Priority")
    await ShipmentPortal.remove_tag("se-shipment-id", "Priority")
    
    # Cancel a shipment (before label purchase)
    await ShipmentPortal.cancel_by_id("se-shipment-id")

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

asyncshipstation-0.1.1.3.tar.gz (34.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

asyncshipstation-0.1.1.3-py3-none-any.whl (54.3 kB view details)

Uploaded Python 3

File details

Details for the file asyncshipstation-0.1.1.3.tar.gz.

File metadata

  • Download URL: asyncshipstation-0.1.1.3.tar.gz
  • Upload date:
  • Size: 34.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.11

File hashes

Hashes for asyncshipstation-0.1.1.3.tar.gz
Algorithm Hash digest
SHA256 8449366da4bcbbfbe751f8e7592643558a7db0b7bf85e6b09a32a4f0c8b114fd
MD5 50022d4bf4f106f962fcc811c8584404
BLAKE2b-256 9a1161eed97aba7ad86d40320221481d5e0d6335ea66c43b6e6acadb16dde59b

See more details on using hashes here.

File details

Details for the file asyncshipstation-0.1.1.3-py3-none-any.whl.

File metadata

File hashes

Hashes for asyncshipstation-0.1.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 bd1ef231d642f6926be518a34d226cee6a07629b69063f5ee0547b11c32b95bd
MD5 f623876ef1ee4a020d159c9466e32ebf
BLAKE2b-256 2c24893f33f6859a88db3dbebcfb39012ca98a61d2ca28ad684acbf37feafa02

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page