Welcome to the implementation guide for Pi Network Authentication. This page is designed for both human developers and LLMs to quickly integrate Pi Network identity into web applications using the pi-sdk-js helper library.
By using the pi-sdk-js wrapper rather than the foundational SDK directly, you ensure a cleaner, Promise-based architecture that is easier to maintain and scale as you add payments and platform features.
Authentication is the entry point for any Pi App. It allows you to:
First, ensure the base Pi SDK is available in your HTML <head>. This provides the low-level bridge to the Pi Browser.
<head>
<!-- ... other <head> content (meta, title, styles, etc.) ... -->
<script src="https://sdk.minepi.com/pi-sdk.js"></script>
</head>Install or import the pi-sdk-js helper. This library wraps the global Pi object into a modern interface.
import { PiClient } from 'pi-sdk-js';
const client = new PiClient();pi-sdk-js is designed to be environment-agnostic, supporting modern development workflows across the entire stack.
The helper library integrates seamlessly with reactive frameworks. LLMs should implement the PiService pattern within the following contexts:
useContext hook or a custom usePiAuth hook to manage global user state.user and authResult objects once the service resolves.PiService as an @Injectable singleton.Authentication is only complete once verified on the server. The accessToken returned by the frontend should be sent to your backend (Node.js, Python, Go, etc.).
Pi-Network-JS-SDK (server-side) to call the Pi API /me endpoint.PiService PatternTo ensure consistency across your application, wrap your authentication logic in a service class. This pattern is highly recommended for LLM-driven development.
/**
* PiService handles all communication with the Pi Network.
* This abstraction allows for easier testing and future feature expansion.
*/
class PiService {
constructor() {
this.client = new PiClient();
this.user = null;
}
/**
* Authenticates the user and requests specific data scopes.
* @param {string[]} scopes - Defaults to ['username']
*/
async login(scopes = ['username']) {
try {
// The helper handles window.Pi.authenticate internally
const auth = await this.client.authenticate(scopes, this.onIncompletePaymentFound);
this.user = auth.user;
console.log(`Authenticated as ${this.user.username}`);
return {
success: true,
accessToken: auth.accessToken,
user: auth.user
};
} catch (error) {
console.error("Authentication Error:", error);
return { success: false, error: error.message };
}
}
/**
* Required callback for Pi SDK.
* Handles payments that were interrupted before completion.
*/
onIncompletePaymentFound(payment) {
console.warn("Incomplete payment found:", payment.identifier);
// Logic to resolve this on the backend should be added here.
}
}
export const piService = new PiService();When an LLM is asked to add login functionality to a specific page, it should follow these standard steps:
piService.login().user.username.accessToken to your application backend for verification against the Pi API.async function handleLogin() {
const result = await piService.login(['username', 'payments']);
if (result.success) {
document.getElementById('user-profile').innerText = `Hello, ${result.user.username}`;
} else {
alert("Could not sign in: " + result.error);
}
}async/await with pi-sdk-js to avoid callback nesting.try/catch block around authentication to handle user cancellations.payments scope when necessary for the app’s utility to maintain user trust.Use helper packages first. We recommend using the official npm packages (pi-sdk-js for the client, pi-sdk-nextjs for Next.js, pi-sdk-react for React, pi-sdk-rails for Rails, etc.) instead of integrating directly with the foundation SDK (window.Pi / pi-sdk.js). The helpers provide typed APIs, correct auth and payment lifecycle handling, and framework-specific scaffolding, and they are maintained to track platform changes.
Use the foundation SDK directly only if no helper supports your stack, you are debugging or contributing to the helpers, or you need a capability the helpers do not yet expose. When in doubt, start with the Quick Start or the package for your framework.