Skip to main content

Configuration reference

Every key the package publishes, its environment variable and its shipped default. The tables follow the order of the published files, so you can read this beside your own config/billing.php.

billing:install publishes all three files; vendor:publish --tag=billing-config re-publishes them. A key you never touch keeps the default listed here — the package merges its own config underneath yours, so a published file missing a key is not an error.

A key with an environment variable can be set from .env or edited in the published file. A key without one is edited in the file, because its value is a structure rather than a scalar.

Set billing.customer.model. It is the one key with no useful default: without it no subscription webhook can resolve its owner. See Choosing your setup.

config/billing.php

Master switch and driver

KeyEnvDefaultWhat it does
billing.enabledBILLING_ENABLEDtrueThe master switch. Off, the manager resolves the no-op NullDriver, no account routes are registered and no billing surface exists — a clone without billing boots and schedules cleanly.
billing.defaultBILLING_DRIVERstripeThe payment driver used when none is named.
billing.stripe.api_versionBILLING_STRIPE_API_VERSIONnullThe dated Stripe API version every call and webhook runs against. Null uses the version the package pins and is tested against. Override it only deliberately: Stripe versions the shape of a webhook payload, so a newer version can silently change what a mapper reads.

Webhooks

KeyEnvDefaultWhat it does
billing.webhook_pathBILLING_WEBHOOK_PATHbilling/webhookThe path the provider posts to. The route carries no middleware group and no CSRF — the driver's verifier authenticates by signature instead.
billing.webhooks.connectionBILLING_WEBHOOK_QUEUE_CONNECTIONnullQueue connection for webhook effects. Null uses the default connection.
billing.webhooks.queueBILLING_WEBHOOK_QUEUEnullQueue name for webhook effects. Set it to keep billing work off the queue your app's other jobs share.
billing.webhooks.triesBILLING_WEBHOOK_TRIES5How often a failing effect is retried before the job is marked failed. It stays re-driveable after that — the raw payload is stored, so billing:webhooks:replay --failed can run it long after the provider stopped redelivering.

Each effect runs in its own queued job, so a slow or failing effect can neither hold the provider's request open nor take the other effects down with it. See Webhooks.

Checkout

KeyEnvDefaultWhat it does
billing.checkout.success_urlBILLING_CHECKOUT_SUCCESS_URLnullWhere a hosted checkout returns on success. Null uses the hub's checkout-return route, which reconciles the subscription onto the local row so a paying customer is never shown the free tier.
billing.checkout.cancel_urlBILLING_CHECKOUT_CANCEL_URLnullWhere an abandoned checkout returns. Null uses the plan screen.
billing.checkout.portal_return_urlBILLING_PORTAL_RETURN_URLnullWhere the hosted billing portal returns. Falls back to success_url, then the subscription screen.
billing.checkout.promotion_codesBILLING_CHECKOUT_PROMOTION_CODEStrueWhether the provider's promotion-code field is offered at checkout.

Owner model and seats

KeyEnvDefaultWhat it does
billing.ownerBILLING_OWNERuserWho owns billing: user (each user pays for themselves) or team (the user's team pays, for seats).
billing.team_relationteamWith a team owner, the relation on the acting user that returns the paying team. Ignored for a user owner.
billing.seats.membership_relationmembersThe relation on the team model that returns its members. HasSeats counts it.
billing.seats.active_status_columnnullColumn to filter the member count to active members. Null when the relation already returns only active ones — a pending invite is not a paid seat.
billing.seats.active_status_valueactiveThe value that column must hold to count.
billing.seats.membership_events[]Your join, leave and remove events. A queued listener is registered on each, so a membership change re-syncs the billed quantity. Empty means nothing fires until you opt in.
billing.seats.owner_properties['team', 'owner']For an event that does not implement AffectsSeats, the first of these properties holding the team model is read.

Customer and tier resolution

KeyEnvDefaultWhat it does
billing.customer.modelBILLING_CUSTOMER_MODELnullThe Eloquent model that owns a provider customer record. Set it before you take a real payment.
billing.customer.columnstripe_idThe column holding the provider's customer reference.
billing.zero_tierBILLING_ZERO_TIERfreeThe fail-safe no-entitlement tier every resolver falls back to.
billing.tier_columnplanThe raw column ColumnTierResolver reads — never an accessor.
billing.untouchable_tiers[]Tier keys the plan-sync webhook effect never flips, in either direction. Use it for an admin-comped grant a provider event must not overwrite.

Tiers, add-ons and coupons

KeyEnvDefaultWhat it does
billing.tiersone free tierThe tier catalog, keyed by tier key; the order is the upgrade ranking. Per tier: label, an optional provider_price (an id, or a per-driver map), price_display, interval, legacy_prices, metered components, trial, and the presentation-only features, highlight and badge. A tier with no price_display is not purchasable. The client submits a tier key, never a price.
billing.addons[]One-time purchasable add-ons, keyed by add-on key: label, provider_price, price_display, and an optional grants (meter plus units). An add-on grants either money credit or prepaid usage units.
billing.coupons[]Package-owned discount codes keyed by the code the customer enters: either percent (1 to 100) or amount plus currency, with an optional expires_at. Add stripe_coupon to have the provider own the money math at checkout.
billing.currencyBILLING_CURRENCYEURUsed where an amount carries no explicit currency, such as a zero dunning fee.

The shape of a tier is worked through in Tiers and pricing; add-ons and prepaid units in Usage-based billing.

Usage and metering

KeyEnvDefaultWhat it does
billing.dimensions[]Extra dimensions a custom UsageProvider reports: label, unit, period, warn_threshold. The default provider ignores this — it derives its dimensions from each tier's metered components, so an owner sees exactly what they are billed for.
billing.metering.max_attempts8A deadline, not a limit: past it the usage is marked failed and logged as an error, because it is revenue that will not be collected unless someone acts. Do not raise it to hide a persistent failure.
billing.metering.backoff_seconds60Base delay for the exponential backoff between flush attempts.
billing.metering.stall_hours6How long usage may sit unreported before billing:usage:reconcile calls it a stall rather than a passing outage. Keep it under your provider's back-dated acceptance window.
billing.usage.hold_secondsBILLING_USAGE_HOLD_SECONDS900How long a hold on a metered allowance stands before it is handed back. Longer than your slowest metered request, shorter than you would tolerate an owner being short of allowance they never spent.
billing.quota.status429The HTTP status the billing.quota:<meter> middleware aborts a blocked request with. Only a blocking meter is gated; a degrade or fair-use meter never is.

Dunning, suspension and notifications

KeyEnvDefaultWhat it does
billing.dunningthree rungs, at 3, 7 and 14 daysThe ladder, in order. Each rung: after_days, an optional fee (amount plus currency), an optional label. billing:dunning:advance sends each rung's warning once and charges its fee if one is set. The delinquency clock is a timestamp, never a gateway status.
billing.dunning_status402The status a non-browser request from a delinquent owner gets. A browser request is redirected to the recovery screen instead.
billing.suspension[]Per-surface lockout thresholds keyed by surface name; the value is the dunning level at which that surface locks. A surface with no threshold never locks.
billing.cards.warn_within_days30How far ahead billing:cards:warn nudges an owner whose default card is expiring — the biggest preventable cause of involuntary churn.
billing.notifications.channels['mail']The transport only, never whether the customer is told: billing notices are transactional and non-suppressible. Add database for an in-app feed. An unusable value falls back to mail rather than sending nothing.

Account hub, admin and runtime

KeyEnvDefaultWhat it does
billing.navigationthe full hubThe hub's sections, keyed by item key: label (an i18n key or a literal), route, and the optional group, icon, order and web_only. Malformed items are dropped. Remove an entry and the section is gone.
billing.runtimeBILLING_RUNTIMEwebweb or native. On native, items flagged web_only are hidden — for flows an app store forbids from being completed in-app.
billing.link_outBILLING_LINK_OUTnullThe external billing portal to link out to when an external merchant of record owns billing. Scheme-restricted: anything but an absolute http or https URL with a host is ignored.
billing.realtime.enabledBILLING_REALTIMEfalseOpt-in live refresh for the hub. Events broadcast only when this is on and a broadcaster is configured; otherwise the screens fall back to a bounded poll.
billing.admin.abilityBILLING_ADMIN_ABILITYbilling-adminThe Gate ability every admin-console access is authorized against. Your app defines it; until you do, the Gate denies everyone.
billing.admin.prefixBILLING_ADMIN_PREFIXadmin/billingThe URL prefix the admin console mounts under.
billing.admin.middleware['web', 'auth']The middleware stack the admin console runs through.
billing.subscriptions.downgrade_timingBILLING_DOWNGRADE_TIMINGperiod_endWhen a downgrade lands. An upgrade is always immediate. period_end avoids owing a refund or taking away paid-for access mid-cycle; immediate downgrades at once. The screen and the swap read this one value, so they cannot disagree.

Trials

KeyEnvDefaultWhat it does
billing.trial.daysBILLING_TRIAL_DAYS0Trial length in days; 0 disables trials. Per-tier override: tiers.<key>.trial.days.
billing.trial.modeBILLING_TRIAL_MODEnullnone, subscription (collected at checkout) or generic (no subscription, granted by Trials::grant()). Null derives it: a configured generic_tier implies generic, otherwise a positive length implies subscription.
billing.trial.generic_tierBILLING_TRIAL_GENERIC_TIERnullThe tier a generic trial unlocks. Null disables generic trials — without a tier to unlock there is nothing to grant.
billing.trial.requires_payment_methodBILLING_TRIAL_REQUIRES_PMtrueWhether a subscription trial collects a card up front.
billing.trial.ending_within_days3How many days before a trial ends the app-shell banner starts nudging.

Tax and the invoice seller

KeyEnvDefaultWhat it does
billing.taxBILLING_TAXnoneprovider (defer to a provider that supports it), eu_oss (the bundled static EU-OSS VAT table) or none. A driver-capability decision, not a checkout option.
billing.tax_profileBILLING_TAX_PROFILEnullWhich country's obligations the package enforces where it can — today, the points a jurisdiction adds to the marketplace go-live checklist. Null means none, and the checklist says so rather than reading as an all-clear. Shipped: de. A jurisdiction the package does not ship is supplied by binding your own JurisdictionProfile, which wins over this name; a name that is neither shipped nor bound is refused at boot.
billing.tax_small_businessthe keys belowThresholds a jurisdiction profile with a small-business rule reads. Inert without such a profile.
billing.tax_small_business.warning_levels[0.80, 0.95]How close to a threshold triggers a forced re-declaration. The percentages are configurable; the basis they are computed on is not — the same percentages against a different basis fire at a completely different moment, which would look like a configuration choice and behave like a different rule.
billing.tax_small_business.eu_revalidate_after_daysBILLING_TAX_EU_REVALIDATE_AFTER_DAYS365How long a confirmed small-business registration stands before it is checked again. A registration confirmed once is not confirmed forever — registers change, and a standing resting on a two-year-old lookup rests on nothing. Once it lapses the merchant is held exactly as if nobody had ever checked.
billing.tax_small_business.reattestation.on_year_changeBILLING_TAX_REATTEST_ON_YEAR_CHANGEtrueWhether a declaration expires at the year boundary. It has to: the threshold is a statement about a year that has not ended, so a declaration made in March says nothing about the following January — and the platform cannot answer for the merchant, because it only sees what was sold here.
billing.tax_small_business.reattestation.grace_daysBILLING_TAX_REATTEST_GRACE_DAYS30How long somebody has to answer an obligation that arrives on the first day of the year. Added to the boundary, never replacing it.
billing.tax_small_business.previous_year_limitBILLING_TAX_SB_PREVIOUS_YEAR_LIMIT2500000Prior-year turnover ceiling, in minor units (the German §19 figure: €25,000). A count over it last year removes the exemption for the whole of this year, effective January 1.
billing.tax_small_business.current_year_limitBILLING_TAX_SB_CURRENT_YEAR_LIMIT10000000Running-year turnover ceiling, in minor units (€100,000). The transaction that breaks it ends the exemption from that transaction's own moment — not the day's start, not the year's.
billing.tax_small_business.founding_year_limitBILLING_TAX_SB_FOUNDING_YEAR_LIMIT2500000Turnover ceiling that applies in the founding year, in minor units (€25,000). A business in its first year has no prior year, so the current-year limit is replaced by this immediate one.
billing.tax_small_business.auto_flip_enabledBILLING_TAX_SB_AUTO_FLIPtrueWhether a broken limit automatically flips the creator from small-business to standard rating. The flip is one-directional by design — a count under the limit never flips back, because the platform sees only a lower bound of the real turnover. Turning this off leaves the flip to an operator.
billing.company.nameBILLING_COMPANY_NAMEnullThe seller party on an e-invoice.
billing.company.vat_idBILLING_COMPANY_VAT_IDnullYour VAT identification number. Also the last fallback for the electronic address below.
billing.company.addressBILLING_COMPANY_ADDRESSnullStreet address of the seller party.
billing.company.postcodeBILLING_COMPANY_POSTCODEnullPostal code of the seller party.
billing.company.cityBILLING_COMPANY_CITYnullCity of the seller party.
billing.company.countryBILLING_COMPANY_COUNTRYDETwo-letter country code of the seller party.
billing.company.endpoint_idBILLING_COMPANY_ENDPOINT_IDnullThe seller electronic address (EN 16931 BT-34). XRechnung makes it mandatory, so an endpoint must always resolve: set it, or the renderer falls back to a company email, then to vat_id.
billing.company.endpoint_schemeBILLING_COMPANY_ENDPOINT_SCHEMEEMThe scheme code for that address (EM is email).

Tax and the invoice surface: Taxes · Invoices and e-invoicing.

Data protection and retention

KeyEnvDefaultWhat it does
billing.audit.levelBILLING_AUDIT_LEVELmoneymoney records every money movement and entitlement or state change — the events an auditor, or a "why is this customer on free?" question, needs. all adds the high-volume navigational and read-side events.
billing.erasure.forget_customerBILLING_ERASURE_FORGET_CUSTOMERfalseWhether billing:erase also deletes the customer at the provider. Irreversible, and it cancels their live subscriptions there — off by default.
billing.retention.webhook_payload_daysBILLING_RETENTION_WEBHOOK_PAYLOAD_DAYS90How long a stored webhook payload is kept. Long past the provider's own redelivery window, which is the only reason it is kept at all.
billing.retention.erased_financial_daysBILLING_RETENTION_ERASED_FINANCIAL_DAYS2920The invoice window for an erased owner's retained invoices: eight years, counted from the end of the year of issue. A shorter value refuses to boot. A floor and a default — set your own for another jurisdiction.
billing.retention.audit_daysBILLING_RETENTION_AUDIT_DAYS3650The book window for the audit ledger: ten years. Deliberately longer than the invoice window above — two record classes, not a value that drifted. Do not unify them.
billing.retention.allow_below_statutory_minimumBILLING_RETENTION_ALLOW_BELOW_STATUTORY_MINIMUMfalseThe escape hatch for a jurisdiction whose invoice minimum genuinely is shorter than the floor above. Left false, a shorter erased_financial_days refuses to boot rather than prune tax records early.

Erasure keeps invoices on purpose: a valid invoice has to carry the buyer's name and address and has to be kept for years, so the right to erasure yields to the retention obligation. Those rows are unlinked from the owner and removed by billing:prune once the window closes. See Data protection and Retention and erasure.

DATEV export

KeyEnvDefaultWhat it does
billing.datev.consultantBILLING_DATEV_CONSULTANTnullThe consultant number in the EXTF header.
billing.datev.clientBILLING_DATEV_CLIENTnullThe client number in the EXTF header.
billing.datev.account_lengthBILLING_DATEV_ACCOUNT_LENGTH4The account-number length your chart uses.
billing.datev.revenue_accountBILLING_DATEV_REVENUE_ACCOUNTnullThe revenue account every invoice books against when no chart is selected. Left empty, the export still produces a structurally valid file with blank account fields.
billing.datev.customer_accountBILLING_DATEV_CUSTOMER_ACCOUNTnullThe receivables account every invoice books to when no chart is selected.
billing.datev.chartBILLING_DATEV_CHARTnullskr03, skr04 or null. Null uses the two accounts above and the export is byte-identical. Selecting a chart changes only the values resolved per transaction, never the file's structure or field order.
billing.datev.accountsan SKR03 and an SKR04 mapThe per-transaction account map for each chart. Each entry is account plus automatic; an automatic account derives its VAT from the posting itself, so a tax key is never set alongside it. The numbers are German-accountant defaults, not values the package invents — override them for a different frame without a code change.

These are specific to your chart of accounts and your tax advisor's setup. Confirm them before importing. See Accounting and DATEV.

Multi-merchant keys

The package ships the single-merchant path. These keys exist because two guarantees have to be enforceable before a routed sale could ever exist, and both are enforced today: a posture cannot be resolved outside the list you opted into, and the platform cannot start holding other people's money by flipping a flag.

KeyEnvDefaultWhat it does
billing.marketplace.enabledBILLING_MARKETPLACE_ENABLEDfalseOff, the custody guard below has nothing to check and single-merchant behavior is byte-identical.
billing.marketplace.custody.platform_heldBILLING_MARKETPLACE_PLATFORM_HELDfalseWhether the platform itself would hold other people's funds. Holding funds is a regulated activity in most jurisdictions, so this is refused at boot unless the host binds a PaymentServiceLicenseAttestation. A flag alone can never make an unaware consumer an unlicensed money holder. There is deliberately no interest or yield option.
billing.marketplace.seller_of_record.default_postureBILLING_MARKETPLACE_POSTUREplatform_deemed_supplierWho the seller is to the buyer. A liability and VAT decision the package enforces but never makes for you.
billing.marketplace.seller_of_record.allowed_postures['platform_deemed_supplier']The postures you have deliberately opted into. Resolving one outside this list is refused.
billing.marketplace.seller_of_record.supplies_are_electronicBILLING_MARKETPLACE_SUPPLIES_ELECTRONICtrueDefault classification of what is sold. An electronically supplied service falls under the deemed-supplier presumption; physical goods do not.
billing.marketplace.seller_of_record.art9a_rebuttal_assertedBILLING_MARKETPLACE_ART9A_REBUTTALfalseThe rebuttal assertion. It and the three keys below must all be true before a seller-of-record posture is allowed for an electronic supply.
billing.marketplace.seller_of_record.no_agb_controlfalseAssert that you do not set the terms of the supply.
billing.marketplace.seller_of_record.no_billing_authorizationfalseAssert that you do not authorize the charge to the buyer.
billing.marketplace.seller_of_record.no_supply_authorizationfalseAssert that you do not authorize the delivery of the supply.
billing.marketplace.seller_activitythe two keys belowWhen a seller is active enough to be asked to declare their standing.
billing.marketplace.seller_activity.sales_thresholdBILLING_MARKETPLACE_SALES_THRESHOLD30Sales in the period that count as trading.
billing.marketplace.seller_activity.proceeds_threshold_minorBILLING_MARKETPLACE_PROCEEDS_THRESHOLD_MINOR200000Proceeds in the period that count as trading, in minor units. Two thresholds read these numbers and they are not the same rule: the declaration is asked for once EITHER measure is reached, the reporting exemption holds only while BOTH stay under and its money comparison is inclusive. At exactly the figure they disagree, deliberately — the exemption's boundary is set by law, and moving it to match a preference over-reports.
billing.marketplace.seller_data_escalationthe keys belowWhat happens when a seller does not supply the data a reporting duty needs.
billing.marketplace.seller_data_escalation.first_reminder_after_daysBILLING_MARKETPLACE_FIRST_REMINDER_DAYS7Days incomplete before the first reminder.
billing.marketplace.seller_data_escalation.second_reminder_after_daysBILLING_MARKETPLACE_SECOND_REMINDER_DAYS30Days before the second.
billing.marketplace.seller_data_escalation.measure_after_daysBILLING_MARKETPLACE_MEASURE_AFTER_DAYS60Days before a measure applies — and only where the missing data is legally required of that seller.
billing.marketplace.seller_data_escalation.measureBILLING_MARKETPLACE_DATA_MEASUREwithhold_payoutsuspend_sales or withhold_payout. Two very different impositions, and neither is obviously the gentler one: stopping somebody selling ends their income, holding their money leaves them selling and unpaid.
billing.marketplace.seller_data_escalation.measure_precautionary_gapsBILLING_MARKETPLACE_MEASURE_PRECAUTIONARYfalseWhether a measure also applies where only precautionary data is missing. Off, because extending a sanction to data no law requires is a contract question between a platform and its sellers.
billing.marketplace.seller_data_escalation.withhold_up_to_daysBILLING_MARKETPLACE_WITHHOLD_UP_TO_DAYS90How long a withholding may last.
billing.marketplace.seller_data_escalation.payout_deadline_daysBILLING_MARKETPLACE_PAYOUT_DEADLINE_DAYS90The money rail's own deadline, read here and defined by the payout schedule. A withholding is capped by it: "held until they cooperate" is open-ended and the rail is not, and a hold that outran it would not be stricter — it would be a payment nobody can complete.
billing.marketplace.seller_recordthe key belowWhat a platform asks a seller for at onboarding.
billing.marketplace.seller_record.collect_precautionaryBILLING_MARKETPLACE_COLLECT_PRECAUTIONARYtrueCollect the fields a reporting duty adds from EVERY seller, not only those the duty currently covers. A seller's classification changes the day they take on different work, and a platform that only asked the sellers it already knew about then has to chase the rest — after the year closed, under a deadline, from people who have gone quiet. Switch it off and those fields are asked for only once a duty applies; the fields needed to settle at all are never affected either way.
billing.marketplace.tax_status_holdthe two keys belowWhat happens while a merchant's tax standing is unestablished.
billing.marketplace.tax_status_hold.blocks_payoutsBILLING_MARKETPLACE_HOLD_BLOCKS_PAYOUTStrueHold the merchant's own earnings until their standing is recorded. Inert under a jurisdiction profile that requires the hold: turning it off there would amount to choosing a default standing for people whose standing nobody knows.
billing.marketplace.tax_status_hold.blocks_salesBILLING_MARKETPLACE_HOLD_BLOCKS_SALEStrueStop selling on their behalf too. Holding only the payout is the more dangerous half-fix: buyers' money keeps arriving and each transaction creates an obligation to settle that cannot be settled — a growing backlog instead of a stop. Equally inert under such a profile.
billing.marketplace.regimethe two keys belowWhich shape a routed sale has. The platform reselling in its own name, or the platform arranging somebody else's sale — they produce different documents, different turnover, and different parties on a receipt.
billing.marketplace.regime.defaultBILLING_MARKETPLACE_REGIMEcommission_chainThe shape a sale has when what is sold does not decide for itself. commission_chain or intermediation. An unreadable or unknown value is refused rather than defaulted: silently choosing here would pick which documents every sale produces, on the strength of a typo.
billing.marketplace.regime.allowed['commission_chain']The regimes you have deliberately opted into. Resolving one outside this list is refused — a platform that has not said it arranges other people's sales must not begin to because a product was classified in a way nobody looked at.
billing.marketplace.numberingthe key belowPrefixes for the document series the platform numbers itself.
billing.marketplace.numbering.seriesthe eight keys belowOne visible prefix per document role. The number format is PREFIX-YYYY-####### — the prefix, the four-digit year, and a seven-digit running number that restarts at 1 each year within the series. A role with no configured prefix is refused at allocation rather than numbered with a blank, because a malformed number issued is itself a numbered event that would then need a correction. These are the German defaults; a consumer elsewhere maps the same roles to their own letters.
billing.marketplace.numbering.series.buyer_receiptFPrefix for the buyer's receipt.
billing.marketplace.numbering.series.self_billed_invoiceGPrefix for a self-billed invoice to a merchant.
billing.marketplace.numbering.series.settlement_noteAPrefix for a settlement note to a private party.
billing.marketplace.numbering.series.commission_invoicePPrefix for a commission invoice — drawn only in an intermediation sale, never in a commission chain.
billing.marketplace.numbering.series.buyer_receipt_correctionKFPrefix for a correction to a buyer receipt.
billing.marketplace.numbering.series.self_billed_invoice_correctionKGPrefix for a correction to a self-billed invoice.
billing.marketplace.numbering.series.settlement_note_correctionKAPrefix for a correction to a settlement note.
billing.marketplace.numbering.series.commission_invoice_correctionKPPrefix for a correction to a commission invoice.
billing.marketplace.self_billingthe keys belowWhether the platform may settle a creator by self-billing, and on what precondition.
billing.marketplace.self_billing.enabledBILLING_MARKETPLACE_SELF_BILLING_ENABLEDtrueWhether the platform settles creators by self-billing at all. On by default. A consumer that does not self-bill turns this off and stays in the fallback lane — the creator submits their own invoice. It is a backstop, not the routing decision: check it before settling, and the engine refuses loudly if it is reached while off rather than issue a document a disabled platform never meant to.
billing.marketplace.self_billing.require_agreementBILLING_MARKETPLACE_SELF_BILLING_AGREEMENTtrueWhether a self-billed document requires a prior agreement with the creator. On by default; it opts out only explicitly. A self-billed document is an invoice only if both sides agreed to the arrangement before it — one issued without that agreement is not an invoice and cannot be repaired. A jurisdiction that does not demand the agreement turns this off, but a missing or non-boolean value keeps the requirement, because the fail-safe is to require it. The clause text and the onboarding screen belong to you; the package ships only the record and the guard.
billing.marketplace.fee.roundingBILLING_MARKETPLACE_FEE_ROUNDINGplatform_firstWhich side of an uneven percentage split keeps the leftover minor unit. platform_first gives it to the fee; creator_first gives it to the net, the only order that hits an exact target payout. At volume that assignment is real money, so it is a documented contract choice rather than an accident of rounding.
billing.consumer_rightsthe two keys belowThe buyer's statutory withdrawal rights. This is consumer law, not tax law, and deliberately its OWN profile — a single seller needs it too, and an operator may run one country's VAT and another's consumer regime.
billing.consumer_rights.profileBILLING_CONSUMER_RIGHTS_PROFILEnullWhich consumer-rights reading is in force. Null means off: no extra checkout step, no changed receipt, byte-identical. Set it and the gate is fail-closed — a digital work whose withdrawal right extinguishes on delivery is not provided until the buyer's double consent is recorded, because providing it first forfeits their refund right on their behalf.
billing.consumer_rights.window_daysBILLING_CONSUMER_RIGHTS_WINDOW_DAYS14How many days a withdrawal remains a right rather than a courtesy.
billing.tax_evidencethe key belowHow the buyer's country is established from the signals available while the sale happens.
billing.tax_evidence.required_signalsBILLING_TAX_EVIDENCE_SIGNALS2How many sources must name a country before a sale can rest on them. The legal answer depends on turnover — one piece of evidence below a threshold, two non-contradicting ones above it — so the package ships the stricter setting: too much evidence costs a checkout question, too little costs a defensible position. A value that cannot be read is refused rather than defaulted, because silently becoming 1 would relax the standard.
billing.tax_marketsnullThe countries you are registered in and may sell into, as ISO code → open | planned | blocked. Absent means no gate at all — a check defaulting to closed would stop every existing install at its next sale, which is an outage rather than a guard. Once configured it is fail-closed: anything not explicitly open is refused, including a country the evidence could not resolve. Refused BEFORE the payment, because a sale into a country with no registration cannot be repaired by any later document. A market opened here that the local rates cannot price refuses the boot. A SIBLING of billing.tax, never a child — nesting under that scalar would turn it into an array and silently produce 0% tax on every invoice.
billing.marketplace.pricingthe key belowHow a price behaves across markets with different tax rates.
billing.marketplace.pricing.modeBILLING_MARKETPLACE_PRICING_MODEuniform_grossWhich quantity stays fixed when the rate changes — something has to move. uniform_gross keeps one buyer price everywhere and lets the payout absorb the difference; uniform_payout keeps the payout predictable and moves the price. A creator names their target PAYOUT rather than the buyer's price, which is what makes a change in their own tax standing visible instead of leaving the price fixed while the payout moves underneath them. Note that under the default rounding order a target that does not divide evenly is paid one cent short — 50.00 at 15% is paid as 49.99 — so show the resulting payout rather than repeating the request back.
billing.marketplace.tipsthe two keys belowTips and pay-what-you-want, run through the ordinary sale pipeline rather than a donation side path. A tip is consideration for the creator's supply and carries the same regime, commission and document chain.
billing.marketplace.tips.enabledBILLING_MARKETPLACE_TIPSfalseWhether tipping is on at all.
billing.marketplace.tips.commission_bpsBILLING_MARKETPLACE_TIPS_COMMISSION_BPSnullA tip-specific commission rate in basis points. Null means a tip takes the platform's ordinary commission.
billing.marketplace.pwywthe key belowPay-what-you-want pricing, where the fan chooses the price.
billing.marketplace.pwyw.minimum_minorBILLING_MARKETPLACE_PWYW_MINIMUM_MINOR0The floor a chosen price may not fall below, in minor units. Enforced on the SERVER — a buyer-chosen price is the one place the package's anti-injection stance would otherwise lapse. A chosen amount of zero is refused as no sale regardless of this floor.
billing.marketplace.buyer_feethe keys belowA fee charged to the BUYER on a C2C sale — a separate supply from the seller-side commission, and the platform's own first supply in the intermediary posture. Off by default. Its place of supply is where the mediated sale happens, not where the buyer banks, and it is quoted gross. Kept on its own revenue account, because netting it into the item price or the seller's turnover would make a taxable supply of the platform's own disappear.
billing.marketplace.buyer_fee.enabledBILLING_MARKETPLACE_BUYER_FEEfalseWhether a buyer fee is charged at all.
billing.marketplace.buyer_fee.modelBILLING_MARKETPLACE_BUYER_FEE_MODELpercentpercent (a share of the sale) or fixed (a flat amount, charged on top of the item price rather than out of it).
billing.marketplace.buyer_fee.bpsBILLING_MARKETPLACE_BUYER_FEE_BPS0The percentage rate in basis points, for the percent model.
billing.marketplace.buyer_fee.fixed_minorBILLING_MARKETPLACE_BUYER_FEE_FIXED_MINOR0The flat gross amount in minor units, for the fixed model.
billing.marketplace.buyer_fee.revenue_accountBILLING_MARKETPLACE_BUYER_FEE_ACCOUNT8510The revenue account the fee is booked to. The number is config; that it is SEPARATE from the item and the seller's turnover is structural.
billing.marketplace.charge_type_by_posturethe two keys belowWhich money routing is compatible with which declared seller. The charge type decides who the PROVIDER treats as the merchant of record; the posture decides who the DOCUMENTS name as the seller. Neither determines the other — for electronic services the seller is assigned by law regardless of how the money flows — and because they are independent they can be set to disagree. A pair that disagrees raises no error: it produces a receipt and a settlement describing different transactions, found in an audit. A missing or misshapen table permits NOTHING rather than everything, so a typo cannot open the combination the check exists to close.
billing.marketplace.charge_type_by_posture.destination['seller_of_record', 'platform_intermediary']Postures a destination charge may be used with. It makes the connected account the merchant of record, so it fits a sale the merchant is the seller of.
billing.marketplace.charge_type_by_posture.separate_transfer['platform_deemed_supplier', 'platform_intermediary']Postures a separate transfer may be used with. The platform takes the whole payment and carries the dispute, which is what a platform that is the deemed supplier must do whatever it would prefer.
billing.marketplace.fee.default_bpsBILLING_MARKETPLACE_FEE_BPS0What the platform keeps, in basis points — 250 is 2.5%. Zero is the neutral position, deliberately: shipping a take rate would be choosing your commercial terms for you. A value that cannot be read as an integer is refused rather than cast, because the cast of a broken rate is 0, and a zero commission is indistinguishable from a platform that deliberately takes nothing.
billing.marketplace.fee.default_flat_minorBILLING_MARKETPLACE_FEE_FLAT_MINOR0A fixed amount kept per transaction, in minor units. Supported alongside the rate because the provider's own pricing has the same shape, and a marketplace that could express only one would have to approximate the other. Taken first; the rate then applies to what remains.
billing.marketplace.fee.processing_fee.borne_byBILLING_MARKETPLACE_PROCESSING_FEE_BORNE_BYmerchantWho economically carries the payment provider's OWN fee — separate from your commission. merchant follows the market: they carry it as they would selling anywhere else. platform records that you absorb it. The package only records which side carries it; the provider bills you directly and the package never invoices it.
billing.marketplace.webhookthe two keys belowThe endpoint provider events about a MERCHANT arrive on. It is separate from the platform endpoint, with a separate secret.
billing.marketplace.webhook.pathBILLING_MARKETPLACE_WEBHOOK_PATHbilling/webhook/marketplaceWhere merchant events are received.
billing.marketplace.webhook.secretBILLING_MARKETPLACE_WEBHOOK_SECRETnullThe signing secret for that endpoint. Required in production once the marketplace is on — the app refuses to boot without it, because a marketplace whose merchant events all fail verification reports no error at all: the capability flags simply never move, and a merchant who lost their payout capability keeps being paid. Never reuse the platform secret: a verifier accepting either would let the merchant key authenticate platform events, and those move the platform's own money.
billing.marketplace.onboardingthe key belowGiving a merchant an account at the provider and driving its hosted identity flow.
billing.marketplace.onboarding.account_typeBILLING_MARKETPLACE_ACCOUNT_TYPEexpressWhich kind of provider account a merchant gets. express leaves onboarding, identity and the merchant dashboard with the provider; standard gives the merchant a full account and a direct relationship with the provider. It decides who runs the identity checks and who absorbs a loss, and a provider will not change it once a merchant has onboarded — so an unsupported value is refused at boot.
billing.marketplace.preflightthe two keys belowThe go-live checklist that gates enabled. php artisan billing:marketplace:preflight prints it; with the marketplace on, an open blocking point refuses the boot and names itself.
billing.marketplace.preflight.attestations[]Points nobody can check from here — terms published, a registration filed — recorded as your own statement, keyed by checkpoint key: version, attested_at (YYYY-MM-DD, mandatory) and an optional reference. The version is the expiry: when a release changes what has to be attested, the recorded version stops matching and the point goes red until somebody re-reads and re-attests.
billing.marketplace.preflight.waived[]Blocking points you deliberately proceed without, by checkpoint key. A waived point is still evaluated and still prints why it did not hold; it is demoted to a warning, never to a pass. Structural points cannot be waived, and an entry naming one is reported as a failure rather than ignored.

A platform that sets its own terms, authorizes billing or approves the supply cannot truthfully assert the three no_* keys. Leave them false.

config/account.php

KeyEnvDefaultWhat it does
account.prefixBILLING_ACCOUNT_PREFIXaccount/billingThe URL prefix the hub mounts under. The whole hub is gated on billing.enabled.
account.middleware['web', 'auth']The middleware stack the hub routes run through. The hub shows a signed-in owner their own billing.
account.layoutBILLING_ACCOUNT_LAYOUTbilling::layouts.accountThe Blade layout the full-page screens extend. Point it at your own layout to frame the hub in your chrome.
account.csp.enabledBILLING_ACCOUNT_CSPtrueThe scoped Content-Security-Policy, so the driver's payment element loads on the billing screens only. Turn it off only if your app already sends its own CSP for these routes — browsers enforce every CSP header at once.
account.csp.additional[]Extra origins to allow, keyed by directive (for example 'font-src' => ['https://fonts.example']). Whitelist here rather than turning the header off.
account.stylesheetBILLING_ACCOUNT_STYLESHEETnullA compiled stylesheet for the standalone layout. Unused in the recommended setup, where account.layout points at your own layout and the package's views are added to your Tailwind source scan.

config/license.php

KeyEnvDefaultWhat it does
license.tiers[]What each tier unlocks, keyed by tier key: features (boolean grants) and limits (numeric ceilings, where null means uncapped). A tier, feature or limit that is not listed is denied or uncapped by the safe defaults — never an error.

This file is licensing, billing.php is pricing, and they are orthogonal on purpose. Billing code never reads license.* — an architecture test enforces it — and the single bridge is the License contract. Neither ever blocks a public or marketing surface.


← Back to the documentation index