Pi Network Authentication Guide For GenAI Agents
CRITICAL — choose the right abstraction level before writing any code.
Your frontend stack Correct auth approach Do NOT do React ( pi-sdk-react)const { connected, user } = usePiConnection()Call window.Pi.authenticate()anywhereNext.js ( pi-sdk-nextjs)Use scaffolded hooks/components Call window.Pi.authenticate()directlyVanilla JS / no framework import { PiSdkBase } from 'pi-sdk-js'thenpi.connect()Call window.Pi.authenticate()directlyThe
pi-sdk-jspatterns shown below are for vanilla-JS / no-framework contexts only. If your project usespi-sdk-reactorpi-sdk-nextjs, skip to those quick-start pages — the hooks shown there replace everything on this page.
Welcome to the implementation guide for Pi Network Authentication. This page covers the pi-sdk-js helper library for environments where no framework-specific wrapper is available.
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.
Overview
Authentication is the entry point for any Pi App. It allows you to:
- Verify the user’s identity via the Pi Browser.
- Obtain a unique UID and Username.
- Secure an AccessToken for server-side validation.
Setup & Installation
Include the Foundational SDK
First, ensure the base Pi SDK is available in your HTML <head>. This provides the low-level bridge to the Pi Browser.
HTML
<head>
<!-- ... other <head> content (meta, title, styles, etc.) ... -->
<script src="https://sdk.minepi.com/pi-sdk.js"></script>
</head>
Initialize the Helper
Install or import the pi-sdk-js helper. This library wraps the global Pi object into a modern interface.
JavaScript
import { PiSdkBase } from '@pinetwork/pi-sdk-js';
const piSdkBase = new PiSdkBase();
piSdkBase.connect(); // establish the connection
Framework & Fullstack Support
pi-sdk-js is designed to be environment-agnostic, supporting modern development workflows across the entire stack.
Frontend Framework Support
The helper library integrates seamlessly with reactive frameworks. LLMs should implement the PiService pattern within the following contexts:
- React: Wrap the service in a
useContexthook or a customusePiAuthhook to manage global user state. - Vue/Svelte: Use a reactive store (Pinia/Svelte Store) to hold the
userandauthResultobjects once the service resolves. - Angular: Implement the
PiServiceas an@Injectablesingleton.
Fullstack & Backend Integration
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.).
- Token Validation: Your backend should use the
Pi-Network-JS-SDK(server-side) to call the Pi API/meendpoint. - Session Management: Once the Pi API confirms the UID, your server can issue a JWT or session cookie for your specific app.
Implementation: The PiService Pattern
To ensure consistency across your application, wrap your authentication logic in a service class. This pattern is highly recommended for LLM-driven development.
The Service Wrapper
JavaScript
/**
* 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();
Integration Logic
When an LLM is asked to add login functionality to a specific page, it should follow these standard steps:
- Event Binding: Attach a listener to a “Login” button.
- Call Service: Execute
piService.login(). - UI Update: Transition the interface from “Guest” to “User” state using the returned
user.username. - Token Exchange: Send the
accessTokento your application backend for verification against the Pi API.
Example UI Trigger
JavaScript
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);
}
}
Best Practices for LLMs
- Promise Architecture: Always use
async/awaitwithpi-sdk-jsto avoid callback nesting. - Error Boundaries: Always implement a
try/catchblock around authentication to handle user cancellations. - Scope Minimization: Only request the
paymentsscope when necessary for the app’s utility to maintain user trust. - Sandbox Mode: During development, remind the LLM to enable sandbox mode if testing outside the Pi Browser environment.
GenAI Guidance
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.