{"_id":"@cygt/boxtal-sdk","name":"@cygt/boxtal-sdk","dist-tags":{"latest":"1.0.1"},"versions":{"1.0.1":{"name":"@cygt/boxtal-sdk","version":"1.0.1","description":"TypeScript SDK for Boxtal API v3","main":"dist/index.js","types":"dist/index.d.ts","type":"module","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./package.json":"./package.json"},"scripts":{"build":"tsc && tsc-alias","dev":"tsc --watch","clean":"rm -rf dist","test":"vitest run","test:watch":"vitest","lint":"eslint .","lint:fix":"eslint . --fix","typecheck":"tsc --noEmit","prepublishOnly":"npm run typecheck && npm run lint && npm test && npm run clean && npm run build"},"engines":{"node":">=22.0.0"},"repository":{"type":"git","url":"git+https://github.com/cguillerminet/boxtal-sdk.git"},"homepage":"https://github.com/cguillerminet/boxtal-sdk#readme","bugs":{"url":"https://github.com/cguillerminet/boxtal-sdk/issues"},"publishConfig":{"access":"public"},"keywords":["boxtal","shipping","typescript","sdk"],"license":"MIT","devDependencies":{"@eslint/js":"^10.0.1","@types/node":"^22.19.18","eslint":"^10.3.0","ts-node":"^10.9.2","tsc-alias":"^1.8.17","typescript":"^5.4.0","typescript-eslint":"^8.59.2","vitest":"^4.1.5"},"gitHead":"024b94f8ec3983fee5420d57fb2f6977a3c3b79e","_id":"@cygt/boxtal-sdk@1.0.1","_nodeVersion":"24.14.1","_npmVersion":"11.11.0","dist":{"integrity":"sha512-Wsqy4YsYyK3XE8dijd8ILZVDou7d1Gs96+Xw7CPdNM4fm8obI4f+3kJaHYciATsA8RJtRjLNcpGSQ8p40lg4fg==","shasum":"d902f81d6d9cd40d91c5ab0f855f26ac6dc90dff","tarball":"https://registry.npmjs.org/@cygt/boxtal-sdk/-/boxtal-sdk-1.0.1.tgz","fileCount":62,"unpackedSize":123861,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDyeeeJSfb1GgHTaAj5EYM3A0rlTm1ISwCsQ+e0tbEK/QIgYLJrtGim2gHBbNqMRZv5kn1SHrVNN3x0NOEHrMYE1+M="}]},"_npmUser":{"name":"c.guillerminet","email":"cyril@guillerminet.com"},"directories":{},"maintainers":[{"name":"c.guillerminet","email":"cyril@guillerminet.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/boxtal-sdk_1.0.1_1778490239229_0.5571719345571551"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-11T09:03:59.156Z","1.0.1":"2026-05-11T09:03:59.356Z","modified":"2026-05-11T09:03:59.524Z"},"maintainers":[{"name":"c.guillerminet","email":"cyril@guillerminet.com"}],"description":"TypeScript SDK for Boxtal API v3","homepage":"https://github.com/cguillerminet/boxtal-sdk#readme","keywords":["boxtal","shipping","typescript","sdk"],"repository":{"type":"git","url":"git+https://github.com/cguillerminet/boxtal-sdk.git"},"bugs":{"url":"https://github.com/cguillerminet/boxtal-sdk/issues"},"license":"MIT","readme":"# @cygt/boxtal-sdk\n\nTypeScript SDK for the [Boxtal API v3](https://developer.boxtal.com/fr/fr/apiv3/guide/getting-started-api-v3) — JSON over HTTPS.\nZero runtime dependencies, ESM, Node.js ≥ 22 (uses native `fetch`, `AbortSignal.timeout/any`, `node:crypto`, `Buffer`).\n\n## Install & build\n\n```bash\nnpm install\nnpm run build\n```\n\n## Quick start\n\n```ts\nimport { BoxtalClient } from \"@cygt/boxtal-sdk\";\n\nconst client = new BoxtalClient({\n  accessKey: process.env.BOXTAL_ACCESS_KEY!,\n  secretKey: process.env.BOXTAL_SECRET_KEY!,\n  environment: \"sandbox\", // or \"production\" (default)\n});\n\nconst points = await client.parcelPoints.searchByNetwork({\n  countryIsoCode: \"FR\",\n  city: \"Paris\",\n  postalCode: \"75001\",\n  searchNetworks: [\"MONR\"],\n});\n```\n\n## Environments\n\n|              | Base URL                   |\n|--------------|----------------------------|\n| `sandbox`    | `https://api.boxtal.build` |\n| `production` | `https://api.boxtal.com`   |\n\n## Authentication\n\nBy default the client exchanges your `accessKey` / `secretKey` for a short-lived\nBearer token at `POST /iam/account-app/token` and caches it until ~60 seconds\nbefore expiry. Concurrent requests share a single in-flight token fetch.\n\nPass `auth: \"basic\"` to skip the token exchange and send Basic auth on every\nrequest — Boxtal accepts both. `client.invalidateToken()` forces a refresh.\n\n## Resources\n\n| Resource                | Methods                                                            |\n|-------------------------|--------------------------------------------------------------------|\n| `contentCategories`     | `list({ language? })`                                              |\n| `parcelPoints`          | `search`, `searchByNetwork`, `searchByShippingOffer`               |\n| `shippingOrders`        | `create`, `get`, `cancel`, `getDocuments`, `getTracking`           |\n| `subscriptions`         | `list`, `create`, `update`, `delete`                               |\n\nFor anything not covered, use the typed escape hatch:\n\n```ts\nconst res = await client.request<MyType>({\n  method: \"GET\",\n  path: \"/shipping/v3.1/anything-new\",\n  query: { foo: \"bar\" },\n});\n```\n\n## Errors\n\nEvery non-2xx response throws `BoxtalApiError` carrying `status`,\n`statusText`, parsed `body`, and the structured `errors` array from the API.\nConvenience getters: `isUnauthorized` (401), `isBadRequest` (400),\n`isUnprocessable` (422), `isServerError` (5xx).\n\nNetwork failures throw `BoxtalNetworkError`; timeouts (default 30s) throw\n`BoxtalTimeoutError`. All inherit from `BoxtalError`.\n\n5xx responses are retried (default 2 retries, exponential backoff starting at\n200ms). `POST`/`PUT`/`DELETE` are *not* retried — they are non-idempotent.\n\n## Webhooks\n\n```ts\nimport { verifyWebhookSignature, type WebhookEventPayload } from \"@cygt/boxtal-sdk\";\n\napp.post(\"/boxtal-webhook\", express.raw({ type: \"application/json\" }), (req, res) => {\n  if (!verifyWebhookSignature(req.body, req.headers[\"x-bxt-signature\"], process.env.WEBHOOK_SECRET!)) {\n    return res.sendStatus(401);\n  }\n  const event = JSON.parse(req.body.toString()) as WebhookEventPayload;\n  // event.type === \"DOCUMENT_CREATED\" | \"TRACKING_CHANGED\"\n  res.sendStatus(200);\n});\n```\n\nVerification uses the raw request bytes; do **not** re-serialize the JSON.\n\n## Configuration\n\n```ts\nnew BoxtalClient({\n  accessKey, secretKey,\n  environment: \"sandbox\" | \"production\",   // default \"production\"\n  baseUrl: \"https://...\",                  // overrides environment\n  auth: \"bearer\" | \"basic\",                // default \"bearer\"\n  timeoutMs: 30_000,\n  retries: { count: 2, initialBackoffMs: 200, maxBackoffMs: 2_000 },\n  fetch: globalThis.fetch,                 // injectable for tests\n  defaultHeaders: { \"X-Trace\": \"abc\" },\n});\n```\n\n## Examples\n\nSandbox-ready scripts live in [`examples/`](./examples). Set `BOXTAL_ACCESS_KEY`\nand `BOXTAL_SECRET_KEY` in `.env`, `npm run build`, then:\n\n```bash\nnode examples/01-list-content-categories.mjs\nnode examples/02-search-parcel-points.mjs\nnode examples/04-manage-subscription.mjs        # full subscription CRUD cycle\nnode examples/05-create-shipping-order.mjs      # dry-run; --send to POST\nnode examples/06-verify-webhook.mjs             # local only\n```\n\nSee [`examples/README.md`](./examples/README.md) for details.\n\n## Scripts\n\n```bash\nnpm run typecheck   # tsc --noEmit\nnpm run lint        # eslint .\nnpm test            # vitest run\nnpm run build       # tsc → dist/\n```\n\n## CI / Release\n\nTwo GitHub Actions workflows are wired up:\n\n- **[`.github/workflows/ci.yml`](.github/workflows/ci.yml)** — runs on every push to `main` and every PR. Matrix-tests Node 22 + 24: typecheck → lint → test → build.\n- **[`.github/workflows/release.yml`](.github/workflows/release.yml)** — fires on `v*` git tags. Verifies the tag matches `package.json` version, runs the full pipeline, publishes to npm (with provenance), then creates a GitHub Release with auto-generated notes.\n\n### One-time setup before the first release\n\n1. **NPM access token** — create an automation token on npmjs.com, then add it as a repository secret named `NPM_TOKEN` (Settings → Secrets and variables → Actions).\n2. **Optional: `npm` environment** — for an extra manual-approval gate, create a GitHub environment called `npm` (Settings → Environments) and scope `NPM_TOKEN` to it. The workflow already references `environment: npm`; remove that block if you don't want the gate.\n3. **Provenance** — already on (`publishConfig.provenance: true`). It requires `id-token: write` (set in the workflow) and a matching `repository` field in `package.json` (set to the cguillerminet/boxtal-sdk repo).\n\n### Cutting a release\n\n```bash\nnpm version patch           # or minor / major — bumps package.json + creates a git tag\ngit push --follow-tags      # pushes the commit and the new vX.Y.Z tag\n```\n\nThe tag push triggers `release.yml`, which republishes if everything is green.\n\n","readmeFilename":"README.md","_rev":"1-9ac6489bf7295e483b5677339725d01c"}