Files
2026-08-20 07:35:31 +01:00

4.3 KiB
Raw Permalink Blame History

Backend — when and how to add server-side logic

When you need a backend

You need a backend if your app needs to:

  • Store data long-term (user preferences, linked accounts, custom records)
  • Call APIs that require server-side secrets (API keys that can’t be in the browser)
  • Run logic when the user isn’t in the Dashboard (webhooks, scheduled jobs)
  • Call third-party services securely (email providers, CRMs, spreadsheet APIs)
  • Perform actions that take longer than the UI can wait for

You don’t need a backend if:

  • Your app only reads and displays Stripe data (use the SDK client directly in the UI)
  • You only need to store a small amount of sensitive data — use the Secret Store API instead

Canonical documentation

Before writing backend code, read these pages using WebFetch:

Topic URL
Backend implementation + fetchStripeSignature https://docs.stripe.com/stripe-apps/build-backend
Authentication types (determines backend pattern) https://docs.stripe.com/stripe-apps/api-authentication
Events and webhooks https://docs.stripe.com/stripe-apps/events
Secret Store API https://docs.stripe.com/stripe-apps/store-secrets

Backend architecture decisions

Authentication type determines the backend pattern

Your app’s stripe_api_access_type controls how the backend authenticates. See authentication.md for the full breakdown of auth types and when to use each one.

CORS configuration

CORS (Access-Control-Allow-Origin: *) is needed ONLY on endpoints called by the UI extension. The UI runs in a sandboxed iframe with a null origin — specific origin allowlisting will not work.

Webhook endpoints do NOT need CORS — they receive requests from Stripe’s servers, not from the browser.

fetchStripeSignature verification

fetchStripeSignature is how the UI extension authenticates requests to your backend. The signed payload and verification method are documented at https://docs.stripe.com/stripe-apps/build-backend.

Key facts:

  • The signing secret (starts with absec_...) is generated on first stripe apps upload
  • The default signed payload contains user_id and account_id (field order matters)
  • Extra data can be included by passing it to fetchStripeSignature(payload)
  • Verification uses stripe.webhooks.signature.verifyHeader()

Webhook configuration

Webhook setup depends on your app’s distribution and auth type:

App type Webhook setup
Private (your account only) ONE standard webhook endpoint
Public with platform keys ONE webhook with “Listen to events on Connected accounts” enabled
Public with restricted API keys Can’t use Connect webhook fanout — each merchant manages their own webhooks

The event_read permission MUST be declared in your manifest, plus read permissions for each event type you want to receive.

Read https://docs.stripe.com/stripe-apps/events for the full setup guide.

For firewall allowlisting of inbound webhook traffic, see https://docs.stripe.com/ips for Stripe’s IP addresses.

Secret Store API

Plain-language: “Stripe has a built-in secure place to store passwords, tokens, and API keys for your app — you don’t need to build your own database for secrets.”

Two scopes

Scope Use for Example
account Shared across all users of an account The business’s API key for an email service
user Per-user secrets An individual user’s OAuth access token

Limits and restrictions

  • Maximum 10 secrets per scope (account and user separately)
  • Always list and delete before adding more if approaching the limit
  • Do not store PCI-sensitive data (card numbers, CVVs, bank account numbers)

Declaring the permission

In stripe-app.yaml:

declarations:
  stripe_api_access:
    permissions:
      - permission: secret_write
        purpose: Store third-party credentials for the app

Implementation

For the correct code patterns to read, write, and delete secrets, read: https://docs.stripe.com/stripe-apps/store-secrets

Local development with a backend

Run your backend locally alongside stripe apps start:

# Terminal 1: start the app preview
stripe apps start

# Terminal 2: start your backend server
node server.js

For webhook forwarding during local development, see references/webhooks.md.