Skip to main content

Table of Contents

Installation

Install the required packages:

Basic Setup

1. Initialize SolvaPay

Create a SolvaPay instance in your Express app:

2. Protect Your First Endpoint

Wrap your business logic with the payable.http() adapter:
That’s it! The endpoint is now protected. The paywall will:
  • Check if the customer has a valid purchase
  • Track usage and enforce limits
  • Return a paywall error with checkout URL if needed

Protecting Endpoints

Multiple Endpoints

Create one payable handler and apply it to all protected endpoints:
Plans are managed on the product in SolvaPay Console. Customers select a plan during activation and the SDK resolves the correct plan from their purchase automatically.

Accessing Request Data

The HTTP adapter passes the Express request object to your business logic:

Authentication Integration

SolvaPay needs to identify customers. You can pass customer references in several ways: Extract customer reference from a custom header:

Option 2: JWT Token

Extract customer ID from a JWT token:

Option 3: Custom Customer Reference Extraction

Use the getCustomerRef option for more complex scenarios:

Error Handling

Basic Error Handling

The HTTP adapter routes paywall gate outcomes through a formatGate channel that emits a 402 response with the standard JSON body ({success:false, error, product, checkoutUrl, message, ...}). Merchants don’t need to catch anything for the happy path:

Custom Paywall Responses

Use paywall.decide() directly when you want full control over the 402 response shape (e.g. a hand-rolled route that doesn’t use payable.http()):

Legacy PaywallError Compat

Consumers that still try/catch a PaywallError keep working — PaywallError is exported as a compat shim for merchant code that throws from deep inside business logic:

Advanced Usage

Custom Customer Reference Extraction

Override customer reference extraction per endpoint:

Response Transformation

Transform responses before sending:

Streaming Responses with payable.gate()

payable.http() owns the whole response, which doesn’t fit streaming or SSE endpoints. For those, use payable.gate() — it returns a decision instead of wrapping a handler, so you keep full control of the response and report usage yourself:
The allow result carries:
  • customerRef — the resolved customer (defaults to the x-customer-ref header)
  • trackSuccess(opts?) / trackFail(error, opts?) — fire-and-forget usage reporting; call exactly one of them after the stream finishes
  • decision — the underlying paywall decision, if you need plan details
Options: getCustomerRef(req) overrides customer resolution, and ctx accepts a Workers-style waitUntil so tracking outlives the response on edge runtimes. See examples/chat-checkout-demo in the SDK repo for a complete SSE chat endpoint built on payable.gate().

Response Formatting

The HTTP adapter automatically formats responses. Your business logic should return:
  • Object: Sent as JSON with 200 status
  • Error: Thrown as exception (PaywallError handled automatically)

Complete Example

Here’s a complete Express.js application with SolvaPay integration:

Testing the Example

Best Practices

  1. Extract Customer Reference Early: Use middleware to extract and validate customer references before they reach protected endpoints.
  2. Handle Paywall Errors Gracefully: Provide clear error messages and checkout URLs to users.
  3. Use Environment Variables: Store API keys and configuration in environment variables.
  4. Separate Business Logic: Keep your business logic functions separate from route handlers for better testability.
  5. Type Safety: Use TypeScript for better type safety and developer experience.
  6. Error Logging: Log errors appropriately for debugging while keeping sensitive information secure.

Next Steps