PayFanout API reference
    Preparing search index...

    Interface PaymentRouterOptions

    interface PaymentRouterOptions {
        circuitBreaker?: false | CircuitBreakerOptions;
        defaultChain?: string[];
        onAttempt?: (
            attempt: {
                error?: PayFanoutError;
                ok: boolean;
                pspName: string;
                skipped?: boolean;
            },
        ) => void;
        onBreakerStateChange?: (
            event: { pspName: string; state: "opened" | "closed" },
        ) => void;
        rules?: RoutingRule[];
        service: PaymentService;
        shouldFailover?: (error: PayFanoutError) => boolean;
    }
    Index
    circuitBreaker?: false | CircuitBreakerOptions

    On by default; pass false to disable outage memory entirely.

    defaultChain?: string[]

    Fallback candidate chain; defaults to the service's registration order.

    onAttempt?: (
        attempt: {
            error?: PayFanoutError;
            ok: boolean;
            pspName: string;
            skipped?: boolean;
        },
    ) => void

    Observability: called once per failed/skipped candidate and once for the winner (error absent). Exceptions it throws are swallowed — routing always wins over observability, so never rely on this hook for control flow.

    onBreakerStateChange?: (
        event: { pspName: string; state: "opened" | "closed" },
    ) => void

    Observability: fired when a PSP's circuit opens (starts being skipped) or closes (a response proved it alive). A failed half-open probe restarts the cooldown without re-firing "opened" — the circuit never closed in between. Exception-isolated like onAttempt.

    rules?: RoutingRule[]

    First matching rule wins. No match -> defaultChain.

    shouldFailover?: (error: PayFanoutError) => boolean

    Decides whether a failed candidate cascades to the next one. Default: transient PSP-side trouble only (err.retryable, psp_unavailable, rate_limited, processing_error). Business rejections (invalid_request, card_declined, …) abort the cascade — retrying them elsewhere would produce surprise duplicate sessions for a request that is simply wrong. The circuit breaker counts exactly the failures this predicate cascades on, so a custom predicate also redefines what the breaker treats as transient (anything else closes the circuit as proof of life).