Pi Network Authentication Guide For GenAI Agents

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.

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.

<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.

import { PiClient } from 'pi-sdk-js';

const client = new PiClient();

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 useContext hook or a custom usePiAuth hook to manage global user state.
  • Vue/Svelte: Use a reactive store (Pinia/Svelte Store) to hold the user and authResult objects once the service resolves.
  • Angular: Implement the PiService as an @Injectable singleton.

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 /me endpoint.
  • 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

/**
 * 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:

  1. Event Binding: Attach a listener to a “Login” button.
  2. Call Service: Execute piService.login().
  3. UI Update: Transition the interface from “Guest” to “User” state using the returned user.username.
  4. Token Exchange: Send the accessToken to your application backend for verification against the Pi API.

Example UI Trigger

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/await with pi-sdk-js to avoid callback nesting.
  • Error Boundaries: Always implement a try/catch block around authentication to handle user cancellations.
  • Scope Minimization: Only request the payments scope 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.