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

114 lines
4.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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`:
```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`:
```bash
# 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`.