Skip to main content

Overview

SolvaPay bills and meters on the server side. Your product keeps its own client (CLI, web app, mobile) and its own identity provider (Auth0, Cognito, a custom IdP, or a provider CLI like login / init). Your backend holds sk_* and links each signed-in user to a SolvaPay customer via a stable externalRef. This is the canonical integration shape when you own the customer experience. SolvaPay does not need a credential in the CLI, a SolvaPay-hosted approval page, or IdP access tokens on SolvaPay APIs.

Quick start (any Node backend)

import { createSolvaPay } from '@solvapay/server'

const solvaPay = createSolvaPay({
  apiKey: process.env.SOLVAPAY_SECRET_KEY,
})

// `externalRef` = your stable user id (Auth0 sub, Cognito sub, internal user id, etc.)
const externalRef = 'auth0|abc123'

const customerRef = await solvaPay.ensureCustomer(externalRef, externalRef, {
  email: 'user@example.com',
  name: 'Jane Doe',
})

// Use customerRef for limits, usage, and payments
await solvaPay.trackUsage({
  customerRef,
  productRef: 'prd_myapi',
  usageType: 'requests',
  amount: 1,
})
ensureCustomer is idempotent: repeated calls with the same externalRef return the same SolvaPay customerRef.

The externalRef contract

RuleDetail
StableUse an identifier that does not change for the lifetime of the user (IdP sub, internal UUID, etc.). Do not use email alone.
DeterministicThe same user must always map to the same externalRef.
IdP-agnosticAny string your backend controls is valid. Auth0 sub is a common choice, not a requirement.
Provider-scopedexternalRef is unique per SolvaPay provider (your account), not globally.
Server-only linkageCall ensureCustomer from code that holds sk_*. Never send IdP access tokens to SolvaPay.
Secret key stays server-sidesk_* never belongs in a CLI, browser, or mobile app.

REST equivalent

The SDK wraps existing SDK customer endpoints:
  • GET /v1/sdk/customers?externalRef= — find by linkage
  • POST /v1/sdk/customers — create with { externalRef, email, name }
  • PATCH /v1/sdk/customers/:reference — update externalRef on an existing customer
ensureCustomer implements find-or-create-by-externalRef so you do not need to manage that flow yourself.
When you create a customer with an email that already exists under your provider and you supply an externalRef, the API links the externalRef onto the existing customer instead of returning 409 Conflict. This lets you idempotently adopt pre-existing SolvaPay customers when wiring up your own auth layer for the first time.

Provider-owned CLI pattern

A provider that ships its own CLI (for example your-cli login backed by Auth0) already has an authenticated user id after login. The CLI talks to your API; your API calls SolvaPay:
  1. CLI completes your IdP login and stores your session token (not sk_*).
  2. CLI calls your backend with that session.
  3. Backend resolves externalRef from the session (e.g. JWT sub).
  4. Backend calls ensureCustomer(externalRef) then trackUsage / payable / checkLimits.
No SolvaPay device flow or hosted handoff is required. See the runnable reference: express-provider-linkage example.

Web app pattern (Auth0 reference)

For Next.js + Auth0, the SDK ships a ready reference that forwards session.user.sub as billing identity: The Auth0 path is one linkage implementation. The same externalRef contract applies with any IdP.

Protecting routes after linkage

Once you have customerRef, pass it into paywall helpers:
const payable = solvaPay.payable({ product: 'prd_myapi' })

// Express: set x-customer-ref after ensureCustomer in your auth middleware
app.post('/tasks', payable.http(createTask))
For Next.js, prefer createAuth0AuthMiddleware (or your own adapter) so route handlers receive x-user-id / externalRef automatically. For Express and other frameworks, resolve externalRef in middleware, call ensureCustomer, then set x-customer-ref for payable.http().

What not to do

  • Do not put SOLVAPAY_SECRET_KEY in a customer CLI or browser.
  • Do not send Auth0 (or other IdP) access tokens to SolvaPay APIs.
  • Do not rely on email alone as externalRef — emails can change; subjects and internal ids should not.
  • Do not assume SolvaPay will host your customer login. Use MCP OAuth only when your OAuth clients need SolvaPay as the authorization server (e.g. MCP / third-party apps), which is separate from provider-owned CLI linkage.