Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
## Summary

<!-- What changed in plain language -->

-

## How to test (optional)

<!-- Add steps only if useful -->

-

## Related

<!-- Link issue(s) if any -->

- Closes #

> Thanks for contributing ❤️
201 changes: 20 additions & 181 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,65 +12,27 @@ This monorepo contains packages for synchronizing your Stripe account with a Pos

---

## Motivation

Sometimes you want to analyze your billing data using SQL. Even more importantly, you want to join your billing data to your product/business data.

This project synchronizes your Stripe account to a PostgreSQL database. It can be a new database, or an existing PostgreSQL database.

---

## Quick Start

The easiest way to sync Stripe data to PostgreSQL:
The easiest way to sync Stripe data to PostgreSQL is using the CLI. It will run a full historical backfill, and optionally stay alive to stream real-time events.

```typescript
import { StripeSync } from 'stripe-experiment-sync'
### CLI (Webhook Mode)

const sync = new StripeSync({
poolConfig: {
connectionString: process.env.DATABASE_URL,
max: 10,
},
stripeSecretKey: process.env.STRIPE_SECRET_KEY,
})

// Create a managed webhook - automatically syncs all Stripe events
const webhook = await sync.webhook.findOrCreateManagedWebhook('https://example.com/stripe-webhooks')

// Cleanup when done
await sync.close()
```bash
npx stripe-experiment-sync sync \
--stripe-key $STRIPE_API_KEY \
--database-url $DATABASE_URL \
--listen-mode webhook \
--ngrok-token $NGROK_AUTH_TOKEN
```

### Manual Webhook Processing
### CLI (Websocket Mode)

If you need to process webhooks in your own Express/Node.js app:

```typescript
import express from 'express'
import { StripeSync } from 'stripe-experiment-sync'

const app = express()
const sync = new StripeSync({
poolConfig: {
connectionString: process.env.DATABASE_URL,
max: 10,
},
stripeSecretKey: process.env.STRIPE_SECRET_KEY,
})

app.post('/stripe-webhooks', express.raw({ type: 'application/json' }), async (req, res) => {
const signature = req.headers['stripe-signature']

try {
await sync.webhook.processWebhook(req.body, signature)
res.status(200).send({ received: true })
} catch (error) {
res.status(400).send({ error: error.message })
}
})

app.listen(3000)
```bash
npx stripe-experiment-sync sync \
--stripe-key $STRIPE_API_KEY \
--database-url $DATABASE_URL \
--listen-mode websocket
```

### Supabase Edge Functions
Expand All @@ -84,24 +46,6 @@ npx stripe-experiment-sync supabase install \
--stripe-key $STRIPE_API_KEY
```

### CLI Commands

```bash
# Run database migrations
npx stripe-experiment-sync migrate --database-url $DATABASE_URL

# Start local sync with ngrok tunnel
npx stripe-experiment-sync start \
--stripe-key $STRIPE_API_KEY \
--ngrok-token $NGROK_AUTH_TOKEN \
--database-url $DATABASE_URL

# Backfill historical data
npx stripe-experiment-sync backfill customer \
--stripe-key $STRIPE_API_KEY \
--database-url $DATABASE_URL
```

---

## Configuration Options
Expand All @@ -127,9 +71,8 @@ npx stripe-experiment-sync backfill customer \
- Automatically runs database migrations to create the `stripe` schema with tables matching Stripe objects.
- Creates managed webhooks in Stripe for automatic event synchronization.
- Processes webhook events and syncs data to PostgreSQL in real-time.
- Supports backfilling historical data from Stripe.
- Supports syncing historical data from Stripe.
- Tracks sync runs and provides observability into sync operations.
- Built-in retry logic for rate limits and transient errors.

---

Expand All @@ -142,123 +85,19 @@ Each package has its own README with installation, configuration, and usage inst

---

## Supabase Edge Function Deployment

Deploy the sync engine to Supabase Edge Functions for serverless operation with automatic webhook processing. See the [sync-engine README](./packages/sync-engine/README.md#supabase-deployment) for detailed instructions.

```bash
npx stripe-experiment-sync supabase install \
--token $SUPABASE_ACCESS_TOKEN \
--project $SUPABASE_PROJECT_REF \
--stripe-key $STRIPE_API_KEY
```
## Webhook Support

---
For the full event matrix (supported, unsupported, and caveats), see [`docs/webhook-event-support.md`](./docs/webhook-event-support.md).

## Webhook Support
## Syncing Data

- [ ] `balance.available`
- [x] `charge.captured` 🟢
- [x] `charge.expired` 🟢
- [x] `charge.failed` 🟢
- [x] `charge.pending` 🟢
- [x] `charge.refunded` 🟢
- [x] `charge.refund.updated` 🟡 - For updates on all refunds, listen to `refund.updated` instead
- [x] `charge.succeeded` 🟢
- [x] `charge.updated` 🟢
- [x] `charge.dispute.closed` 🟢
- [x] `charge.dispute.created` 🟢
- [x] `charge.dispute.funds_reinstated` 🟢
- [x] `charge.dispute.funds_withdrawn` 🟢
- [x] `charge.dispute.updated` 🟢
- [x] `checkout.session.async_payment_failed` 🟢
- [x] `checkout.session.async_payment_succeeded` 🟢
- [x] `checkout.session.completed` 🟢
- [x] `credit_note.created` 🟢
- [x] `credit_note.updated` 🟢
- [x] `credit_note.voided` 🟢
- [x] `customer.created` 🟢
- [x] `customer.deleted` 🟢
- [ ] `customer.source.created`
- [ ] `customer.source.updated`
- [x] `customer.subscription.created` 🟢
- [x] `customer.subscription.deleted` 🟢
- [x] `customer.subscription.paused` 🟢
- [x] `customer.subscription.pending_update_applied` 🟢
- [x] `customer.subscription.pending_update_expired` 🟢
- [x] `customer.subscription.resumed` 🟢
- [x] `customer.subscription.trial_will_end` 🟢
- [x] `customer.subscription.updated` 🟢
- [x] `customer.tax_id.created` 🟢
- [x] `customer.tax_id.deleted` 🟢
- [x] `customer.tax_id.updated` 🟢
- [x] `customer.updated` 🟢
- [x] `invoice.created` 🟢
- [x] `invoice.deleted` 🟢
- [x] `invoice.finalized` 🟢
- [x] `invoice.finalization_failed` 🟢
- [x] `invoice.marked_uncollectible` 🟢
- [x] `invoice.paid` 🟢
- [x] `invoice.payment_action_required` 🟢
- [x] `invoice.payment_failed` 🟢
- [x] `invoice.payment_succeeded` 🟢
- [x] `invoice.sent` 🟢
- [x] `invoice.upcoming` — Acknowledged and skipped (preview object with no `id`)
- [x] `invoice.updated` 🟢
- [x] `invoice.overdue` 🟢
- [x] `invoice.overpaid` 🟢
- [x] `invoice.will_be_due` 🟢
- [x] `invoice.voided` 🟢
- [ ] `issuing_authorization.request`
- [ ] `issuing_card.created`
- [ ] `issuing_cardholder.created`
- [x] `payment_intent.amount_capturable_updated` 🟢
- [x] `payment_intent.canceled` 🟢
- [x] `payment_intent.created` 🟢
- [x] `payment_intent.partially_refunded` 🟢
- [x] `payment_intent.payment_failed` 🟢
- [x] `payment_intent.processing` 🟢
- [x] `payment_intent.requires_action` 🟢
- [x] `payment_intent.succeeded` 🟢
- [x] `payment_method.attached` 🟢
- [x] `payment_method.automatically_updated` 🟢
- [x] `payment_method.detached` 🟢
- [x] `payment_method.updated` 🟢
- [x] `plan.created` 🟢
- [x] `plan.deleted` 🟢
- [x] `plan.updated` 🟢
- [x] `price.created` 🟢
- [x] `price.deleted` 🟢
- [x] `price.updated` 🟢
- [x] `product.created` 🟢
- [x] `product.deleted` 🟢
- [x] `product.updated` 🟢
- [x] `radar.early_fraud_warning.created` 🟢
- [x] `radar.early_fraud_warning.updated` 🟢
- [x] `refund.created` 🟢
- [x] `refund.failed` 🟢
- [x] `refund.updated` 🟢
- [x] `review.opened` 🟢
- [x] `review.closed` 🟢
- [x] `setup_intent.canceled` 🟢
- [x] `setup_intent.created` 🟢
- [x] `setup_intent.requires_action` 🟢
- [x] `setup_intent.setup_failed` 🟢
- [x] `setup_intent.succeeded` 🟢
- [x] `subscription_schedule.aborted` 🟢
- [x] `subscription_schedule.canceled` 🟢
- [x] `subscription_schedule.completed` 🟢
- [x] `subscription_schedule.created` 🟢
- [x] `subscription_schedule.expiring` 🟢
- [x] `subscription_schedule.released` 🟢
- [x] `subscription_schedule.updated` 🟢
- [x] `entitlements.active_entitlement_summary.updated` 🟢
For the current supported Stripe object types, see [`packages/sync-engine/README.md#syncing-data`](./packages/sync-engine/README.md#syncing-data).

---

## Contributing

Issues and pull requests are welcome at [https://github.com/stripe-experiments/sync-engine](https://github.com/stripe-experiments/sync-engine).
Issues and pull requests are welcome at [`stripe-experiments/sync-engine`](https://github.com/stripe-experiments/sync-engine).

## License

Expand Down
34 changes: 13 additions & 21 deletions docs/contributing.md
Original file line number Diff line number Diff line change
@@ -1,35 +1,27 @@
# Contributing

Contributions are welcome! This document provides guidelines for contributing to the Stripe Sync Engine project.
Thanks for your interest in Stripe Sync Engine.

## Contributing to the Docs
This project is currently accepting code contributions only. Docs are maintained by project maintainers.

Building documentation requires Python 3.8+ and uv.
## Quick Workflow

### Install Dependencies
1. Fork the repo and create a branch.
2. Make your changes.
3. Run relevant checks locally.
4. Open a pull request with a clear description.

Create a virtual environment and install mkdocs, themes, and extensions using uv.
## Development Setup

```sh
source .venv/bin/activate # On Windows: .venv\Scripts\activate
uv pip install -r docs/requirements_docs.txt
```

### Serving

To serve the documentation locally, make sure your virtual environment is activated and run:
This repo uses `pnpm` workspaces.

```sh
source .venv/bin/activate # On Windows: .venv\Scripts\activate
mkdocs serve
pnpm install
```

and visit the docs at [http://127.0.0.1:8000/](http://127.0.0.1:8000/)

### Deploying

If you have write access to the repository, documentation can be updated using:
Common checks from the repo root:

```sh
mkdocs gh-deploy
pnpm lint
pnpm test
```
Loading