PnPjs: a fluent, type-safe client for SharePoint and Graph REST APIs
Fluent JavaScript API for SharePoint and Microsoft Graph REST APIs
At a glance
- What is it?
- PnPjs is a community built JavaScript and TypeScript library that wraps the SharePoint and Microsoft Graph REST endpoints in a fluent, typed API. It runs in SharePoint Framework, in Node.js and in plain browser projects, and it carries no Microsoft support SLA.
- Who is it for?
- PnPjs earns a place in SharePoint Framework or Node.js code that calls the same REST endpoints repeatedly, where the fluent chaining and the TypeScript definitions save more than the abstraction costs. It is the wrong choice for a product that needs a support contract from Microsoft, because the project states plainly that there is no SLA and no direct support from Microsoft, and the published packages are not listed in the manifest you can read here.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 11 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
PnPjs exists to complement the Microsoft SDKs, not to replace them
The project describes itself as a fluent JavaScript API for consuming SharePoint and Microsoft Graph REST APIs in a type-safe way, and it positions itself as an open source initiative that complements the existing SDKs provided by Microsoft. That framing is the single most useful fact in the project description, because it tells you the goal is not to be another Microsoft-first SDK. The goal is to make raw REST calls pleasant from JavaScript.
The audience is broad but specific: developers building on the SharePoint Framework, developers working in Node.js, and developers in ordinary JavaScript projects. All three groups hit the same problem, which is that the REST surfaces of SharePoint and Graph are large and shaped by the underlying product rather than by an API designer's taste. PnPjs turns that surface into method chains that read like the domain, with types attached so the compiler can catch a mistyped path before the request leaves the browser.
Note what the project is not. It is not a Microsoft-provided module. The supportability section says so directly, and it says there is no SLA and no direct support for the component from Microsoft. Support comes from an active community, and issues are filed on the project's own issues list. Anyone evaluating this for a supported production service has to price that difference in.
A monorepo of packages, versioned in the manifest rather than in releases
The repository root describes a monorepo layout rather than a single package. The private root manifest is named @pnp/monorepo, carries version 4.22.0, and declares the package as an ES module. Underneath it sit directories for packages, docs, samples, test, tools and debug, plus a buildsystem-config.ts and a set of tsconfig files that include a separate localresolver build.
That localresolver file is worth noticing, because it implies the library can resolve packages locally during development rather than pulling them from a registry. The build itself runs through a separate tool, @pnp/buildsystem, and the root scripts show the shape of the workflow.
"build": "npm run pnp-buildsystem-init && pnpbuild -n build",
"lint": "eslint ./packages ./test --ext .ts",So a contributor does not run a plain tsc invocation for the whole tree. The build is driven by pnpbuild in a build mode, and linting is scoped to the packages directory and the test directory with the TypeScript extension flag.
Two details about how versions surface. The default branch is version-4, and the project has no GitHub releases at all. The only version number a reader can confirm is the one in package.json, currently 4.22.0. A consumer therefore cannot pick up release notes from a releases page, and the changelog in the repository root and the documentation site, which is updated with each release, are the places to look instead.
The samples directory is the fastest way to see a working PnPjs call
Because the repository publishes no releases and keeps its documentation on a separate site, the samples are the most concrete artefact in the tree. There are six of them: an Azure Function, a custom bundle webpack setup, a Node.js application, a project preset, a readme, and a SharePoint Framework React components sample.
Each of those names answers a question an adopter actually has. The Azure Function sample covers server-side execution. The Node.js application sample covers running outside the browser. The custom bundle webpack sample covers injecting PnPjs into an existing bundler setup, which is where most integration pain lives. The project preset sample covers the scaffolding path, and the SPFx React components sample covers the framework case that the project name is built around.
What the samples do not do is fill in the details. The project itself points readers to the Getting Started guide in the main documentation for the actual first step, and to the transition guide for anyone moving from v2. So the honest reading order is: skim the sample that matches your hosting model, then read the Getting Started guide, and if your existing code predates the current major version, read the transition guide before you start editing.
The library supports the SharePoint Framework, Node.js and plain JavaScript projects, so the same core API serves all three. Where the environment differs, the differences live in the authentication and request setup rather than in the query surface.
A major version transition sits between v2 code and the current branch
The project carries a standing note for anyone arriving from v2, pointing to a transition guide hosted with the documentation. Its presence is a signal about upgrade cost rather than a footnote.
The scale of the change is visible in the repository itself. The current development branch is version-4, the root manifest sits at 4.22.0, and the source tree carries separate tsconfig files for the build system, for the local resolver and for the base project. Reaching a numbered 4.x means the API surface has been revised across at least two major boundaries since v2, and a consumer with v2 code in production is looking at a migration, not a patch.
Two more upgrade signals sit in the devDependencies. The TypeScript compiler is pinned to the 4.x line, and the Node type definitions are pinned to 18.11.9. The eslint packages are on the 8.x line as well, with @typescript-eslint at 6.21.0. These are the versions the project itself builds and tests against, so if your application uses a newer TypeScript or a newer eslint, you are compiling against a different toolchain than the maintainers use, and type definition mismatches between your app and the library are a realistic source of friction.
The good news for an adopter is that the tooling is conventional. Mocha with chai and chai-as-promised, webpack for bundling, del-cli for cleaning, yargs for CLI flags. There is no exotic build step to reverse engineer.
Licence terms and support are the two things to read before signing off
The licence is not one of the common permissive identifiers. The licence field carries a custom notice that GitHub cannot classify, and the LICENSE file in the repository root is the authority. That matters for legal review rather than for engineering, but it means an organisation with an automated licence allowlist will not get a clean pass from the metadata and will need to read the file. A disclaimer in the project description states that the code is provided as is, without warranty of any kind, including implied warranties of fitness for a particular purpose and non-infringement.
On support, the wording is unusually direct. The project is described as an open source, community provided library with an active community supporting it, and it states explicitly that this is not a Microsoft provided module, so there is no SLA and no direct support from this open source component. It also notes that the contributors include Microsoft and community contributors, with the work done as an open source community project, and that it follows the Microsoft Open Source Code of Conduct with a contact address for questions.
For a reader evaluating this, the distinction is simple. A bug in your own PnPjs code is your problem to file on the issues list. A question about how the community or the maintainers will respond to an upstream SharePoint or Graph change is not something the library promises to answer, because the commitment is community effort rather than a service agreement.
Where PnPjs is the wrong tool
Three cases stand out. The first is any product that requires a support contract with the platform vendor. The supportability section is unambiguous about the absence of an SLA, and no amount of good engineering in the library changes that. Where a procurement checklist requires an SLA for the library that talks to SharePoint, this project does not satisfy it.
The second case is a codebase that only needs a handful of REST calls. PnPjs brings a package family, a build system, a documentation site and a major version migration path with it. For a one-off list of items, a typed fetch wrapper against the REST endpoint is smaller in every dimension, and it does not tie the project to the abstraction's major version schedule.
The third case is a team that wants the Microsoft-provided SDK semantics. PnPjs positions itself as complementary to the SDKs Microsoft ships, and the project directs readers to the Microsoft 365 and Power Platform Community site for the wider initiative. If your organisation has standardised on the vendor client libraries, adopting PnPjs means running two client styles over the same tenant.
On the flip side, the failure mode to guard against is underestimating the upgrade path. The transition guide for v2 arrivals exists precisely because breaking changes landed, and the pinned TypeScript 4.x line plus the eslint 8 toolchain mean you should plan a dedicated pass rather than a dependency bump when you move to the version-4 branch.
Editorial conclusion
PnPjs earns a place in SharePoint Framework or Node.js code that calls the same REST endpoints repeatedly, where the fluent chaining and the TypeScript definitions save more than the abstraction costs. It is the wrong choice for a product that needs a support contract from Microsoft, because the project states plainly that there is no SLA and no direct support from Microsoft, and the published packages are not listed in the manifest you can read here. Before adopting, check the transition guide if your code targets v2, confirm the packages directory in the monorepo carries the module you need, and pin to the version recorded in package.json, which is 4.22.0.
Frequently asked questions
What is PnPjs used for?
PnPjs is a fluent, type-safe JavaScript and TypeScript API for consuming SharePoint and Microsoft Graph REST APIs, and it is positioned as complementing the SDKs provided by Microsoft. It can be used with SharePoint Framework, Node.js or plain JavaScript projects.
How do I install PnPjs and run my first call?
The project documentation sends readers to the Getting Started guide in the main documentation for the first step, and the samples directory in the repository holds working setups for Azure Functions, Node.js, SPFx React components, a project preset and a custom webpack bundle. The visible root manifest is the private monorepo manifest @pnp/monorepo at version 4.22.0, so it does not list the installable packages for a consumer.
Does Microsoft support PnPjs?
The supportability section states that the project is a community provided open source library, that it is not a Microsoft provided module, and that there is no SLA or direct support from Microsoft for the component. Support comes from the community, and issues are filed on the project issues list.
What do I need to know when moving from PnPjs v2?
The project keeps a standing note for v2 users pointing to a transition guide in the documentation. The current development branch is version-4 and the root manifest reports version 4.22.0, so migrating code means crossing more than one major version.
How do I build and lint the PnPjs repository?
The root package.json scripts run the build system for a build pass and lint the packages and test directories with the TypeScript extension flag. The build depends on a local package.json entry for the build system init step before the build tool runs.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/pnp-pnpjs)