Configuration

Headcount can be configured via the control panel under Headcount → Settings, or by creating a config/headcount.php file. The config file always wins over CP settings, which makes per-environment configuration easy.

Config File

Create config/headcount.php to override settings per environment:

<?php

return [
    'stripeSecretKey' => getenv('STRIPE_SECRET_KEY'),
    'stripePublishableKey' => getenv('STRIPE_PUBLISHABLE_KEY'),
    'stripeWebhookSecret' => getenv('STRIPE_WEBHOOK_SECRET'),
    'paypalClientId' => getenv('PAYPAL_CLIENT_ID'),
    'paypalClientSecret' => getenv('PAYPAL_CLIENT_SECRET'),
    'paypalEnabled' => false,
    'defaultCurrency' => 'USD',
    'checkoutSuccessUrl' => '/membership/thank-you',
    'checkoutCancelUrl' => '/membership/plans',
    'loginUrl' => '/login',
    'pricingUrl' => '/membership/plans',

    // Wallet cards
    'walletEnabled' => true,
    'appleWalletEnabled' => true,
    'applePassTypeIdentifier' => getenv('APPLE_PASS_TYPE_ID'),
    'appleTeamIdentifier' => getenv('APPLE_TEAM_ID'),
    'appleCertificatePath' => getenv('APPLE_PASS_CERT_PATH'),
    'appleCertificatePassword' => getenv('APPLE_PASS_CERT_PASSWORD'),
    'appleWwdrCertificatePath' => getenv('APPLE_WWDR_CERT_PATH'),
    'googleWalletEnabled' => true,
    'googleWalletIssuerId' => getenv('GOOGLE_WALLET_ISSUER_ID'),
    'googleWalletServiceAccountPath' => getenv('GOOGLE_WALLET_KEY_PATH'),
];

Stripe

Headcount uses Stripe Checkout Sessions and the Stripe Customer Portal — cards never touch your server, so your site stays in PCI SAQ A scope.

SettingDescription
stripeSecretKeyStripe secret API key (server-side)
stripePublishableKeyStripe publishable key (client-side)
stripeWebhookSecretSigning secret for the Stripe webhook endpoint (whsec_…). Required — without it every Stripe webhook is refused, because none can be verified.

Stripe Webhook

Add a webhook endpoint in Stripe pointing to:

https://yoursite.com/actions/headcount/webhook/stripe

Subscribe to these events:

  • checkout.session.completed
  • customer.subscription.created
  • customer.subscription.updated
  • customer.subscription.deleted
  • invoice.paid
  • invoice.payment_failed
  • invoice.payment_action_required
  • customer.subscription.trial_will_end

PayPal (Optional)

To accept PayPal subscriptions, set paypalEnabled to true and provide your PayPal Business credentials.

SettingDescription
paypalEnabledEnable the PayPal gateway
paypalClientIdPayPal REST API client ID
paypalClientSecretPayPal REST API client secret
paypalWebhookIdThe ID PayPal gives your webhook. Required — without it every PayPal webhook is refused.

PayPal cannot be used for season memberships — its Subscriptions API only bills on a cycle, so checkout refuses a PayPal season purchase rather than signing the member up to something recurring.

PayPal Webhook

Add a webhook in your PayPal developer dashboard pointing to:

https://yoursite.com/actions/headcount/webhook/paypal

Then copy the Webhook ID PayPal shows for it into Headcount's PayPal settings. Headcount asks PayPal to verify every event against that ID, and refuses events when it isn't set.

URLs & Defaults

SettingDefaultDescription
defaultCurrencyUSDThree-letter ISO currency code
checkoutSuccessUrl/membership/thank-youWhere Stripe sends users after successful checkout
checkoutCancelUrl/membership/plansWhere Stripe sends users who cancel checkout
loginUrl/loginWhere unauthenticated visitors are redirected when access is required
pricingUrl/membership/plansWhere gated content sends visitors with the “Redirect” behavior

Wallet Cards

Apple Wallet and Google Wallet credentials live under Headcount → Settings → Wallet Cards. They are your own — an Apple Pass Type ID certificate and a Google Wallet issuer account — and every field accepts an environment variable. Keep the certificate and key files outside your web root. Full setup in the Wallet Cards guide.

SettingDescription
walletEnabledMaster switch for wallet cards
walletImagePathDirectory holding icon.png and friends. Apple rejects a pass with no icon
appleWalletEnabledIssue Apple Wallet passes
applePassTypeIdentifierYour Pass Type ID, e.g. pass.com.yourclub.membership
appleTeamIdentifierTen-character Apple Developer team ID
appleCertificatePathPath to the Pass Type ID certificate (.p12)
appleCertificatePasswordPassword the .p12 was exported with
appleWwdrCertificatePathPath to Apple’s WWDR intermediate certificate (.pem)
applePassUpdatesEnabledRun Apple’s pass web service so cards on a device update themselves. Needs HTTPS and curl with HTTP/2
googleWalletEnabledIssue Google Wallet passes
googleWalletIssuerIdNumeric issuer ID from the Google Pay & Wallet Console
googleWalletServiceAccountPathPath to the service account JSON key

Outgoing Webhooks

Set a webhook URL in Headcount → Settings to receive POST notifications for subscription lifecycle events. Payloads are signed with HMAC-SHA256 in the X-Headcount-Signature header.

Events emitted:

  • subscription.created
  • subscription.updated
  • subscription.canceled
  • subscription.expired
  • member.upgraded
  • member.downgraded

API Keys

Issue API keys from Headcount → Settings to authenticate REST API requests for non-session contexts (mobile apps, integrations). Pass the key in the X-Headcount-Api-Key header.

Every credential setting accepts an environment variable ($HEADCOUNT_API_KEY). A variable that doesn't resolve counts as unset — for the API key that means key access is off, and for the outgoing webhook secret it means nothing is sent — and the settings screen says so.

The ?apiKey= query parameter was removed in 5.2.0 — it leaked keys into web server logs, browser history, and the Referer header of outbound links. Any integration still using it must move to the header.

More in Site Features

Pairs well with Headcount

The bigger pieces a client asks for by name. Events, bookings, memberships, courses, reviews, a support desk, job listings and the rest.