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-upPOST /auth/sign-inPOST /auth/sign-outGET /auth/mePATCH /auth/mePOST /auth/refreshPOST /auth/change-passwordPOST /auth/forgot-passwordPOST /auth/reset-passwordPOST /auth/magic-linkPOST /auth/magic-link/verifyGET /auth/oauth/:providerGET /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.