Vortos
Paddle Billing

Configuration

Full configuration reference for the Vortos Paddle billing package.

Configuration

config/paddle.php receives Vortos\Paddle\DependencyInjection\VortosPaddleConfig.

config/paddle.php
<?php

declare(strict_types=1);

use Vortos\Paddle\DependencyInjection\VortosPaddleConfig;

return static function (VortosPaddleConfig $config): void {
    $config
        ->mode($_ENV['PADDLE_MODE'] ?? 'sandbox')
        ->apiKey($_ENV['PADDLE_API_KEY'] ?? '')
        ->notificationSecret($_ENV['PADDLE_NOTIFICATION_SECRET'] ?? '')
        ->webhookPath('/webhooks/paddle');

    $config->client()
        ->maxRetries(3)
        ->retryOnRateLimit(true)
        ->idempotencyKeyTtlSeconds(86400);

    $config->circuitBreaker()
        ->failureThreshold(5)
        ->resetTimeoutSeconds(60);

    $config->security()
        ->enforceIpAllowlist(false)
        ->replayWindowSeconds(5);
        // allowSandboxIps is auto-set when mode=sandbox

    $config->webhooks()
        ->enabled(true)
        ->idempotencyTable('paddle_webhook_idempotency')
        ->idempotencyTtlSeconds(259200);

    $config->outbox()
        ->maxAttempts(5)
        ->backoffBaseSeconds(60)
        ->backoffCapSeconds(3600)
        ->batchSize(50)
        ->sleepSecondsWhenEmpty(2);

    $config->observability()
        ->logging(true)
        ->tracing(true)
        ->metrics(true);
};

You can also provide an environment-specific override:

config/prod/paddle.php
<?php

declare(strict_types=1);

use Vortos\Paddle\DependencyInjection\VortosPaddleConfig;

return static function (VortosPaddleConfig $config): void {
    $config->mode('live');
};

Mode

ValueDescription
sandboxPaddle sandbox. Sandbox webhook IPs are automatically allowed.
livePaddle production. Use for real billing.

API Client

OptionDefaultDescription
maxRetries3Retries on transient Paddle API errors.
retryOnRateLimittrueRetry after 429 rate limit responses.
idempotencyKeyTtlSeconds86400How long idempotency keys are stored (seconds).

Circuit Breaker

OptionDefaultDescription
failureThreshold5Consecutive failures before the circuit opens.
resetTimeoutSeconds60Seconds before attempting recovery after the circuit opens.

Webhooks

OptionDefaultDescription
enabledtrueRegister the webhook controller route.
idempotencyTablepaddle_webhook_idempotencyTable for deduplicating incoming events.
idempotencyTtlSeconds2592003 days — how long received event IDs are retained.

Security

OptionDefaultDescription
enforceIpAllowlistfalseBlock requests not from Paddle IP ranges.
replayWindowSeconds5Reject webhook signatures older than this many seconds.
allowSandboxIpsautoAuto-enabled when mode=sandbox. Set explicitly to override.

Outbox

OptionDefaultDescription
maxAttempts5Delivery attempts before an entry is permanently failed.
backoffBaseSeconds60Base for exponential backoff: attempt 1 = 60s, attempt 2 = 120s, etc.
backoffCapSeconds3600Maximum backoff delay (1 hour).
batchSize50Rows processed per relay cycle.
sleepSecondsWhenEmpty2Pause between polls when the outbox is empty (worker mode).

Outbox delivery is at-least-once

The relay re-runs any row whose status = pending and next_attempt_at <= now. Idempotency keys in the Paddle SDK protect against duplicate API side effects within the TTL window.

On this page