{"id":50237196,"url":"https://github.com/dougborg/statuspro-openapi-client","last_synced_at":"2026-05-26T20:07:42.515Z","repository":{"id":352674485,"uuid":"1213868824","full_name":"dougborg/statuspro-openapi-client","owner":"dougborg","description":"StatusPro API client ecosystem — Python + TypeScript + MCP server with transport-layer resilience, rate-limit awareness, and auto-pagination.","archived":false,"fork":false,"pushed_at":"2026-05-20T22:52:27.000Z","size":1443,"stargazers_count":0,"open_issues_count":13,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-21T02:55:45.769Z","etag":null,"topics":["mcp-server","openapi","order-status","python-client","statuspro","typescript-client"],"latest_commit_sha":null,"homepage":"https://dougborg.github.io/statuspro-openapi-client/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dougborg.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"docs/CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"docs/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["dougborg"],"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"lfx_crowdfunding":null,"polar":null,"buy_me_a_coffee":null,"thanks_dev":null,"custom":null}},"created_at":"2026-04-17T21:10:29.000Z","updated_at":"2026-05-20T22:52:31.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/dougborg/statuspro-openapi-client","commit_stats":null,"previous_names":["dougborg/statuspro-openapi-client"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/dougborg/statuspro-openapi-client","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dougborg%2Fstatuspro-openapi-client","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dougborg%2Fstatuspro-openapi-client/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dougborg%2Fstatuspro-openapi-client/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dougborg%2Fstatuspro-openapi-client/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dougborg","download_url":"https://codeload.github.com/dougborg/statuspro-openapi-client/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dougborg%2Fstatuspro-openapi-client/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33536866,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"ssl_error","status_checked_at":"2026-05-26T15:22:15.568Z","response_time":63,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["mcp-server","openapi","order-status","python-client","statuspro","typescript-client"],"created_at":"2026-05-26T20:07:41.881Z","updated_at":"2026-05-26T20:07:42.502Z","avatar_url":"https://github.com/dougborg.png","language":"Python","funding_links":["https://github.com/sponsors/dougborg"],"categories":[],"sub_categories":[],"readme":"# StatusPro — API Client Ecosystem\n\nMulti-language client ecosystem for the\n[StatusPro API](https://app.orderstatuspro.com/api/v1), a small REST API for **reading\nand updating the status of orders**. The StatusPro API is used by merchants to expose\nproduction progress to their customers (order received → in production → shipped, etc.)\nand to update that status from their own systems.\n\nThis monorepo ships:\n\n- A production-grade Python client with transport-layer retries, rate-limit awareness,\n  and auto-pagination across all list endpoints.\n- A TypeScript client generated from the same OpenAPI spec.\n- An MCP server exposing StatusPro operations as tools to AI assistants like Claude\n  Desktop.\n\n[![Python 3.12+](https://img.shields.io/badge/python-3.12+-blue.svg)](https://www.python.org/downloads/)\n[![TypeScript](https://img.shields.io/badge/typescript-5.0+-blue.svg)](https://www.typescriptlang.org/)\n[![OpenAPI 3.1.0](https://img.shields.io/badge/OpenAPI-3.1.0-green.svg)](https://spec.openapis.org/oas/v3.1.0)\n\n## Packages\n\n| Package                                                  | Language   | Version | Description                                        |\n| -------------------------------------------------------- | ---------- | ------- | -------------------------------------------------- |\n| [statuspro-openapi-client](statuspro_public_api_client/) | Python     | 0.1.0   | API client with transport-layer resilience         |\n| [statuspro-mcp-server](statuspro_mcp_server/)            | Python     | 0.1.0   | Model Context Protocol server for AI assistants    |\n| [statuspro-client](packages/statuspro-client/)           | TypeScript | 0.1.0   | TypeScript/JavaScript client with full type safety |\n\n## Features\n\n| Feature                                     | Python | TypeScript | MCP Server              |\n| ------------------------------------------- | ------ | ---------- | ----------------------- |\n| Automatic retries (network + 5xx)           | Yes    | Yes        | Yes (via Python client) |\n| Rate-limit retry with exponential backoff   | Yes    | Yes        | Yes                     |\n| Auto-pagination (page + per_page with meta) | Yes    | Yes        | Yes                     |\n| Two-step confirm on mutations               | —      | —          | Yes                     |\n| Full type safety (attrs + Pydantic / TS)    | Yes    | Yes        | Yes                     |\n| AI tool surface                             | —      | —          | Claude, Cursor, etc.    |\n\n## Quick Start\n\n### Python Client\n\n```bash\npip install statuspro-openapi-client\n```\n\n```python\nimport asyncio\nfrom statuspro_public_api_client import StatusProClient\n\nasync def main():\n    async with StatusProClient() as client:\n        orders = await client.orders.list(per_page=25)\n        for order in orders:\n            status = order.status.name if order.status else \"(no status)\"\n            print(f\"{order.name}: {status}\")\n\nasyncio.run(main())\n```\n\n### TypeScript Client\n\n```bash\nnpm install statuspro-client\n```\n\n```typescript\nimport { StatusProClient } from \"statuspro-client\";\n\nconst client = await StatusProClient.create();\nconst response = await client.get(\"/orders\");\nconst { data, meta } = await response.json();\nconsole.log(`Found ${meta.total} orders (page ${meta.current_page}/${meta.last_page})`);\n```\n\n### MCP Server (Claude Desktop)\n\n```bash\npip install statuspro-mcp-server\n```\n\nAdd to Claude Desktop config\n(`~/Library/Application Support/Claude/claude_desktop_config.json`):\n\n```json\n{\n  \"mcpServers\": {\n    \"statuspro\": {\n      \"command\": \"uvx\",\n      \"args\": [\"statuspro-mcp-server\"],\n      \"env\": {\n        \"STATUSPRO_API_KEY\": \"your-api-key-here\"\n      }\n    }\n  }\n}\n```\n\n## Configuration\n\nAll packages authenticate via bearer token:\n\n1. **Environment variable**: `STATUSPRO_API_KEY`\n1. **`.env` file**: `STATUSPRO_API_KEY=your-key`\n1. **Direct parameter**: pass `api_key=...` to the client constructor\n1. **`~/.netrc`**: `machine app.orderstatuspro.com` + `password your-key`\n\n```bash\n# .env\nSTATUSPRO_API_KEY=your-api-key-here\nSTATUSPRO_BASE_URL=https://app.orderstatuspro.com/api/v1  # optional override\n```\n\n## API Coverage\n\nThe StatusPro API is intentionally small and focused on order status. All 7 endpoints\nare covered:\n\n| Tag      | Method | Path                           | Purpose                                                        |\n| -------- | ------ | ------------------------------ | -------------------------------------------------------------- |\n| Orders   | GET    | `/orders`                      | Paginated list with filters (search, status, tags, due date).  |\n| Orders   | GET    | `/orders/{id}`                 | Full detail for one order including history.                   |\n| Orders   | GET    | `/orders/lookup`               | Look up an order by order number + customer email.             |\n| Orders   | GET    | `/orders/{id}/viable-statuses` | Statuses that are valid transitions from the current state.    |\n| Orders   | POST   | `/orders/{id}/status`          | Change the status of a single order.                           |\n| Orders   | POST   | `/orders/{id}/comment`         | Add a history comment (5/min rate limit).                      |\n| Orders   | POST   | `/orders/{id}/due-date`        | Set or update the due date (single date or range).             |\n| Orders   | POST   | `/orders/bulk-status`          | Update up to 50 orders at once (5/min, queued asynchronously). |\n| Statuses | GET    | `/statuses`                    | Every status defined on the account (code, name, color).       |\n\n**Conventions:**\n\n- Bearer token auth on every endpoint (`Authorization: Bearer \u003cSTATUSPRO_API_KEY\u003e`).\n- `GET /orders` returns\n  `{\"data\": [...], \"meta\": {current_page, last_page, per_page, total, from, to}}`.\n- `GET /statuses` and `GET /orders/{id}/viable-statuses` return raw JSON arrays.\n- Pagination uses `page` + `per_page` query params (`per_page` max 100).\n- Rate limits are documented per-endpoint (60/min on most, 5/min on `/comment` and\n  `/bulk-status`) but not surfaced in response headers.\n\n## MCP Tools\n\nThe `statuspro-mcp-server` package maps each endpoint to a tool. Mutations use a\ntwo-step confirm pattern: call with `confirm=false` for a preview, then `confirm=true`\nto apply (the client elicits explicit user approval).\n\n| Tool                       | Mutation? | Description                               |\n| -------------------------- | --------- | ----------------------------------------- |\n| `list_orders`              | no        | Filter + paginate orders                  |\n| `get_order`                | no        | Full detail for one order                 |\n| `lookup_order`             | no        | Find an order by number + customer email  |\n| `list_statuses`            | no        | Full status catalog                       |\n| `get_viable_statuses`      | no        | Valid transitions for an order            |\n| `update_order_status`      | yes       | Change one order's status                 |\n| `add_order_comment`        | yes       | Add a history comment                     |\n| `update_order_due_date`    | yes       | Set or change the due date                |\n| `bulk_update_order_status` | yes       | Change status for up to 50 orders at once |\n\nPlus two resources:\n\n- `statuspro://statuses` — JSON list of every status (cached read).\n- `statuspro://help` — tool reference and recommended workflows.\n\n## Resilience (Python client)\n\nEvery endpoint inherits these transport-layer behaviors automatically — no decorators or\nwrappers needed:\n\n- **Retries**: `httpx-retries` retries idempotent methods on 502/503/504 and any method\n  on 429. Configurable via `max_retries`.\n- **Rate-limit awareness**: `Retry-After` headers are honored when present; otherwise\n  exponential backoff.\n- **Auto-pagination**: `GET /orders` is walked to completion using `meta.last_page` as\n  the stop condition, up to `max_pages` (default 100) or an explicit `max_items`\n  override. Raw-array endpoints (`/statuses`, `/viable-statuses`) are never paginated.\n- **Sensitive-data redaction**: Authorization headers and common secret field names\n  (`api_key`, `password`, `email`, etc.) are scrubbed from log output.\n\n## Project Structure\n\n```text\nstatuspro-openapi-client/               # Monorepo root\n├── pyproject.toml                      # Workspace configuration (uv)\n├── uv.lock                             # Python lock file\n├── pnpm-workspace.yaml                 # TS workspace\n├── docs/\n│   ├── statuspro-openapi.yaml          # OpenAPI 3.1.0 spec (source of truth)\n│   └── *.md                            # Shared documentation\n├── statuspro_public_api_client/        # Python client\n│   ├── statuspro_client.py             # Resilient client + transport layer\n│   ├── domain/                         # Hand-written Pydantic domain models\n│   ├── helpers/                        # Ergonomic facades (client.orders, .statuses)\n│   ├── utils.py                        # unwrap/unwrap_as/unwrap_data + error types\n│   ├── api/, models/                   # Generated from the OpenAPI spec\n│   └── docs/                           # Package documentation\n├── statuspro_mcp_server/                # MCP server\n│   └── src/statuspro_mcp/\n│       ├── server.py                   # FastMCP server\n│       ├── tools/                      # 9 tools (orders + statuses)\n│       └── resources/                  # help + statuses resources\n└── packages/\n    └── statuspro-client/                # TypeScript client\n        ├── src/\n        │   └── generated/              # Generated from the same spec\n        └── openapi-ts.config.ts\n```\n\n## Development\n\n### Prerequisites\n\n- **Python 3.12+** for Python packages\n- **Node.js 18+** for TypeScript package\n- **uv** ([install](https://docs.astral.sh/uv/getting-started/installation/))\n- **pnpm** ([install](https://pnpm.io/installation))\n\n### Setup\n\n```bash\ngit clone https://github.com/dougborg/statuspro-openapi-client.git\ncd statuspro-openapi-client\n\nuv sync --all-extras          # install Python deps\nuv run pre-commit install     # install git hooks\npnpm install                  # install TS deps\ncp .env.example .env          # add STATUSPRO_API_KEY\n```\n\n### Common Commands\n\n```bash\nuv run poe quick-check        # fast: format + lint\nuv run poe check              # full: format + lint + typecheck + test\nuv run poe test               # just tests (pytest -n 4)\nuv run poe regenerate-client  # regenerate the Python client from docs/statuspro-openapi.yaml\nuv run poe generate-pydantic  # regenerate Pydantic v2 models\npnpm --filter statuspro-client generate  # regenerate the TypeScript client\n```\n\n### Commit Standards\n\nConventional commits drive per-package semantic-release versioning:\n\n```bash\ngit commit -m \"feat(client): add helper for archived orders\"\ngit commit -m \"fix(client): handle empty viable-status responses\"\ngit commit -m \"feat(mcp): add tool for lookup by date range\"\ngit commit -m \"feat(ts): export pagination helpers\"\ngit commit -m \"docs: update quick-start\"\n```\n\nUse `!` for breaking changes: `feat(client)!: drop Python 3.11 support`.\n\nSee [MONOREPO_SEMANTIC_RELEASE.md](docs/MONOREPO_SEMANTIC_RELEASE.md) for details.\n\n## License\n\nMIT License — see [LICENSE](LICENSE).\n\n## Contributing\n\nContributions welcome. See [CONTRIBUTING.md](docs/CONTRIBUTING.md) for guidelines.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdougborg%2Fstatuspro-openapi-client","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdougborg%2Fstatuspro-openapi-client","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdougborg%2Fstatuspro-openapi-client/lists"}