Skip to main content

Documentation Index

Fetch the complete documentation index at: https://danestvesllc-2b77d201.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

The checkout method on any Billable model creates a Polar-hosted checkout session and returns a redirect response. Chain additional modifiers to control the success URL, prefill metadata, or override the price before the session is created.
How it works: Calling checkout() makes an API request to Polar, which creates a hosted checkout URL. Returning the result from a route automatically redirects the user to that URL. After payment, Polar fires a webhook back to your app.
Before you can pass product IDs, you need to know what they are. Run php artisan polar:products to print a table of all your products and their IDs.
php artisan polar:products

Single product checkout

Pass an array with one product ID to present a checkout for a single product:
use Illuminate\Http\Request;

Route::get('/subscribe', function (Request $request) {
    return $request->user()->checkout(['product_id_123']);
});
The checkout method returns a Checkout instance, which implements Responsable. Returning it from a route or controller automatically issues a 303 redirect to the Polar-hosted checkout page.

Multiple products checkout

Pass multiple product IDs to let the customer choose between plans — for example, monthly, yearly, and lifetime variants of the same product:
use Illuminate\Http\Request;

Route::get('/subscribe', function (Request $request) {
    return $request->user()->checkout([
        'monthly_product_id',
        'yearly_product_id',
        'lifetime_product_id',
    ]);
});
Polar presents the products as selectable options on a single checkout page.
Checkout URLs are generated via an API call to Polar on each request. If you render the URL frequently (for example, in a pricing table served to every visitor), cache the result to avoid unnecessary API calls.
$url = cache()->remember('checkout_url', now()->addHour(), function () use ($request) {
    return $request->user()->checkout(['product_id_123'])->url();
});

Custom price override

Use charge to override the product’s price. The first argument is the amount in the smallest currency unit (cents for USD):
use Illuminate\Http\Request;

Route::get('/subscribe', function (Request $request) {
    return $request->user()->charge(1000, ['product_id_123']);
});
charge is a shorthand for checkout with an explicit amount option. The rest of the fluent API applies equally.

Redirect after purchase

Chain withSuccessUrl to send customers to a custom page after they complete the checkout:
$request->user()->checkout(['product_id_123'])
    ->withSuccessUrl(url('/success'));
To capture the checkout session ID on the success page, include the {CHECKOUT_ID} placeholder in the URL. Polar replaces it with the actual session ID before redirecting:
$request->user()->checkout(['product_id_123'])
    ->withSuccessUrl(url('/success?checkout_id={CHECKOUT_ID}'));
You can then read request('checkout_id') on your success page to look up the order or display a confirmation message.

Custom metadata

Attach arbitrary key-value pairs to the checkout session using withMetadata. This data appears in the relevant webhook payloads after purchase:
$request->user()->checkout(['product_id_123'])
    ->withMetadata(['plan' => 'pro', 'source' => 'landing-page']);
To attach data that is copied to the customer record instead, use withCustomerMetadata:
$request->user()->checkout(['product_id_123'])
    ->withCustomerMetadata(['company' => 'Acme Inc.', 'referral' => 'google']);
Metadata values must be strings, integers, or booleans. Keys must be 40 characters or fewer, values must be 500 characters or fewer, and you can include up to 50 pairs.
The following keys are reserved by Laravel Polar and must not be used in withMetadata or withCustomerMetadata. Using them will throw an exception:
  • billable_id
  • billable_type
  • subscription_type
These keys are used internally to associate Polar webhooks with the correct billable model in your database.

Full example — all modifiers chained

All modifiers are chainable. Here’s everything combined in a single expression:
use Illuminate\Http\Request;

Route::get('/subscribe', function (Request $request) {
    return $request->user()
        ->checkout(['product_id_123'])
        ->withSuccessUrl(url('/success?checkout_id={CHECKOUT_ID}'))
        ->withMetadata(['source' => 'pricing-page'])
        ->withCustomerMetadata(['company' => 'Acme Inc.']);
});