GUARDLABS
GuardLabs ยท Technical note

How to Connect Stripe Webhooks to Google Sheets Using Python

This guide shows you how to capture Stripe events (such as payment_intent.succeeded) and automatically log them to a Google Sheet using Python, Flask, and the Google Sheets API. This setup uses Stripe's official SDK to verify webhook signatures, ensuring your endpoint remains secure.

1. Set Up Google Sheets API Access

Before writing Python code, you must enable API access to your Google Sheet:

  • Go to the Google Cloud Console and create a new project.
  • Enable the Google Drive API and Google Sheets API.
  • Go to Credentials, click Create Credentials, and select Service Account.
  • Generate a new JSON key for the service account and download it. Rename this file to credentials.json and place it in your project directory.
  • Open your Google Sheet, click Share, and invite the service account email address (found in your JSON file) as an Editor.

2. Install Required Python Packages

Install the necessary libraries for handling webhooks, validating Stripe signatures, and interacting with Google Sheets:

pip install Flask stripe gspread google-auth

3. Write the Python Webhook Listener

Create a file named app.py. This script runs a local Flask server, listens for POST requests from Stripe, verifies the webhook signature, and appends the payload data to your Google Sheet.

import os
import json
from flask import Flask, request, jsonify
import stripe
import gspread
from google.oauth2.service_account import Credentials

# Configuration
stripe.api_key = "your_stripe_secret_key"
endpoint_secret = "your_stripe_webhook_signing_secret"
SPREADSHEET_ID = "your_google_sheet_id"

app = Flask(__name__)

# Initialize Google Sheets client
scopes = ["https://www.googleapis.com/auth/spreadsheets"]
creds = Credentials.from_service_account_file("credentials.json", scopes=scopes)
client = gspread.authorize(creds)
sheet = client.open_by_key(SPREADSHEET_ID).sheet1

@app.route('/webhook', methods=['POST'])
def stripe_webhook():
    payload = request.data
    sig_header = request.headers.get('Stripe-Signature')
    event = None

    try:
        # Verify webhook signature
        event = stripe.Webhook.construct_event(
            payload, sig_header, endpoint_secret
        )
    except ValueError as e:
        # Invalid payload
        return jsonify({'status': 'invalid payload'}), 400
    except stripe.error.SignatureVerificationError as e:
        # Invalid signature
        return jsonify({'status': 'invalid signature'}), 400

    # Handle specific event types
    if event['type'] == 'payment_intent.succeeded':
        payment_intent = event['data']['object']
        amount = payment_intent['amount'] / 100  # Convert cents to dollars
        currency = payment_intent['currency'].upper()
        customer_email = payment_intent.get('receipt_email') or "N/A"
        payment_id = payment_intent['id']

        # Append data to Google Sheet
        try:
            sheet.append_row([payment_id, customer_email, amount, currency, "Succeeded"])
        except Exception as e:
            print(f"Error writing to Google Sheets: {e}")
            return jsonify({'status': 'sheet write error'}), 500

    return jsonify({'status': 'success'}), 200

if __name__ == '__main__':
    app.run(port=4242)

4. Connect Stripe to Your Local Server

To test this setup locally, Stripe needs a public URL to send events to. Use the Stripe CLI to forward events directly to your local Flask app:

  • Download and log in to the Stripe CLI.
  • Run the following command to forward webhooks to your running Flask application:
stripe listen --forward-to localhost:4242/webhook

The CLI will output a webhook signing secret starting with whsec_. Copy this value and replace your_stripe_webhook_signing_secret in your app.py file.

5. Deploying to Production

When deploying this script to a live server (e.g., AWS, Heroku, or DigitalOcean):

  • Ensure your production endpoint uses HTTPS.
  • Replace the Stripe CLI signing secret with your live webhook signing secret from the Stripe Dashboard (Developers > Webhooks).
  • Store sensitive credentials (like your Stripe API keys and Google JSON credentials) securely using environment variables rather than hardcoding them in the source code.

Need this done fast? order it on Kwork.

Published 2026-06-23 2 min read All articles EN / RU / ES
Need help with this?

I take on freelance fixes and builds in this area.