Python
    rest-api

    Python Stripe Payment Intent API Example with Requests

    Step-by-step Python Stripe Payment Intent example using requests. Learn how to authenticate with secret keys, use idempotency, handle errors, and test requests in Apicurl.

    0 views
    Updated 2/23/2026

    Ready to test this code?

    Load this example into the app

    Code Example

    Copy and run
    import os
    import requests
    
    STRIPE_SECRET_KEY = os.getenv("STRIPE_SECRET_KEY", "sk_test_your_test_key_here")
    
    def create_payment_intent(amount_cents: int, currency: str = "usd"):
        url = "https://api.stripe.com/v1/payment_intents"
    
        headers = {
            "Authorization": f"Bearer {STRIPE_SECRET_KEY}",
            "Content-Type": "application/x-www-form-urlencoded",
        }
    
        data = {
            "amount": str(amount_cents),
            "currency": currency,
            "payment_method_types[]": "card",
            "description": "Apicurl Python Stripe Payment Intent Example",
        }
    
        response = requests.post(url, headers=headers, data=data, timeout=15)
    
        if response.status_code != 200:
            print("Stripe error:", response.status_code, response.text)
            raise SystemExit("Failed to create payment intent")
    
        payment_intent = response.json()
        print("Created Payment Intent:", payment_intent["id"], "status:", payment_intent["status"])
        return payment_intent
    
    if __name__ == "__main__":
        create_payment_intent(2000)
    

    Overview

    Python Stripe Payment Intent API Example with Requests

    Stripe is a popular payments platform that exposes a clean, well-documented HTTP API. In this tutorial, you will learn how to call the Stripe Payment Intents API using Python's requests library in a way that is safe, testable, and suitable for production.

    We will cover:

    • Authenticating with Stripe using a secret API key
    • Creating a Payment Intent with amount, currency, and metadata
    • Using idempotency keys to safely retry API calls
    • Handling errors and declined payments correctly
    • Testing the request in Apicurl so you can debug headers and JSON

    The examples below use Stripe test mode and test API keys. Never hard-code real live keys in your source code or commit them to version control.

    1. Prerequisites

    Before you start, you should have:

    • A Stripe account (you can use a free test account)
    • A Stripe test secret key, which looks like sk_test_...
    • Python 3.x installed
    • The requests package installed:
    pip install requests
    
    • Apicurl open at /app if you want to test the HTTP request interactively.

    2. Configure Your Stripe Secret Key

    In production, you should load secrets from environment variables. For local testing, you can define:

    export STRIPE_SECRET_KEY="sk_test_your_test_key_here"
    

    In Windows PowerShell:

    $Env:STRIPE_SECRET_KEY="sk_test_your_test_key_here"
    

    In Python, you can then read this value safely:

    import os
    
    STRIPE_SECRET_KEY = os.getenv("STRIPE_SECRET_KEY", "sk_test_your_test_key_here")
    

    Never log or expose your secret key in client-side code, error messages, or analytics.

    3. Create a Stripe Payment Intent with Python Requests

    The Payment Intents API lets you model the full lifecycle of a payment, including multi-step flows like 3D Secure. Here is a minimal example that creates a Payment Intent for a 20.00 USD payment:

    import os
    import requests
    
    STRIPE_SECRET_KEY = os.getenv("STRIPE_SECRET_KEY", "sk_test_your_test_key_here")
    
    def create_payment_intent(amount_cents: int, currency: str = "usd"):
        url = "https://api.stripe.com/v1/payment_intents"
    
        headers = {
            "Authorization": f"Bearer {STRIPE_SECRET_KEY}",
            "Content-Type": "application/x-www-form-urlencoded",
        }
    
        data = {
            "amount": str(amount_cents),
            "currency": currency,
            "payment_method_types[]": "card",
            "description": "Apicurl Python Stripe Payment Intent Example",
            "metadata[order_id]": "sample-order-123",
        }
    
        response = requests.post(url, headers=headers, data=data, timeout=15)
    
        if response.status_code != 200:
            print("Stripe error:", response.status_code, response.text)
            raise SystemExit("Failed to create payment intent")
    
        payment_intent = response.json()
        print("Created Payment Intent:", payment_intent["id"], "status:", payment_intent["status"])
        return payment_intent
    
    if __name__ == "__main__":
        create_payment_intent(2000)
    

    This function:

    • Sends amount in cents (e.g., 2000 = $20.00)
    • Sets payment_method_types[] to card
    • Uses metadata so you can later correlate Stripe objects with your own orders

    4. Add Idempotency for Safe Retries

    Network issues, timeouts, or server restarts can cause duplicate requests. Stripe supports idempotency keys so that the same request can be retried safely without charging the customer multiple times.

    import uuid
    
    def create_payment_intent_idempotent(amount_cents: int, currency: str = "usd"):
        url = "https://api.stripe.com/v1/payment_intents"
        idempotency_key = str(uuid.uuid4())
    
        headers = {
            "Authorization": f"Bearer {STRIPE_SECRET_KEY}",
            "Content-Type": "application/x-www-form-urlencoded",
            "Idempotency-Key": idempotency_key,
        }
    
        data = {
            "amount": str(amount_cents),
            "currency": currency,
            "payment_method_types[]": "card",
            "description": "Apicurl Python Stripe Payment Intent Example (idempotent)",
        }
    
        response = requests.post(url, headers=headers, data=data, timeout=15)
    
        if response.status_code != 200:
            print("Stripe error:", response.status_code, response.text)
            raise SystemExit("Failed to create payment intent")
    
        payment_intent = response.json()
        print("Created Payment Intent:", payment_intent["id"], "status:", payment_intent["status"])
        return payment_intent
    

    When you repeat the same call with the same Idempotency-Key, Stripe ensures that only one Payment Intent is created.

    5. Confirming a Payment Intent (Server-Side)

    For many test flows, you can confirm the Payment Intent directly with a test card. In production, you integrate with Stripe Elements or a payment form. Here is a simplified example that confirms a Payment Intent server-side in test mode:

    def confirm_payment_intent(intent_id: str):
        url = f"https://api.stripe.com/v1/payment_intents/{intent_id}/confirm"
    
        headers = {
            "Authorization": f"Bearer {STRIPE_SECRET_KEY}",
            "Content-Type": "application/x-www-form-urlencoded",
        }
    
        data = {
            "payment_method": "pm_card_visa",  # Stripe test card
        }
    
        response = requests.post(url, headers=headers, data=data, timeout=15)
    
        if response.status_code != 200:
            print("Stripe error:", response.status_code, response.text)
            raise SystemExit("Failed to confirm payment intent")
    
        payment_intent = response.json()
        print("Confirmed Payment Intent:", payment_intent["id"], "status:", payment_intent["status"])
        return payment_intent
    

    In test mode, Stripe provides a special test payment method pm_card_visa that always succeeds. For real customers, you would collect card details via Stripe.js and send the resulting payment method ID to your backend.

    6. Using This Example in Apicurl

    To explore and debug these Stripe requests in Apicurl:

    1. Open /examples/python/rest-api/python-stripe-payment-intent.
    2. Click "Try It in Apicurl".
    3. The example request will load into the Apicurl app as a configured POST request.
    4. Replace the placeholder sk_test_your_test_key_here with your real Stripe test key.
    5. Send the request and inspect the JSON response, headers, and error messages.

    Using Apicurl you can also:

    • Duplicate the request for different currencies and amounts.
    • Add test scripts that assert on status values like requires_payment_method or succeeded.
    • Generate code snippets for other languages using the same HTTP configuration.

    7. Best Practices for Calling Stripe from Python

    When integrating Stripe into a Python backend:

    • Always use HTTPS and the official API endpoints.
    • Store Stripe keys in environment variables, not in code.
    • Use idempotency keys for operations that create charges or payment intents.
    • Implement clear error handling for declined cards and network issues.
    • Log Stripe request IDs (request-id header) to correlate logs with dashboard events.
    • Use tools like Apicurl in staging to test webhooks and payment flows before going live.

    By following these patterns and using this example as a starting point, you get a Stripe integration that is secure, predictable, and easy to evolve as your product grows.

    Related Topics

    python
    stripe api
    payment intent
    online payments
    api authentication
    idempotency
    api testing
    apicurl

    Ready to test APIs like a pro?

    Apicurl is a free, powerful API testing tool.