Testing & Development

Test everything before processing real payments. Salable's Test Mode is a complete sandbox with its own Products, Subscriptions, API keys, and data. Develop features, test edge cases, and validate changes with full Stripe test card integration. No risk to production.

Overview

Before handling real payments, verify that your Salable payment model works as intended. Salable's Test Mode provides a sandbox environment where you can experiment, validate your Payment Integration, and test your Subscription flows without affecting customers.

Test Mode is a fully functional parallel environment with its own Products, Subscriptions, API keys, and data. You can develop new features, test edge cases, or validate changes without touching production. Test Mode integrates with Stripe's test infrastructure for realistic payment simulation.

This guide covers testing strategies from initial integration development through production deployment.

Test Mode Fundamentals

Complete Environment Isolation

Test Mode and Live Mode are separate environments. A Product created in Test Mode exists only in Test Mode. This isolation extends to every resource: Plans, Subscriptions, Carts, Usage Records, Entitlements, Grantee Groups etc.

You can create test Products with experimental pricing, simulate Subscription lifecycles, test edge cases that would be difficult to reproduce in production, and validate integration changes with no risk to real customers.

The only difference between Test Mode and Live Mode is that Test Mode does not process real money. All payments use Stripe's test environment.

Note Test Mode API keys can only access Test Mode data. Webhooks are also segregated: test events go to test webhook endpoints, production events to production endpoints.

Stripe Requirements

Both Test and Live Mode require a Stripe account connected through Payment Integrations. Once connected, you can build your pricing structure (creating Products, configuring Plans, and setting up Line Items) even with minimal Stripe account setup.

To generate checkout links in Test Mode, complete two forms in the Stripe Connect onboarding process: the business type form and the personal details form. Without both forms, Stripe rejects checkout link generation with an error. Full onboarding (banking details, identity verification) is not required for Test Mode checkout links.

Live Mode requires full Stripe Connect onboarding. You can create Products and Plans with incomplete onboarding, but generating checkout links requires your Stripe account to be fully onboarded with Active status, including banking information and identity verification.

Stripe's test environment accepts special test card numbers that simulate different scenarios. The card number 4242 4242 4242 4242 always succeeds. The number 4000 0000 0000 0002 always declines. Other test cards simulate specific scenarios like authentication requirements, insufficient funds, or expired cards. Read about Stripe test environments here.

Setting Up Your Test Environment

Initial Configuration

Check the mode indicator in the dashboard sidebar. If you are in Live Mode, switch to Test Mode before proceeding.

Start by creating your Product(s) how you would intend to on Live Mode. This may be a single Product if you are testing a simple Subscription model, or multiple Products if you offer different services or add-ons.

Next configure Plans for your test Products with the pricing models you have in mind. For example a Basic Plan at $29/month, a Pro Plan at $79/month, and a Premium Plan at $99/month. Create and include the same Entitlements you will use in production so you can test feature access correctly.

Keep your test data accurate so you are simulating a production-level environment.

Test API Keys

Generate test API keys from the organization settings in the dashboard. These keys grant access only to Test Mode data.

Store test API keys as environment variables. Use separate configuration for development, staging, and production environments so each uses the appropriate API keys and endpoints.

# .env.development
SALABLE_API_KEY=test_abc123...
SALABLE_BASE_URL=https://salable.app/test
 
# .env.production
SALABLE_API_KEY=live_xyz789...
SALABLE_BASE_URL=https://salable.app/live

This configuration separation prevents accidentally using production keys during development or test keys in production.

Webhook Configuration for Testing

Configure test webhook endpoints that point to your development or staging servers. For local development, tools like ngrok provide public URLs that forward to your local server, allowing Salable to deliver webhooks to your development environment.

# Start ngrok to expose local port 3000
ngrok http 3000
 
# Use the ngrok URL as your test webhook endpoint
# Example: https://abc123.ngrok.io/webhooks/salable

Configure this ngrok URL as a test webhook endpoint in the Salable dashboard. Select the event types you want to receive, and save the signing secret for verifying webhook authenticity.

The dashboard's webhook delivery log shows each event sent to your endpoint, the payload, your endpoint's response, and whether delivery succeeded.

Testing Checkout Flows

Basic Subscription Purchase

Start by testing a customer subscribing to a Plan. This validates your checkout integration end-to-end.

Create a Cart in your application using your test API key. Add a Plan to the Cart, generate a checkout link, and navigate to it in your browser.

Stripe's checkout page loads in Test Mode, indicated by a "Test Mode" badge. Enter test payment information using Stripe test cards. Use the card number 4242 4242 4242 4242, any future expiry date, any CVC, and any postal code.

Click the payment button. Stripe processes the test payment instantly and redirects you to your configured success URL. Shortly after, your webhook endpoint receives a Subscription.created event.

Verify the Subscription appears in the Salable dashboard under Subscriptions. Check that your application provisioned access correctly. The customer should have the Entitlements associated with their Plan.

Testing Payment Failures

Payment failures are inevitable, so test that your application handles them gracefully. Stripe provides test card numbers that simulate failed or declined payments.

Use card number 4000 0000 0000 0002, which always declines with a generic decline code.

Use card number 4000 0000 0000 9995, which declines with an "insufficient funds" error.

Test authentication requirements using card number 4000 0025 0000 3155, which requires 3D Secure authentication. Complete the authentication challenge in the test flow to verify your checkout process handles it correctly.

Testing Different Currencies

If you support multiple currencies, test the checkout flow with each one. Create Carts specifying different currencies and verify that checkout displays amounts correctly, Stripe processes payments in the expected currency, and Subscriptions are created with correct pricing.

Team Subscription Checkout

For applications with team-based Subscriptions, test the team onboarding flow. Create a Grantee Group and add members to it. Next create a Cart with a per-seat Plan, assign the Grantee Group to the Cart item with the appropriate quantity.

Complete checkout and verify that all team members receive appropriate Entitlements. Test adding members after Subscription creation to validate seat management works correctly.

Testing Subscription Management

Upgrade and Downgrade Flows

Test Plan upgrades and downgrades with the Subscriptions you just created. In your application's Subscription management interface, trigger a Plan change from Basic to Pro. Verify that the API request succeeds, proration charges are calculated correctly, Entitlements update immediately to reflect the new Plan, and your application UI shows the new Plan.

Quantity Adjustments

For per-seat Plans, test increasing and decreasing seat quantities. Verify that quantity increases succeed and charge prorated amounts, quantity decreases respect minimum seat requirements, attempts to reduce below minimum seats are rejected, and Grantee Group size constraints are enforced if applicable.

Adding and Removing Plans

Test adding add-ons or additional Products to existing Subscriptions. Create another Subscription for one of your test Products, then use the Subscription modification API to add an add-on or another Product. Verify the new Plan appears on the Subscription, is included in invoices, and grants its Entitlements to the customer.

Test removing Plans by selecting a Subscription item and deleting it. Verify that the Plan is removed, associated Entitlements are revoked, and the customer is not charged for the removed Plan in future billing cycles. Verify that attempts to remove the last Plan from a Subscription are rejected. Subscriptions must always have at least one Plan.

Cancellation Testing

Test both types of cancellation to verify your implementation handles each correctly. Cancel a Subscription with end-of-period timing and verify that it remains active until the billing period ends, the customer retains access until the scheduled cancellation date, no refund is issued, and your application shows the upcoming cancellation to the customer.

Test immediate cancellation and verify that the Subscription terminates right away, Entitlements are revoked immediately, a prorated refund is issued if configured, and your application handles the sudden access revocation appropriately.

Test reversing scheduled cancellations by resuming a Subscription after scheduling end-of-period cancellation. Verify that the Subscription continues to auto-renew normally.

Testing Metered Usage

Recording Usage

If you have metered Line Items, test that usage is recorded correctly. In your application, trigger actions that should record usage: making API calls, consuming storage, or whatever your metered metric tracks.

Verify that usage recording API calls succeed, the correct quantity is recorded, and the slug correctly identifies the usage type. Usage increments accumulate by default. To test idempotency, send requests with the same idempotency-key header value; duplicate requests within 24 hours are deduplicated. Without the header, repeated calls increment the usage counter each time.

Test usage recording across multiple billing periods. Record usage, wait for the Subscription to bill (or manually advance time in your test), and verify that usage records finalize and appear on the invoice.

Checking Current Usage

Test your application's usage display by retrieving current usage counts through the API and displaying them to customers. Verify that counts are accurate, update in real-time as usage is recorded, and reset appropriately at the start of new billing periods.

If your application enforces usage limits, test that these limits work correctly. Record usage up to the limit and verify that your application prevents further usage or prompts the customer to upgrade.

Cross-Plan Metering

If you use the same metered slug across multiple Plans (such as shared API call tracking for Basic and Pro Plans at different per-unit prices), verify that usage recorded against one slug appears correctly on invoices for Subscriptions with different Plans, each customer is charged at their Plan's rate, and a single usage counter tracks consumption regardless of which Plan the customer has.

Shared metering requires careful testing to verify billing calculates correctly.

Testing Entitlements and Access Control

Entitlement Checking

Verify that your customers have access to the correct features through Entitlements. Call the Entitlement check API with a Grantee ID and Entitlement name, then confirm the response matches the user's Subscription status.

Test positive cases: verify that subscribed users with the appropriate Plan receive positive Entitlement checks. Test negative cases: verify that unsubscribed users, users on Plans without the Entitlement, and users with cancelled Subscriptions receive negative Entitlement checks.

Test timing boundaries by checking Entitlements immediately after Subscription creation, right before Subscription expiry, immediately after cancellation, and during trial periods. These boundary conditions surface timing bugs that grant or deny access incorrectly.

Grantee Group Access

For team Subscriptions, test that all members of a Grantee Group receive Entitlements from the group's Subscription. Add a user to a group associated with a Subscription, check that user's Entitlements, and verify they have access to features granted by the group Subscription.

Test removing users from groups and verify that their Entitlements update appropriately. If they have no other Subscriptions granting those Entitlements, they should lose access immediately.

Test users who belong to multiple Grantee Groups with different Subscriptions. Verify that they receive the union of Entitlements from all groups. If one group Subscription grants feature_a and another grants feature_b, the user should have both.

Entitlement Expiry

If you use Entitlements with expiry dates, test that access is granted before expiry and denied after. Create Entitlements with expiry dates in the near future, then check access before and after the expiry timestamp.

Testing Webhook Handling

Event Processing

Trigger each event type in Test Mode and verify your handler processes it correctly.

Create Subscriptions to trigger subscription.created events. Verify your handler provisions access, updates your database, or performs whatever initialization your application requires for new Subscriptions.

Modify Subscriptions to trigger subscription.updated events. Verify your handler detects the changes and updates your application state accordingly.

Cancel Subscriptions to trigger subscription.cancelled events. Verify your handler revokes access and updates Subscription status in your system.

Use Stripe test cards that simulate payment failures (like 4000 0000 0000 0002) to verify your application handles declined payments gracefully. Note that payment.failed is a Stripe webhook event, not a Salable event. Configure Stripe webhooks separately if you need to handle payment failures directly.

Idempotency Testing

Webhook deliveries can be duplicated, so your handlers must be idempotent. Test by resending the same webhook event multiple times through the dashboard's webhook delivery interface.

Verify that processing the same event multiple times has the same effect as processing it once: no duplicate records, no double provisioning, no multiple notifications.

The event ID included in webhook payloads is your tool for implementing idempotency. Store processed event IDs and skip events you have already seen.

Error Handling

Test how your webhook handler behaves when processing fails. Introduce errors in your handler code (for example, by commenting out database access temporarily) and observe webhook deliveries failing.

Verify that Salable retries failed deliveries according to the documented retry schedule. Check the dashboard's webhook delivery log to see retry attempts. Fix the error in your handler and verify that a subsequent retry succeeds.

This verifies your production system can recover from transient issues without losing events.

Webhook Security

Verify that your webhook handler validates signatures. Send a webhook with an invalid signature (modify the signature header before processing) and confirm your handler rejects it with a 401 response.

Send a webhook with no signature and verify rejection. Send a webhook with the correct signature and verify acceptance.

Performance and Load Testing

Rate Limit Verification

Verify that your application handles rate limits gracefully. Send more than 100 requests per second to the API and observe the 429 responses. Verify that your client implements exponential backoff and retries.

Test that your application continues to function under rate limiting: requests eventually succeed, users see no errors, and your system does not enter a retry storm.

Concurrent Operations

Test scenarios where multiple operations happen simultaneously. Create several Carts concurrently, modify the same Subscription from multiple requests, record usage from multiple sources simultaneously, and check Entitlements for many users in parallel.

Verify that your application handles concurrency without race conditions or duplicates. Database transactions, idempotency keys, and proper error handling are critical here.

Large Dataset Handling

If you expect many Subscriptions or high usage volumes, test with realistic data sizes. Create dozens or hundreds of test Subscriptions, record large volumes of usage, and retrieve large Subscription lists with pagination.

Verify that pagination works correctly, your application does not load excessive data into memory, and performance remains acceptable with realistic data volumes.

Integration Testing Strategies

End-to-End Test Suites

Build automated test suites that exercise flows from your application through Salable to Stripe and back.

An end-to-end Subscription test might create a Cart, add a Plan, generate a checkout link, simulate completing checkout (using test cards), wait for the webhook, verify the Subscription was created, check Entitlements, and verify your application state.

Continuous Integration

Integrate your test suite into your continuous integration pipeline. Configure your CI environment with Test Mode API keys, run the full test suite on every commit or pull request, and block deployments if tests fail.

Transitioning to Production

Pre-Launch Checklist

Before launching in Live Mode, verify your test mode data is accurate. Confirm your Test Mode integration works with all flows tested: success paths, error handling, edge cases, and webhook processing. Your Stripe Connect onboarding must be fully complete with an Active status. Incomplete Stripe Connect accounts prevent checkout links from working.

Once your test Products are accurate, navigate to the Product configuration page and click the Copy to Live Mode button. This copies your Product and all corresponding data (Plans, Line Items etc) to Live Mode.

Update your application configuration to use Live Mode API keys and endpoints. Configure production webhook endpoints with appropriate URLs and verify they are reachable.

Gradual Rollout

Consider launching to a limited audience first. A limited rollout lets you verify production behaviour with real customers and real money while limiting the impact of undiscovered issues.

Monitor error rates, webhook delivery success, payment success rates, and customer feedback during initial rollout. If everything looks good, expand access to your full customer base.

Production Monitoring

Once live, monitor key metrics: Subscription creation rates and success/failure patterns, payment success rates and decline reasons, webhook delivery success and processing times, Entitlement check response times, and error rates across all API operations.

Set up alerts for anomalies: sudden spikes in payment failures, webhook delivery failures, API error rates, or unexpected drops in Subscription creation.

Common Testing Scenarios

Free Trial to Paid Conversion

Test the trial lifecycle: create a Plan with a trial period, subscribe a test customer, verify they have full access during the trial, simulate time passing (or note when the trial ends), and verify that billing occurs correctly when the trial expires.

Test trial cancellation by canceling before the trial ends and verifying the customer is never charged.

Team Onboarding Flows

Test the team signup journey: an administrator creates an account, invites team members before purchasing, subscribes to a team Plan with appropriate seat quantity, and all team members receive access immediately.

After purchase, test team management: adding members, adjusting seat quantities, removing members, and verifying Entitlements update correctly.

Complex Multi-Plan Subscriptions

For customers who purchase multiple Products or add-ons together, test creating Carts with multiple Plans, completing checkout, verifying all Plans appear on the Subscription, and checking that all Entitlements from all Plans are granted.

Test modifying these multi-Plan Subscriptions by adding additional Plans, removing some Plans while keeping others, and changing quantities on specific Plans.

Migration from Other Systems

If you are migrating customers from another billing system to Salable, test your migration process thoroughly. Create test data representing your existing customer structures, run your migration scripts against Test Mode, verify Subscriptions are created with proper billing dates, and confirm Entitlements map correctly from old system to new.

Debugging and Troubleshooting

API Response Inspection

When tests fail or behaviour does not match expectations, examine API responses. Error messages include error codes for programmatic handling, human-readable descriptions, and details about validation failures or constraint violations.

Enable detailed logging in your application to capture API requests and responses during development.

Dashboard Investigation

The Salable dashboard provides another angle for investigating issues. View resources your API calls created or modified, check Subscription states and histories, review webhook delivery logs and event payloads, and examine usage records and invoice Line Items.

The dashboard complements API logs and often makes issues visible that would be opaque from request/response data alone.

Webhook Replay

Use the dashboard's webhook replay feature to resend events to your handler. This lets you fix bugs and reprocess events without recreating entire Subscription scenarios.

The replay preserves the original event ID, so your idempotency checking must allow for replays during development. You might need to clear your processed events table or add a development mode bypass.

Support Resources

If you cannot resolve an issue, contact Salable support. Include relevant Subscription IDs, API request/response details with full JSON payloads, webhook event IDs and payloads if applicable, and a description of what you expected versus what happened.

This context helps support staff diagnose issues and provide specific solutions.


Test checkout flows, Subscription management, usage tracking, Entitlements, and webhooks in Test Mode before launching. Catching issues here prevents production problems and support overhead.