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.

Laravel Polar automatically records orders whenever the order.created webhook fires. The Billable trait exposes these records as an Eloquent relationship, so you can query, filter, and display order history with the same patterns you use everywhere else in Laravel.
Orders are created automatically by the webhook handler — you never need to create them manually. Each Order model maps 1:1 to a Polar order and is linked to the billable model that initiated the checkout.

Accessing orders

Call $user->orders to retrieve all orders belonging to a billable model. Results are returned ordered by date descending — newest first.
$orders = $user->orders;
Each item in the collection is an instance of Danestves\LaravelPolar\Order.

Order attributes

The Order model exposes the following attributes. Monetary values are always stored in minor units (cents for USD) — divide by 100 before displaying to customers.
AttributeTypeDescription
polar_id`stringnull`The Polar order ID
statusOrderStatusCurrent status enum value
amountintTotal charged, in minor units (e.g. cents)
tax_amountintTax portion, in minor units
refunded_amountintAmount refunded so far, in minor units
refunded_tax_amountintTax portion of any refunds, in minor units
currencystringISO 4217 currency code, e.g. "usd"
ordered_atCarbonWhen the order was placed
refunded_at`Carbonnull`When the order was fully refunded, if applicable

Checking order status

Use the boolean helper methods to check the current state of an order instead of comparing the status attribute directly.
$order->paid();             // true when status === OrderStatus::Paid
$order->refunded();         // true when status === OrderStatus::Refunded
$order->partiallyRefunded(); // true when status === OrderStatus::PartiallyRefunded
The refunded_at timestamp is set when the order moves to fully refunded status. You can use it to display the refund date to customers:
if ($order->refunded()) {
    echo 'Refunded on ' . $order->refunded_at->toFormattedDateString();
}
partiallyRefunded() returns true when some amount has been refunded but the order is not fully refunded. An order can move from partiallyRefunded to refunded if subsequent refunds cover the remaining balance.

Checking for a specific product

To determine whether a particular order is for a given product, use hasProduct():
if ($order->hasProduct('product_id_123')) {
    // This order is for the specified product
}
To check whether the user has ever completed a paid purchase for a product — regardless of which order — use hasPurchasedProduct() on the billable model:
if ($user->hasPurchasedProduct('product_id_123')) {
    // The user has at least one paid order for this product
}
hasPurchasedProduct() checks the customer’s order history for a completed purchase matching the given product ID, so it only returns true for paid orders.
Use hasPurchasedProduct() in authorization policies or middleware to gate access to one-time purchases, such as downloadable content or lifetime licenses.

Displaying order history in a Blade view

Pass the user’s orders to your view and render them in a table:
// In your controller
public function index(Request $request): View
{
    return view('orders.index', [
        'orders' => $request->user()->orders,
    ]);
}
<table>
    <thead>
        <tr>
            <th>Order ID</th>
            <th>Date</th>
            <th>Amount</th>
            <th>Currency</th>
            <th>Status</th>
        </tr>
    </thead>
    <tbody>
        @forelse ($orders as $order)
            <tr>
                <td>{{ $order->polar_id }}</td>
                <td>{{ $order->ordered_at->toFormattedDateString() }}</td>
                <td>{{ number_format($order->amount / 100, 2) }}</td>
                <td>{{ strtoupper($order->currency) }}</td>
                <td>
                    @if ($order->paid())
                        Paid
                    @elseif ($order->refunded())
                        Refunded on {{ $order->refunded_at->toFormattedDateString() }}
                    @elseif ($order->partiallyRefunded())
                        Partially refunded
                    @else
                        {{ $order->status->value }}
                    @endif
                </td>
            </tr>
        @empty
            <tr>
                <td colspan="5">No orders found.</td>
            </tr>
        @endforelse
    </tbody>
</table>
Amounts are stored in minor units (cents for USD). Divide by 100 before displaying them to customers.