{"_id":"ship24","_rev":"2-79e7501d63edca6411e126a514b547d2","name":"ship24","dist-tags":{"latest":"1.1.0"},"versions":{"1.0.0":{"name":"ship24","version":"1.0.0","keywords":["ship24","tracking","package-tracking","parcel-tracking","shipment-tracking","courier","logistics","shipping","tracking-api","sdk","typescript","esm"],"author":{"name":"Ship24"},"license":"MIT","_id":"ship24@1.0.0","maintainers":[{"name":"ship24","email":"dev@ship24.com"}],"homepage":"https://github.com/ship24/ship24-node#readme","bugs":{"url":"https://github.com/ship24/ship24-node/issues"},"dist":{"shasum":"cf1f30b355d368b9072e50cee0be6533fb95020c","tarball":"https://registry.npmjs.org/ship24/-/ship24-1.0.0.tgz","fileCount":9,"integrity":"sha512-Qu+J/AXJfLPLEc1fc0gXAPYTeLLU+Cb+vikokN6Z/zTK/71RxZZtW2Ztlgtv0GLWP9ExMdoyfzucUM6yRc3poA==","signatures":[{"sig":"MEQCIHiGxAr9SW0O7YyMXpXoEYlnteatWgeZ1AUVfy5sjADPAiB4uJyixak93Du2BQSAnopFg8yGYQSh5axU/k5r4+gwYw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/ship24@1.0.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":172565},"main":"./dist/index.cjs","type":"module","_from":"file:ship24-1.0.0.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./package.json":"./package.json"},"scripts":{"dev":"tsup --watch","docs":"typedoc","lint":"biome check .","test":"vitest run","build":"tsup","format":"biome format --write .","generate":"tsx scripts/generate-types.ts","lint:fix":"biome check --write .","typecheck":"tsc --noEmit","test:watch":"vitest","check:exports":"publint --strict && attw --pack ."},"_npmUser":{"name":"ship24","email":"dev@ship24.com"},"_resolved":"/tmp/2d4d5afb9ff1c2bfd77f971a7a9157f7/ship24-1.0.0.tgz","_integrity":"sha512-Qu+J/AXJfLPLEc1fc0gXAPYTeLLU+Cb+vikokN6Z/zTK/71RxZZtW2Ztlgtv0GLWP9ExMdoyfzucUM6yRc3poA==","repository":{"url":"git+https://github.com/ship24/ship24-node.git","type":"git"},"_npmVersion":"10.9.8","description":"Official Node.js & TypeScript SDK for the Ship24 Tracking API","directories":{},"sideEffects":false,"_nodeVersion":"22.23.1","publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.0","tsup":"^8.3.0","yaml":"^2.6.0","vitest":"^2.1.0","publint":"^0.2.12","typedoc":"^0.27.0","typescript":"^5.7.0","@types/node":"^22.10.0","@biomejs/biome":"^1.9.4","@changesets/cli":"^2.27.0","openapi-typescript":"^7.4.0","@arethetypeswrong/cli":"^0.18.5"},"_npmOperationalInternal":{"tmp":"tmp/ship24_1.0.0_1784021215699_0.030668642915176125","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"_id":"ship24@1.1.0","bugs":{"url":"https://github.com/ship24/ship24-node/issues"},"dist":{"shasum":"9be68cb3a3ac9930a6b9f60927df0bd30e8686c9","tarball":"https://registry.npmjs.org/ship24/-/ship24-1.1.0.tgz","fileCount":9,"integrity":"sha512-24VPvkzATfaOw4Hkvw6GlLTARQlYE6CcNkxauL+KbNPKH6jYVt+DQ5vfveJaU2oeFUb/qN9tp9AF+jWWbAFg3A==","signatures":[{"sig":"MEQCIFNit3x8WDbhVMuqDSCBB9zlsQwMwCuRzUsHLfTbb02tAiAOnRTrdPl2xmVFQZA3Vi8b8xhrQeCc90esPe5X9A8BSA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIDycwMwejAbGXKDYx8puHpmFdqwU+xqd8xr3lTkQ1aWRAiEA4ZSOP2NyTO9gGgpNJkoWORHmJraDUYLURUkOeq1mBvA="}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/ship24@1.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":180745},"main":"./dist/index.cjs","name":"ship24","type":"module","_from":"file:ship24-1.1.0.tgz","types":"./dist/index.d.ts","author":{"name":"Ship24"},"module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./package.json":"./package.json"},"license":"MIT","scripts":{"dev":"tsup --watch","docs":"typedoc","lint":"biome check .","test":"vitest run","build":"tsup","format":"biome format --write .","generate":"tsx scripts/generate-types.ts","lint:fix":"biome check --write .","typecheck":"tsc --noEmit","test:watch":"vitest","check:exports":"publint --strict && attw --pack ."},"version":"1.1.0","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"a7d1006e-f665-4613-8a37-7b1acbb5649b"}},"homepage":"https://github.com/ship24/ship24-node#readme","keywords":["ship24","tracking","package-tracking","parcel-tracking","shipment-tracking","courier","logistics","shipping","tracking-api","sdk","typescript","esm"],"_resolved":"/tmp/c1f2ac603bd5393c0e74cef1f206f104/ship24-1.1.0.tgz","_integrity":"sha512-24VPvkzATfaOw4Hkvw6GlLTARQlYE6CcNkxauL+KbNPKH6jYVt+DQ5vfveJaU2oeFUb/qN9tp9AF+jWWbAFg3A==","repository":{"url":"git+https://github.com/ship24/ship24-node.git","type":"git"},"_npmVersion":"11.21.0","description":"Official Node.js & TypeScript SDK for the Ship24 Tracking API","directories":{},"maintainers":[{"name":"ship24","email":"dev@ship24.com"}],"sideEffects":false,"_nodeVersion":"22.23.3","publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.0","tsup":"^8.3.0","yaml":"^2.6.0","vitest":"^3.2.6","publint":"^0.2.12","typedoc":"^0.27.0","typescript":"^5.7.0","@types/node":"^22.10.0","@biomejs/biome":"^1.9.4","@changesets/cli":"^2.27.0","openapi-typescript":"^7.4.0","@arethetypeswrong/cli":"^0.18.5"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/ship24_1.1.0_1791272881183_0.9589514556356911"}}},"time":{"created":"2026-07-14T09:26:55.506Z","modified":"2026-10-06T07:48:01.603Z","1.0.0":"2026-07-14T09:26:55.851Z","1.1.0":"2026-10-06T07:48:01.268Z"},"bugs":{"url":"https://github.com/ship24/ship24-node/issues"},"author":{"name":"Ship24"},"license":"MIT","homepage":"https://github.com/ship24/ship24-node#readme","keywords":["ship24","tracking","package-tracking","parcel-tracking","shipment-tracking","courier","logistics","shipping","tracking-api","sdk","typescript","esm"],"repository":{"url":"git+https://github.com/ship24/ship24-node.git","type":"git"},"description":"Official Node.js & TypeScript SDK for the Ship24 Tracking API","maintainers":[{"name":"ship24","email":"dev@ship24.com"}],"readme":"# ship24\n\nOfficial Node.js & TypeScript SDK for the [Ship24 Tracking API](https://docs.ship24.com/).\n\n- **Typed** — full TypeScript types for every request and response, `strict` throughout.\n- **Isomorphic & zero-dependency** — built on native `fetch`. Runs on Node 18+, Bun, Deno, Cloudflare Workers/edge, and modern browsers. No runtime dependencies.\n- **Ergonomic** — `new Ship24({ apiKey })`, then `ship24.trackers.create({ trackingNumber })`.\n\n> This SDK `1.0.0` targets the Ship24 Tracking API `/public/v1`. The SDK version is independent of the API version.\n\n## Install\n\n```bash\nnpm install ship24\n# or: pnpm add ship24 / yarn add ship24 / bun add ship24\n```\n\n## Quickstart\n\n```ts\nimport { Ship24 } from 'ship24';\n\nconst ship24 = new Ship24({ apiKey: process.env.SHIP24_API_KEY! });\n\nconst tracker = await ship24.trackers.create({ trackingNumber: '1234567890' });\nconsole.log(tracker.trackerId);\n```\n\n## Authentication\n\nEvery request sends `Authorization: Bearer <apiKey>`. Create an API key in your\n[Ship24 dashboard](https://www.ship24.com/) and pass it to the constructor. Never hard-code\nkeys — read them from the environment or a secret manager.\n\n## Which product am I on?\n\nShip24 sells two tracking products on two billing models. This SDK keeps them **separate and\nunmistakable**:\n\n| | Per-shipment (default, recommended) | Per-call |\n|---|---|---|\n| Namespaces | `ship24.trackers.*`, `ship24.couriers.*` | `ship24.perCall.*` |\n| Model | Create a tracker; Ship24 tracks asynchronously, pushes webhooks, results fetchable any time | One synchronous track-by-number call, billed per API call |\n| Subscription | Per-shipment plan | **Separate active \"Per-call\" subscription** |\n| Return type | `Tracking` (has `.tracker`) | `PerCallTracking` (**no** `.tracker`) |\n\n```ts\n// Per-shipment (default, recommended)\nconst [tracking] = await ship24.trackers.track({ trackingNumber: '1234567890' });\ntracking.tracker; // ✅\n\n// Per-call (separate subscription, billed per call)\nconst [result] = await ship24.perCall.track({ trackingNumber: '1234567890' });\nresult.tracker; // ❌ type error — PerCallTracking has no tracker\n```\n\nCalling `perCall.track` without a Per-call subscription throws a `SubscriptionError` (HTTP 422)\nwith an actionable message.\n\n## Usage\n\nPer-shipment (`ship24.trackers`):\n\n| Method | Endpoint |\n|---|---|\n| `create(body, opts?)` | `POST /trackers` |\n| `track(body, opts?)` | `POST /trackers/track` — synchronous, ~60s |\n| `bulkCreate(items, opts?)` | `POST /trackers/bulk` — up to 100; returns an envelope, never throws on it |\n| `list(params?, opts?)` | `GET /trackers` |\n| `get(trackerId, opts?)` | `GET /trackers/{id}` |\n| `update(trackerId, body, opts?)` | `PATCH /trackers/{id}` |\n| `getResults(trackerId, opts?)` | `GET /trackers/{id}/results` |\n| `getResultsByTrackingNumber(tn, opts?)` | `GET /trackers/search/{tn}/results` |\n| `resendWebhooks(trackerId, opts?)` | `POST /trackers/{id}/webhook-events/resend` |\n| `downloadWebhookHistory(trackerId, opts?)` | `GET /trackers/{id}/webhook-history/download` |\n\nCouriers: `ship24.couriers.list(opts?)` → `GET /couriers`.\n\nPer-call: `ship24.perCall.track(body, opts?)` → `POST /tracking/search`.\n\nRunnable snippets for each are in [`examples/`](./examples).\n\n`searchBy` — methods that take a `trackerId` accept `{ searchBy: 'clientTrackerId' }` to resolve\nthe id as your own client id instead:\n\n```ts\nconst tracker = await ship24.trackers.get('order-4242', { searchBy: 'clientTrackerId' });\n```\n\n### Bulk results\n\n`bulkCreate` **never throws on the bulk envelope** — HTTP 201/207/400/403 all resolve to a\n`BulkCreateResult`. Inspect `status` and per-item `itemStatus`/`errors`; only auth/rate-limit\nfailures reject.\n\n```ts\nconst result = await ship24.trackers.bulkCreate([{ trackingNumber: 'A' }, { trackingNumber: 'B' }]);\nif (result.status !== 'success') {\n  for (const item of result.data ?? []) {\n    if (item.itemStatus === 'error') console.error(item.inputData.trackingNumber, item.errors);\n  }\n}\n```\n\n## Error handling\n\nAll errors extend `Ship24Error`. HTTP error responses are `Ship24APIError` (carrying `httpStatus`,\n`errors`, `code`, and `requestId`) with these subclasses:\n\n| Class | When |\n|---|---|\n| `AuthenticationError` | `auth_*` (400/401) |\n| `InvalidRequestError` (alias `ValidationError`) | 400 validation / immutable field / malformed |\n| `NotFoundError` | 404 `tracker_not_found`, `parcel_not_found` |\n| `ConflictError` | `request_conflict` (409), `tracker_conflict` (400) |\n| `RateLimitError` | 429 — exposes `retryAfter` (seconds) and `rateLimit` (IETF headers) |\n| `QuotaError` | `quota_limit_reached` (403/405), `bulk_create_limit_exceeded` (403) |\n| `SubscriptionError` | `no_active_subscription` (422) — actionable per-call message |\n| `ServerError` | 5xx |\n\nTransport failures (no HTTP response): `Ship24ConnectionError` and `Ship24TimeoutError`.\n\n```ts\nimport { NotFoundError, RateLimitError } from 'ship24';\n\ntry {\n  await ship24.trackers.get('unknown');\n} catch (err) {\n  if (err instanceof NotFoundError) console.error(err.code, err.requestId);\n  else if (err instanceof RateLimitError) console.error(`retry after ${err.retryAfter}s`);\n  else throw err;\n}\n```\n\n## Configuration\n\n```ts\nnew Ship24({\n  apiKey: '...',            // required\n  baseUrl: '...',           // override the API origin; default 'https://api.ship24.com'\n  timeoutMs: 10_000,        // default; track/perCall.track default to 60_000\n  fetch: customFetch,       // default globalThis.fetch\n  headers: { 'X-App': '1' },// extra default headers (cannot override Authorization)\n});\n```\n\nPer-call options on every method: `{ timeoutMs?, signal?, headers? }` (plus `searchBy?` on\ntracker-id methods). Note `trackers.track` and `perCall.track` are synchronous and may take up to\n~60s — they default to a 60 000ms timeout; override with `timeoutMs`.\n\n## Supported runtimes\n\nNode 18+ (native `fetch`), Bun, Deno, Cloudflare Workers/edge, and modern browsers. CI tests\nagainst Node 20/22/24, latest Bun, and latest Deno.\n\n## Contributing / regenerating types\n\nTypes for the core objects are hand-written (the source of truth). The OpenAPI spec is **vendored**\nat `spec/ship24-tracking-api.yaml` and used as a **drift reference**:\n\n```bash\nnpm run generate   # clean the vendored spec → openapi-typescript → src/generated/schema.d.ts\n```\n\n`npm run generate` never fetches the spec over the network. A scheduled CI job diffs the canonical\nspec URL against the vendored copy and opens an issue when they differ. See\n[docs/spec-drift.md](./docs/spec-drift.md) for how to handle it.\n\n```bash\nnpm run typecheck && npm run lint && npm test && npm run build && npm run check:exports\n```\n\n## License\n\n[MIT](./LICENSE) © Ship24\n","readmeFilename":"README.md"}