Guide
Publish your TypeScript SDK to a private npm registry — Verdaccio, JFrog Artifactory, Sonatype Nexus, AWS CodeArtifact, Cloudsmith — without writing the glue yourself.
Last reviewed: April 23, 2026
Most serious shipping teams end up with a private npm registry. The reasons pile on: compliance demands every dependency come from an audited source, legal wants to keep API surface off public npm, platform wants package installs to work during a public-npm outage, security wants a single chokepoint where tarballs are scanned. Whether the tool is Verdaccio on an EC2 box or a paid JFrog Artifactory tenant, "the private registry" becomes part of the supply chain.
Generating a TypeScript SDK from OpenAPI and landing it on that registry sounds like one more publish target. It is, in the strict sense — the npm protocol is the npm protocol, and any conforming registry accepts a tarball. What makes it different is the operational tail: each registry has its own auth shape (bearer token here, basic auth there, a service account elsewhere), its own rotation cadence, its own audit hooks, its own network access story. None of that is interesting work, but all of it is work somebody has to do.
SDK Factory treats every standard-protocol npm registry as a uniform target. You paste the registry URL, paste a token, pick a package name, and the pipeline handles the same auto-rebuild-on-schema-change loop it does for public npm. Compliance, audit, and rotation are built into the product instead of each team reinventing them.
What you actually spend time on when you wire this by hand — and what eventually drifts.
Verdaccio wants `_authToken`. JFrog Artifactory wants `_auth` with base64-encoded credentials, or a different path per repo. Nexus wants yet another path style. AWS CodeArtifact wants a short-lived token from an `aws` CLI call. Getting the publish side right the first time on each registry is a ticket; keeping it right is a standing order.
A registry behind SAML or OIDC makes human access easy and automation access awkward. Teams end up with a service account whose credentials the CI pipeline holds, rotated on a calendar, with nobody confident what happens when the calendar misses a beat.
Some registries expire tokens every 30 days (CodeArtifact). Some never expire unless you revoke (Verdaccio, Artifactory classic tokens). Some depend on the backing identity provider's rotation policy. A mixed shop ends up with one rotation SOP per registry and no dashboard to see which is due.
When a customer asks "which exact tarball was live on 2026-03-18 at 10:42" you want an answer, not a grep through CI logs. Most internal publish pipelines don't retain the artifact — they retain the publish event. If the registry has gone through a retention sweep, the tarball is gone.
The hand-rolled version versus the pasted-URL version — same end state, very different footprint.
# 1. Figure out the right .npmrc for *this* registry
cat > .npmrc <<'INI'
registry=https://npm.internal.acme.io/repository/npm-releases/
//npm.internal.acme.io/:_authToken=${NPM_TOKEN}
always-auth=true
INI
# 2. Generate SDK, build, publish
npx @openapitools/openapi-generator-cli generate ...
cd generated && npm install && npm run build
npm version patch --no-git-tag-version
npm publish --registry https://npm.internal.acme.io/...
# 3. Token lifecycle — your calendar
# - rotate every 90d
# - update in GitHub Actions secrets
# - update in any other CI that references it
# - pray nobody forgets
# 4. Audit — whatever the registry retains
# if retention swept the 1.4.2 tarball, it is gonePaste schema URL: https://api.example.com/openapi.yaml Registry: [ custom ▼ ] URL: https://npm.internal.acme.io/repository/npm-releases/ Auth type: [ bearer token ▼ ] Token: •••••••••••• (AES256, rotatable) Package name: @acme/api-client ┌──────────────────────────┐ │ Create & auto-publish │ └──────────────────────────┘ → Tarball archived in S3 keyed by deployment ID. → Every publish: schema hash + version + SHA-256 retained. → Rotation is a form submit. No CI file edits.
The same pain points, handled by the pipeline — not by whoever is on call this week.
Paste the URL, paste the token, pick an auth type. Verdaccio, JFrog, Sonatype Nexus, AWS CodeArtifact, Cloudsmith, GitLab, an in-house mirror — all the same form. No per-registry quirks leaking into your CI.
Tokens are AES-256 encrypted at rest with the envelope key separate from the database. Rotation is a first-class operation on the dashboard, not a CI file edit. Rotation events are logged with timestamp and actor.
Each published tarball is stored in S3 keyed by deployment ID, in addition to the registry itself. If your registry purges an old version, drops under a retention policy, or suffers an outage, the canonical artifact is still one click from the dashboard.
Every deployment is persisted with: the schema hash that produced it, the registry target, the package version, the published-at timestamp, and the SHA-256 of the shipped tarball. "Which tarball was live on $date" has a single answer, not a log archaeology project.
Verdaccio (self-hosted or SaaS), JFrog Artifactory's npm repositories, Sonatype Nexus's npm format, AWS CodeArtifact, Cloudsmith, GitLab Package Registry, and GitHub Packages all ship as first-class registry targets. The common protocol they all implement is plain npm — a `PUT` to a tarball URL with an `Authorization` header — so the list is really "anything that speaks the npm protocol."
The per-registry variation is not in the protocol but in the auth shape. Bearer tokens are the common case. Basic auth (username + password, base64-encoded in the `Authorization` header) shows up on older Artifactory tenants and some on-prem Nexus instances. AWS CodeArtifact uses short-lived tokens fetched via `aws codeartifact get-authorization-token` — we support this as a scheduled refresh on our side so you don't schedule a cron to keep the token alive.
The one pattern we do not support today is mutual TLS. Registries that require client certificates for publish need a client identity on our infrastructure that the registry trusts, and we haven't wired that up. If your registry is behind mTLS, the honest answer is that a self-hosted generator + a bastion with the cert is a better fit than SDK Factory right now.
We publish over the public internet. Your registry has to be reachable from our egress IPs. For most private registries that means it's on a hostname with a real TLS certificate — which is the common case today, since cloud-hosted registries (CodeArtifact, Cloudsmith, JFrog Cloud) are internet-facing by default.
If your registry is VPN-only or on a private VPC, you have options: expose a read-only proxy on the public internet for our publish traffic, put the registry behind an IP-allowlisted ingress, or run a self-hosted generator instead. The "allowlist our egress IPs" path is the common choice and is documented on the app page once a custom registry is configured.
SSO in front of the registry doesn't change anything from our side — we use service-account credentials, the same way your CI does. If the SSO provider issues short-lived tokens, we support scheduled refresh.
Every tarball we publish is copied to S3, keyed by deployment ID, with a SHA-256 manifest. That artifact is retained independently of the registry — if your registry loses the version (unpublish, retention sweep, accidental delete), the tarball is still recoverable from the dashboard.
Each deployment also stores the canonicalised schema hash that produced it. "Which OpenAPI document produced version 1.4.3?" and "when did the schema actually change between 1.4.2 and 1.4.3?" both have one-click answers. That is the shape most audit questions take when a customer asks why something behaved unexpectedly on a specific date.
Re-publishing an archived tarball (for a rollback, or to re-seed a registry that lost a version) is a dashboard action on the Pro tier. The bytes are identical — not a rebuild from the same schema, which could produce a different artifact if the generator itself moved.
Only inside our database, associated with the app that uses it. It appears in operational logs in the same way any outbound URL does (request paths, response codes). It is not shared, aggregated, or surfaced in any public-facing product feature.
Yes — SDK Factory publishes from a fixed set of egress IPs that you can allowlist on your ingress. The current list is published on the app page for any app configured with a custom registry. We send change notices in advance when the set changes.
Not today. If mTLS is a hard requirement, a self-hosted generation path (OpenAPI Generator from a bastion with the cert) is the honest answer. We'd rather say that than build a half-working mTLS shim.
S3 storage, keyed by deployment ID, retained for the lifetime of the app (deleted apps are physically purged after 180 days per our retention SLA). The bytes are exactly what was published to the registry — same SHA-256.
Yes, from the dashboard's deployment detail page. Downloading the archived tarball gives you the identical artifact that the registry has; installing it from disk with `npm install ./pkg-1.4.3.tgz` works the same as installing from the registry.
OpenAPI to TypeScript SDK
Turn any OpenAPI 3.x document into a published, auto-rebuilding TypeScript SDK — without adding a single file to your API repo.
OpenAPI to npm package
Go from an OpenAPI URL to a versioned npm package on your registry — public, private, or custom — every time the schema changes.
OpenAPI to Zod-validated client
An OpenAPI-generated TypeScript client with Zod schemas validating every request and response at the runtime boundary.
OpenAPI to GitHub Packages
Publish a TypeScript SDK from your OpenAPI document to GitHub Packages, re-published automatically every time the schema changes.
One app on the Free tier, no card required. Paste your OpenAPI URL and see the generated private npm registry in minutes.