Installation
Copy
pip install crossborderly
Quick Start
Copy
from crossborderly import CrossBorderly
client = CrossBorderly(
api_key="pk_your_api_key",
environment="production" # or "sandbox"
)
# Create an order
order = client.orders.create(
idempotency_key="my-order-123",
sender={...},
receiver={...},
parcel_details={...}
)
print(f"Tracking: {order.parcel.tracking_number}")
Configuration
Copy
from crossborderly import CrossBorderly
client = CrossBorderly(
api_key="pk_your_api_key",
environment="production",
timeout=30, # seconds
max_retries=3,
debug=False
)
Orders
Create Order
Copy
order = client.orders.create(
idempotency_key=f"order-{int(time.time())}",
sender={
"full_name": "John Smith",
"phone": "+1 305-555-0123",
"address": {
"line1": "1234 Main St",
"city": "Miami",
"state": "FL",
"zip_code": "33101",
"country": "US"
}
},
receiver={
"full_name": "María García",
"phone": "+593 99 123 4567",
"national_id": "1234567890",
"address": {
"line1": "Av. 9 de Octubre 123",
"city": "Guayaquil",
"province": "Guayas",
"zip_code": "090101",
"country": "EC"
}
},
parcel_details={
"weight_lbs": 2.5,
"declared_value": 99.99
}
)
print(order.parcel.tracking_number)
print(order.parcel.label_url)
Void Order
Copy
result = client.orders.void(
idempotency_key="void-123",
tracking_numbers=["CBECUSD123456789"],
reason="Customer cancelled"
)
print(f"Voided: {result.voided}")
Manifests
Submit Manifest
Copy
manifest = client.manifests.submit(
idempotency_key="manifest-123",
awb_number="180-12345678",
flight_number="LA2480",
flight_date="2024-12-25",
origin_airport="MIA",
destination_airport="UIO",
carrier="LATAM Airlines",
country="EC",
parcels=[
{"tracking_number": "CBECUSD123456789"},
{"tracking_number": "CBECUSD123456790"}
]
)
print(f"Linked: {manifest.linked}")
Tracking
Single Parcel
Copy
tracking = client.tracking.get(
"CBECUSD123456789",
include_history=True
)
print(f"Status: {tracking.status}")
for event in tracking.history:
print(f"{event.timestamp}: {event.status_name}")
Batch Tracking
Copy
results = client.tracking.batch(
tracking_numbers=["CBECUSD123456789", "CBECUSD123456790"],
include_history=False
)
for parcel in results.results:
print(f"{parcel.tracking_number}: {parcel.status}")
Labels
Download Label
Copy
# Get label info
label = client.labels.get("CBECUSD123456789")
print(f"Download: {label.label_url}")
# Download as bytes
pdf_bytes = client.labels.download("CBECUSD123456789", format="PDF")
with open("label.pdf", "wb") as f:
f.write(pdf_bytes)
Reprint Label
Copy
reprint = client.labels.reprint(
"CBECUSD123456789",
idempotency_key="reprint-123",
label_format="PDF"
)
print(f"New URL: {reprint.label_url}")
Webhooks
Verify Webhook Signature
Copy
from crossborderly import verify_webhook_signature
from flask import Flask, request
app = Flask(__name__)
@app.route('/webhooks', methods=['POST'])
def handle_webhook():
signature = request.headers.get('X-CrossBorderly-Signature')
if not verify_webhook_signature(
request.data,
signature,
webhook_secret
):
return 'Invalid signature', 401
event = request.json
# Process webhook...
return 'OK', 200
Error Handling
Copy
from crossborderly.exceptions import (
CrossBorderlyError,
ValidationError,
RateLimitError,
NotFoundError
)
try:
order = client.orders.create(...)
except ValidationError as e:
print(f"Validation failed: {e.errors}")
except RateLimitError as e:
print(f"Rate limited, retry after: {e.retry_after}")
except NotFoundError as e:
print(f"Resource not found: {e.message}")
except CrossBorderlyError as e:
print(f"API error: {e.code} - {e.message}")
Async Support
Copy
import asyncio
from crossborderly import AsyncCrossBorderly
async def main():
client = AsyncCrossBorderly(api_key="pk_your_api_key")
order = await client.orders.create(...)
print(order.parcel.tracking_number)
await client.close()
asyncio.run(main())
Context Manager
Copy
with CrossBorderly(api_key="pk_your_api_key") as client:
order = client.orders.create(...)
print(order.parcel.tracking_number)
# Connection automatically closed
Type Hints
The SDK includes full type hints for IDE support:Copy
from crossborderly.types import (
CreateOrderRequest,
CreateOrderResponse,
ParcelStatus
)
request: CreateOrderRequest = {
"idempotency_key": "order-123",
"sender": {...},
"receiver": {...},
"parcel_details": {...}
}
response: CreateOrderResponse = client.orders.create(**request)