laravel-creem
default — updating stats…
No stats yet — add your API key in Setup
Laravel Creem Demo

Interactive demo for the laravel-creem package — a full-featured Laravel SDK for the Creem payment platform. Connect your test API key in API Setup and explore every feature live against the real API.

Quick Start
1
Get your test API key
Sign up at creem.io → Dashboard → Developers → API Keys. Copy the key starting with creem_test_.
2
Connect in API Setup
Open the API Setup tab, paste your key, and click Save & Connect. The stats bar will turn green.
3
Create a product
Switch to One-Time Payments and click + Random Product to create a product via the API.
4
Run a test checkout
Click Buy on any product. You'll be redirected to a real Creem checkout. Use test card 4242 4242 4242 4242.
5
Watch webhooks fire
After payment, open Webhooks & Access to see the captured checkout.completed event.
Running on localhost? Creem needs a public HTTPS URL to deliver webhooks. Expose your local app with ngrok (ngrok http 8000) or Cloudflare Tunnels, then add the generated URL as a webhook endpoint in your Creem dashboard.
Test Cards
4242 4242 4242 4242 Success
4000 0000 0000 9995 Decline
4000 0025 0000 3155 3DS Auth

Any future expiry · any 3-digit CVV

What you can do
🛍️
One-Time Payments
Create products, generate checkout links, process real payments.
🔄
Subscriptions
Recurring plans with 4 billing periods (monthly to yearly).
🏷️
Discounts
Percentage or fixed-amount coupon codes applied at checkout.
📡
Webhooks
Live events: checkout.completed, subscription.paid, etc.
🔐
Access Control
GrantAccess / RevokeAccess driven by webhook events.
💳
Transactions
Browse real payment transactions from the Creem API.
👤
Multi-Profile
Switch API environments (sandbox ↔ production) on the fly.
📋
Code Examples
Copy-ready Laravel snippets on every tab.
Profile name
creem_test_ = sandbox  ·  creem_ = live
From Creem Dashboard → Developers → Webhooks. The webhook URL is generated below after saving.
Demo always uses test_mode: true. Do not use production keys — use only test keys starting with creem_test_
Multi-profile Example
// Example: seed two profiles into the demo session
// (run in a controller, tinker, or route during development)
session(['creem_demo_config' => [
    'default' => ['api_key' => 'creem_test_default_xyz', 'webhook_secret' => 'whsec_...'],
    'staging' => ['api_key' => 'creem_test_staging_abc', 'webhook_secret' => 'whsec_...'],
]]);
session(['creem_demo_active_profile' => 'staging']);

// Apply session config to runtime so Creem::profile('staging') works
\Modules\CreemDemo\Livewire\ConfigurationForm::applySessionConfig();

// Now you can call via profile name:
// Creem::profile('staging')->products()->list();
One-Time Products
billing_type = onetime
🔑
Configure API credentials in Setup first.
Code Example

// Create a one-time product
$product = Creem::products()->create([
    'name'         => 'My Digital Product',
    'price'        => 2999,   // in cents
    'currency'     => 'USD',
    'billing_type' => 'onetime',
    'tax_mode'     => 'inclusive',
    'tax_category' => 'saas', // string, not array
]);

// Create checkout session
$checkout = Creem::checkouts()->create([
    'product_id'  => $product['id'],
    'customer'    => ['email' => $user->email],
    'success_url' => route('dashboard'),
    'metadata'    => ['user_id' => $user->id],
]);

// IMPORTANT: always guard against null url
$url = $checkout['checkout_url'] ?? null;
if (!$url) {
    // Log the error for debugging
    Log::error('Creem checkout_url missing', [
        'product_id' => $product['id'],
        'user_id' => $user->id,
        'response' => $checkout,
    ]);

    // Display a user-friendly error message
    return redirect()->route('dashboard')->withErrors([
        'checkout' => 'Unable to create checkout session. Please try again later.',
    ]);
}

return redirect($url);
Recurring Plans
monthly · quarterly · bi-annual · annual
🔑
Configure API credentials in Setup.
Code Example

// All valid billing_period values:
// every-month | every-three-months
// every-six-months | every-year

$plan = Creem::products()->create([
    'name'           => 'Pro Plan',
    'price'          => 2900,
    'currency'       => 'USD',
    'billing_type' => 'recurring',
    'billing_period' => 'every-month',
    'tax_mode'       => 'inclusive',
    'tax_category'   => 'saas',
]);

$checkout = Creem::checkouts()->create([
    'product_id'  => $plan['id'],
    'customer'    => ['email' => $user->email],
    'success_url' => route('dashboard'),
]);

// Guard against null checkout_url
$url = $checkout['checkout_url'] ?? null;
if (!$url) {
    Log::error('Checkout failed', [
        'product' => $plan['id']
    ]);
    return back()->withErrors([
        'payment' => 'Checkout unavailable'
    ]);
}

return redirect($url);

// Manage subscriptions via real API
Creem::subscriptions()->cancel($subId);
Creem::subscriptions()->pause($subId);
Creem::subscriptions()->resume($subId);
Discount Codes
Create percentage or fixed coupons via API
🏷️
Configure API credentials in Setup first.
Code Example

// Percentage discount for specific products
Creem::discounts()->create([
    'name'        => 'Launch Special',
    'type'        => 'percentage',
    'percentage'  => 30,        // 30%
    'code'        => 'LAUNCH30',
    'duration'    => 'forever',
    'currency'    => 'USD',
    'applies_to_products' => [$productId],
]);

// Fixed-amount discount for multiple products
$productIds = ['prod_123', 'prod_456'];
Creem::discounts()->create([
    'name'               => '$10 Off Bundle',
    'type'               => 'fixed',
    'amount'             => 1000,     // $10.00 in cents
    'code'               => 'SAVE10',
    'duration'           => 'once',
    'currency'           => 'USD',
    'applies_to_products'=> $productIds,
]);

// Apply discount at checkout
Creem::checkouts()->create([
    'product_id'    => $productId,
    'discount_code' => 'LAUNCH30',
    'customer'      => ['email' => $user->email],
]);
Transactions
Loading…
No transactions found.
Page 1
Code Example

// List transactions
use Romansh\LaravelCreem\Facades\Creem;

// Apply session config first (demo uses session-backed profiles)
\Modules\CreemDemo\Livewire\ConfigurationForm::applySessionConfig();

$txns = Creem::profile('default')->transactions()->list([
    'page_number' => 1,
    'page_size'   => 20,
]);

foreach ($txns['items'] ?? [] as $t) {
    $id = $t['id'] ?? $t['transaction_id'];
    $amount = isset($t['amount']) ? number_format($t['amount'] / 100, 2) : null;
    $customer = data_get($t, 'customer') ?? $t['customer_id'];
    echo "{$id} — {$amount} — customer: {$customer}\n";
}
Access Log
GrantAccess / RevokeAccess
🔐
No access events yet.
Complete a test checkout to trigger GrantAccess.
Event Log 0
📡
Waiting for events…
Register your URL in Creem Dashboard, then complete a test checkout.
URL to register:
https://your-domain.com/creem/webhook
Event → Action Mapping
checkout.completed GrantAccess
subscription.paid GrantAccess
subscription.canceled RevokeAccess
subscription.expired RevokeAccess
AppServiceProvider

use Romansh\LaravelCreem\Events\GrantAccess;
use Romansh\LaravelCreem\Events\RevokeAccess;

// In AppServiceProvider::boot()
Event::listen(GrantAccess::class,
    function (GrantAccess $event) {
        // $event->customer['email']
        // $event->metadata  (from checkout)
        User::where('email',
            $event->customer['email'])
            ->update(['is_pro' => true]);
    }
);

Event::listen(RevokeAccess::class,
    function (RevokeAccess $event) {
        User::where('email',
            $event->customer['email'])
            ->update(['is_pro' => false]);
    }
);
🧪 Test Cards
4242 4242 4242 4242 Success
4000 0000 0000 9995 Decline
4000 0025 0000 3155 3DS Auth

Any future expiry · any 3-digit CVV