Back to skills
SkillHub ClubShip Full StackFull Stack

shippo

Shippo — shipping labels, rates comparison, package tracking, address validation, and returns.

Packaged view

This page reorganizes the original catalog entry around fit, installability, and workflow context first. The original raw source lives below.

Stars
3,131
Hot score
99
Updated
March 20, 2026
Overall rating
C4.0
Composite score
4.0
Best-practice grade
B84.0

Install command

npx @skill-hub/cli install openclaw-skills-shippo

Repository

openclaw/skills

Skill path: skills/aiwithabidi/shippo

Shippo — shipping labels, rates comparison, package tracking, address validation, and returns.

Open repository

Best for

Primary workflow: Ship Full Stack.

Technical facets: Full Stack.

Target audience: everyone.

License: MIT.

Original source

Catalog source: SkillHub Club.

Repository owner: openclaw.

This is still a mirrored public skill entry. Review the repository before installing into production workflows.

What it helps with

  • Install shippo into Claude Code, Codex CLI, Gemini CLI, or OpenCode workflows
  • Review https://github.com/openclaw/skills before adding shippo to shared team environments
  • Use shippo for development workflows

Works across

Claude CodeCodex CLIGemini CLIOpenCode

Favorites: 0.

Sub-skills: 0.

Aggregator: No.

Original source / Raw SKILL.md

---
name: shippo
description: "Shippo — shipping labels, rates comparison, package tracking, address validation, and returns."
homepage: https://www.agxntsix.ai
license: MIT
compatibility: Python 3.10+ (stdlib only — no dependencies)
metadata: {"openclaw": {"emoji": "📦", "requires": {"env": ["SHIPPO_API_TOKEN"]}, "primaryEnv": "SHIPPO_API_TOKEN", "homepage": "https://www.agxntsix.ai"}}
---

# 📦 Shippo

Shippo — shipping labels, rates comparison, package tracking, address validation, and returns.

## Requirements

| Variable | Required | Description |
|----------|----------|-------------|
| `SHIPPO_API_TOKEN` | ✅ | Shippo API token |


## Quick Start

```bash
# Create shipment & get rates
python3 {{baseDir}}/scripts/shippo.py create-shipment --from "JSON address" --to "JSON address" --parcel "JSON"

# List shipments
python3 {{baseDir}}/scripts/shippo.py list-shipments --results "25" --page "1"

# Get shipment details
python3 {{baseDir}}/scripts/shippo.py get-shipment <id>

# Get rates for shipment
python3 {{baseDir}}/scripts/shippo.py get-rates <id>

# Purchase shipping label
python3 {{baseDir}}/scripts/shippo.py purchase-label --rate <value>

# List label transactions
python3 {{baseDir}}/scripts/shippo.py list-transactions --results "25"

# Get label/transaction details
python3 {{baseDir}}/scripts/shippo.py get-transaction <id>

# Track a package
python3 {{baseDir}}/scripts/shippo.py track-package --carrier <value> --tracking-number <value>

# Validate an address
python3 {{baseDir}}/scripts/shippo.py validate-address --name <value> --street1 <value> --city <value> --state <value> --zip <value> --country "US"

# List saved parcels
python3 {{baseDir}}/scripts/shippo.py list-parcels

# Create a parcel template
python3 {{baseDir}}/scripts/shippo.py create-parcel --length <value> --width <value> --height <value> --weight <value>

# Create return shipment
python3 {{baseDir}}/scripts/shippo.py create-return --from "JSON" --to "JSON" --parcel "JSON" --is-return "true"

# List carrier accounts
python3 {{baseDir}}/scripts/shippo.py list-carriers
```

## Output Format

All commands output JSON by default.

## Script Reference

| Script | Description |
|--------|-------------|
| `{baseDir}/scripts/shippo.py` | Main CLI — all commands in one tool |

## Credits
Built by [M. Abidi](https://www.linkedin.com/in/mohammad-ali-abidi) | [agxntsix.ai](https://www.agxntsix.ai)
[YouTube](https://youtube.com/@aiwithabidi) | [GitHub](https://github.com/aiwithabidi)
Part of the **AgxntSix Skill Suite** for OpenClaw agents.

📅 **Need help setting up OpenClaw for your business?** [Book a free consultation](https://cal.com/agxntsix/abidi-openclaw)


---

## Skill Companion Files

> Additional files collected from the skill directory layout.

### _meta.json

```json
{
  "owner": "aiwithabidi",
  "slug": "shippo",
  "displayName": "Shippo",
  "latest": {
    "version": "1.0.0",
    "publishedAt": 1772823223146,
    "commit": "https://github.com/openclaw/skills/commit/3ff919b8a03acc3aeafed8ccf3e1fe327f890f85"
  },
  "history": []
}

```

### scripts/shippo.py

```python
#!/usr/bin/env python3
"""Shippo CLI — Shippo — shipping labels, rates comparison, package tracking, address validation, and returns.

Zero dependencies beyond Python stdlib.
"""

import argparse
import json
import os
import sys
import urllib.request
import urllib.error
import urllib.parse

API_BASE = "https://api.goshippo.com"


def get_env(name):
    val = os.environ.get(name, "")
    if not val:
        env_path = os.path.join(os.environ.get("WORKSPACE", os.path.expanduser("~/.openclaw/workspace")), ".env")
        if os.path.exists(env_path):
            with open(env_path) as f:
                for line in f:
                    line = line.strip()
                    if line.startswith(name + "="):
                        val = line.split("=", 1)[1].strip().strip('"').strip("'")
                        break
    return val


def req(method, url, data=None, headers=None, timeout=30):
    body = json.dumps(data).encode() if data else None
    r = urllib.request.Request(url, data=body, method=method)
    r.add_header("Content-Type", "application/json")
    if headers:
        for k, v in headers.items():
            r.add_header(k, v)
    try:
        resp = urllib.request.urlopen(r, timeout=timeout)
        raw = resp.read().decode()
        return json.loads(raw) if raw.strip() else {}
    except urllib.error.HTTPError as e:
        err = e.read().decode()
        print(json.dumps({"error": True, "code": e.code, "message": err}), file=sys.stderr)
        sys.exit(1)


def api(method, path, data=None, params=None):
    """Make authenticated API request."""
    base = API_BASE
    token = get_env("SHIPPO_API_TOKEN")
    if not token:
        print("Error: SHIPPO_API_TOKEN not set", file=sys.stderr)
        sys.exit(1)
    headers = {"Authorization": f"Bearer {token}"}
    url = f"{base}{path}"
    if params:
        qs = urllib.parse.urlencode({k: v for k, v in params.items() if v}, doseq=True)
        url = f"{url}{'&' if '?' in url else '?'}{qs}"
    return req(method, url, data=data, headers=headers)


def out(data):
    print(json.dumps(data, indent=2, default=str))


def cmd_create_shipment(args):
    """Create shipment & get rates"""
    path = "/shipments"
    data = {}
    if getattr(args, 'from'):
        data["from"] = getattr(args, 'from')
    if args.to:
        data["to"] = args.to
    if args.parcel:
        data["parcel"] = args.parcel
    result = api("POST", path, data=data)
    out(result)

def cmd_list_shipments(args):
    """List shipments"""
    path = "/shipments"
    params = {}
    if args.results:
        params["results"] = args.results
    if args.page:
        params["page"] = args.page
    result = api("GET", path, params=params)
    out(result)

def cmd_get_shipment(args):
    """Get shipment details"""
    path = "/shipments/{id}"
    path = path.replace("{id}", str(args.id))
    result = api("GET", path)
    out(result)

def cmd_get_rates(args):
    """Get rates for shipment"""
    path = "/shipments/{id}/rates"
    path = path.replace("{id}", str(args.id))
    result = api("GET", path)
    out(result)

def cmd_purchase_label(args):
    """Purchase shipping label"""
    path = "/transactions"
    data = {}
    if args.rate:
        data["rate"] = args.rate
    result = api("POST", path, data=data)
    out(result)

def cmd_list_transactions(args):
    """List label transactions"""
    path = "/transactions"
    params = {}
    if args.results:
        params["results"] = args.results
    result = api("GET", path, params=params)
    out(result)

def cmd_get_transaction(args):
    """Get label/transaction details"""
    path = "/transactions/{id}"
    path = path.replace("{id}", str(args.id))
    result = api("GET", path)
    out(result)

def cmd_track_package(args):
    """Track a package"""
    path = "/tracks/{carrier}/{tracking_number}"
    path = path.replace("{carrier}", str(args.carrier or ""))
    path = path.replace("{tracking-number}", str(args.tracking_number or ""))
    params = {}
    if args.tracking_number:
        params["tracking-number"] = args.tracking_number
    result = api("GET", path, params=params)
    out(result)

def cmd_validate_address(args):
    """Validate an address"""
    path = "/addresses"
    data = {}
    if args.name:
        data["name"] = args.name
    if args.street1:
        data["street1"] = args.street1
    if args.city:
        data["city"] = args.city
    if args.state:
        data["state"] = args.state
    if args.zip:
        data["zip"] = args.zip
    if args.country:
        data["country"] = args.country
    result = api("POST", path, data=data)
    out(result)

def cmd_list_parcels(args):
    """List saved parcels"""
    path = "/parcels"
    result = api("GET", path)
    out(result)

def cmd_create_parcel(args):
    """Create a parcel template"""
    path = "/parcels"
    data = {}
    if args.length:
        data["length"] = args.length
    if args.width:
        data["width"] = args.width
    if args.height:
        data["height"] = args.height
    if args.weight:
        data["weight"] = args.weight
    result = api("POST", path, data=data)
    out(result)

def cmd_create_return(args):
    """Create return shipment"""
    path = "/shipments"
    data = {}
    if getattr(args, 'from'):
        data["from"] = getattr(args, 'from')
    if args.to:
        data["to"] = args.to
    if args.parcel:
        data["parcel"] = args.parcel
    if args.is_return:
        data["is-return"] = args.is_return
    result = api("POST", path, data=data)
    out(result)

def cmd_list_carriers(args):
    """List carrier accounts"""
    path = "/carrier_accounts"
    result = api("GET", path)
    out(result)


def main():
    parser = argparse.ArgumentParser(description="Shippo CLI")
    sub = parser.add_subparsers(dest="command")
    sub.required = True

    p_create_shipment = sub.add_parser("create-shipment", help="Create shipment & get rates")
    p_create_shipment.add_argument("--from", dest="from_addr", default="JSON address")
    p_create_shipment.add_argument("--to", default="JSON address")
    p_create_shipment.add_argument("--parcel", default="JSON")
    p_create_shipment.set_defaults(func=cmd_create_shipment)

    p_list_shipments = sub.add_parser("list-shipments", help="List shipments")
    p_list_shipments.add_argument("--results", default="25")
    p_list_shipments.add_argument("--page", default="1")
    p_list_shipments.set_defaults(func=cmd_list_shipments)

    p_get_shipment = sub.add_parser("get-shipment", help="Get shipment details")
    p_get_shipment.add_argument("id")
    p_get_shipment.set_defaults(func=cmd_get_shipment)

    p_get_rates = sub.add_parser("get-rates", help="Get rates for shipment")
    p_get_rates.add_argument("id")
    p_get_rates.set_defaults(func=cmd_get_rates)

    p_purchase_label = sub.add_parser("purchase-label", help="Purchase shipping label")
    p_purchase_label.add_argument("--rate", required=True)
    p_purchase_label.set_defaults(func=cmd_purchase_label)

    p_list_transactions = sub.add_parser("list-transactions", help="List label transactions")
    p_list_transactions.add_argument("--results", default="25")
    p_list_transactions.set_defaults(func=cmd_list_transactions)

    p_get_transaction = sub.add_parser("get-transaction", help="Get label/transaction details")
    p_get_transaction.add_argument("id")
    p_get_transaction.set_defaults(func=cmd_get_transaction)

    p_track_package = sub.add_parser("track-package", help="Track a package")
    p_track_package.add_argument("--carrier", required=True)
    p_track_package.add_argument("--tracking-number", required=True)
    p_track_package.set_defaults(func=cmd_track_package)

    p_validate_address = sub.add_parser("validate-address", help="Validate an address")
    p_validate_address.add_argument("--name", required=True)
    p_validate_address.add_argument("--street1", required=True)
    p_validate_address.add_argument("--city", required=True)
    p_validate_address.add_argument("--state", required=True)
    p_validate_address.add_argument("--zip", required=True)
    p_validate_address.add_argument("--country", default="US")
    p_validate_address.set_defaults(func=cmd_validate_address)

    p_list_parcels = sub.add_parser("list-parcels", help="List saved parcels")
    p_list_parcels.set_defaults(func=cmd_list_parcels)

    p_create_parcel = sub.add_parser("create-parcel", help="Create a parcel template")
    p_create_parcel.add_argument("--length", required=True)
    p_create_parcel.add_argument("--width", required=True)
    p_create_parcel.add_argument("--height", required=True)
    p_create_parcel.add_argument("--weight", required=True)
    p_create_parcel.set_defaults(func=cmd_create_parcel)

    p_create_return = sub.add_parser("create-return", help="Create return shipment")
    p_create_return.add_argument("--from", dest="from_addr", default="JSON")
    p_create_return.add_argument("--to", default="JSON")
    p_create_return.add_argument("--parcel", default="JSON")
    p_create_return.add_argument("--is-return", default="true")
    p_create_return.set_defaults(func=cmd_create_return)

    p_list_carriers = sub.add_parser("list-carriers", help="List carrier accounts")
    p_list_carriers.set_defaults(func=cmd_list_carriers)

    args = parser.parse_args()
    args.func(args)


if __name__ == "__main__":
    main()

```

shippo | SkillHub