Authentication

All API requests are scoped to a specific database via an API key. The SDK also provides end-user authentication — sign-up, sign-in, OAuth, and magic links — for apps that need user accounts.

Keep your API keys secret. Never expose them in client-side code or public repositories. Use a public key (read-only) for browser-side operations.

Getting your API key

Create and manage API keys from Dashboard → Databases → API Keys.

Initializing the client

import { createClient } from "paperdb";

const db = createClient({
  apiKey: process.env.PAPERDB_API_KEY,
  baseUrl: "https://api.paperdb.app", // or your self-hosted URL
});

Email / Password

// Sign up
const { user, session } = await db.auth.signUp({
  email: "user@example.com",
  password: "securepassword",
  name: "Alice"
});

// Sign in
const { user, session } = await db.auth.signIn({
  email: "user@example.com",
  password: "securepassword"
});

// Sign out
await db.auth.signOut();

// Get current user
const user = await db.auth.getUser();

OAuth (Google, GitHub)

OAuth redirects the browser to the provider. After the callback, the session token is appended to your redirectUrl.

// Redirects to Google — call from a button click
await db.auth.signInWithProvider({
  provider: "google",
  redirectUrl: "https://paperdb.app/auth/callback"
});

// On the callback page, extract the token from the URL
const token = new URLSearchParams(window.location.search).get("token");
if (token) db.auth.setSessionToken(token);

OAuth requires GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET or GITHUB_CLIENT_ID / GITHUB_CLIENT_SECRET to be set on the server, plus OAUTH_CALLBACK_BASE_URL.

Magic Links

Send a one-time sign-in link to a user's email. The link expires in 15 minutes and can only be used once.

// Send the magic link
await db.auth.sendMagicLink({
  email: "user@example.com",
  redirectUrl: "https://yourapp.com/auth/callback"
});

// On the verify page (token comes from the link URL)
const { user, session } = await db.auth.verifyMagicLink(email, token);

Password Reset

// Request a reset email (link valid for 1 hour)
await db.auth.resetPassword("user@example.com");

// Confirm the reset (token + email come from the reset link URL)
await db.auth.confirmResetPassword(email, token, "newpassword123");

Session Management

// Refresh session (extends expiry)
await db.auth.refreshSession();

// Change password (requires current password)
await db.auth.changePassword("currentpass", "newpass");

// Update profile
await db.auth.updateProfile({ name: "Bob", avatar: "https://..." });

// Listen to auth state changes
const unsubscribe = db.auth.onAuthStateChange((state) => {
  console.log(state.isAuthenticated, state.user);
});

Available API Routes

  • POST /auth/sign-up
  • POST /auth/sign-in
  • POST /auth/sign-out
  • GET /auth/me
  • PATCH /auth/me
  • POST /auth/refresh
  • POST /auth/change-password
  • POST /auth/forgot-password
  • POST /auth/reset-password
  • POST /auth/magic-link
  • POST /auth/magic-link/verify
  • GET /auth/oauth/:provider
  • GET /auth/oauth/:provider/callback

Rate Limits

The API enforces two rate limits, returned as response headers:

  • Per API key: 1,000 requests / minute — X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset
  • Per IP: 200 requests / minute (unauthenticated traffic)

Exceeding either limit returns 429 Too Many Requests with a retryAfter field in the response body.