Thank you for your interest in contributing to Shipstack.
This project aims to be the most reliable, type‑safe, and framework‑agnostic shipping SDK in the ecosystem.
Contributions are welcome, whether they involve bug fixes, new features, documentation, or improvements to developer experience.
Shipstack operates in Library Mode, meaning:
- No global environment variables
- No framework assumptions
- No runtime assumptions
- Strict TypeScript typing
- Predictable, testable behavior
Understanding the project structure will help you contribute effectively.
Shipstack is organized into three primary layers:
- Auto‑generated OpenAPI clients for USPS, FedEx, and UPS
- These files should never be edited manually
- Regenerated using
openapi-typescript-codegen
- Hand‑written wrappers around the generated clients
- Handles:
- Authentication
- Request shaping
- Error normalization
- Configuration injection
- Exposes the public functional API (
getRates,validateAddress,trackShipment, etc.)
- The orchestration layer
- Combines multiple carrier operations into unified workflows
- Includes:
- Address aggregator
- Rates aggregator
- Tracking aggregator
- Shipment aggregator (staged + actual)
- Converts raw carrier responses into normalized Shipstack types
USPS pulls directly from the official USPS Developer Portal:
npm run generate:uspsFedEx and UPS use local OpenAPI specs stored in specs/fedex and specs/ups:
npm run generate:fedex
npm run generate:upsRegenerate all carriers:
npm run generate:allWhen implementing new functionality (e.g., Saturday delivery, new service codes, new tracking fields):
-
Update the Request Builder
Modify the appropriate file, such as:src/fedex/rates/request.tssrc/usps/labels/request.tssrc/ups/shipping/request.ts
-
Update the Converter
Ensure the raw carrier response is mapped to Shipstack’s normalized types:src/converters/rates/*src/converters/tracking/*src/converters/shipment/*
-
Update the Aggregator
Make sure the new data flows through the orchestrator layer. -
Update the Public API
If the feature should be exposed to users, update:src/api/*src/index.ts
-
Add Tests
All new features must include unit tests and, when appropriate, integration tests.
Shipstack uses TypeScript path aliases for clean imports.
Always use:
import { ShipstackError } from "@/errors";Never use relative paths like:
import { ShipstackError } from "../../errors";Shipstack uses Vitest for testing.
- Should mock carrier responses
- Use fixtures stored in
tests/fixtures - Test request builders, converters, and error handling
- Validate aggregator behavior
- Ensure multi‑carrier workflows behave consistently
- Test staged vs actual shipment creation
Run tests:
npm run testShipstack supports two shipment modes:
- No API calls
- No label creation
- Pure request‑builder logic
- Must be fully tested with fixtures
- Calls real carrier APIs
- Should be tested with mocked responses
- Never hit live carrier endpoints in CI
- Fork the repository
- Create a feature branch
- Write clear commit messages
- Include tests for all new functionality
- Update documentation when necessary
- Ensure the build passes
- Submit a PR with a clear description of the change
- TypeScript only
- No
anyunless absolutely necessary - Prefer pure functions
- Avoid side effects in request builders
- Use
ShipstackErrorfor all thrown errors - Maintain consistent naming across carriers
- Keep the public API stable and predictable
If you’re unsure where to start, feel free to open a GitHub Discussion or Issue.
We’re happy to help guide contributions of any size.