Python library for the Stripe API.

Overview

Stripe Python Library

Build Status Coverage Status

The Stripe Python library provides convenient access to the Stripe API from applications written in the Python language. It includes a pre-defined set of classes for API resources that initialize themselves dynamically from API responses which makes it compatible with a wide range of versions of the Stripe API.

Documentation

See the Python API docs.

See video demonstrations covering how to use the library.

Installation

You don't need this source code unless you want to modify the package. If you just want to use the package, just run:

pip install --upgrade stripe

Install from source with:

python setup.py install

Requirements

  • Python 2.7+ or Python 3.4+ (PyPy supported)

Usage

The library needs to be configured with your account's secret key which is available in your Stripe Dashboard. Set stripe.api_key to its value:

import stripe
stripe.api_key = "sk_test_..."

# list customers
customers = stripe.Customer.list()

# print the first customer's email
print(customers.data[0].email)

# retrieve specific Customer
customer = stripe.Customer.retrieve("cus_123456789")

# print that customer's email
print(customer.email)

Handling exceptions

Unsuccessful requests raise exceptions. The class of the exception will reflect the sort of error that occurred. Please see the Api Reference for a description of the error classes you should handle, and for information on how to inspect these errors.

Per-request Configuration

Configure individual requests with keyword arguments. For example, you can make requests with a specific Stripe Version or as a connected account:

import stripe

# list customers
stripe.Customer.list(
    api_key="sk_test_...",
    stripe_account="acct_...",
    stripe_version="2019-02-19"
)

# retrieve single customer
stripe.Customer.retrieve(
    "cus_123456789",
    api_key="sk_test_...",
    stripe_account="acct_...",
    stripe_version="2019-02-19"
)

Configuring a Client

The library can be configured to use urlfetch, requests, pycurl, or urllib2 with stripe.default_http_client:

client = stripe.http_client.UrlFetchClient()
client = stripe.http_client.RequestsClient()
client = stripe.http_client.PycurlClient()
client = stripe.http_client.Urllib2Client()
stripe.default_http_client = client

Without a configured client, by default the library will attempt to load libraries in the order above (i.e. urlfetch is preferred with urllib2 used as a last resort). We usually recommend that people use requests.

Configuring a Proxy

A proxy can be configured with stripe.proxy:

stripe.proxy = "https://user:[email protected]:1234"

Configuring Automatic Retries

You can enable automatic retries on requests that fail due to a transient problem by configuring the maximum number of retries:

stripe.max_network_retries = 2

Various errors can trigger a retry, like a connection error or a timeout, and also certain API responses like HTTP status 409 Conflict.

Idempotency keys are automatically generated and added to requests, when not given, to guarantee that retries are safe.

Logging

The library can be configured to emit logging that will give you better insight into what it's doing. The info logging level is usually most appropriate for production use, but debug is also available for more verbosity.

There are a few options for enabling it:

  1. Set the environment variable STRIPE_LOG to the value debug or info

    $ export STRIPE_LOG=debug
  2. Set stripe.log:

    import stripe
    stripe.log = 'debug'
  3. Enable it through Python's logging module:

    import logging
    logging.basicConfig()
    logging.getLogger('stripe').setLevel(logging.DEBUG)

Writing a Plugin

If you're writing a plugin that uses the library, we'd appreciate it if you identified using stripe.set_app_info():

stripe.set_app_info("MyAwesomePlugin", version="1.2.34", url="https://myawesomeplugin.info")

This information is passed along when the library makes calls to the Stripe API.

Request latency telemetry

By default, the library sends request latency telemetry to Stripe. These numbers help Stripe improve the overall latency of its API for all users.

You can disable this behavior if you prefer:

stripe.enable_telemetry = False

Development

The test suite depends on stripe-mock, so make sure to fetch and run it from a background terminal (stripe-mock's README also contains instructions for installing via Homebrew and other methods):

go get -u github.com/stripe/stripe-mock
stripe-mock

Run the following command to set up the development virtualenv:

make

Run all tests on all supported Python versions:

make test

Run all tests for a specific Python version (modify -e according to your Python target):

TOX_ARGS="-e py37" make test

Run all tests in a single file:

TOX_ARGS="-e py37 -- tests/api_resources/abstract/test_updateable_api_resource.py" make test

Run a single test suite:

TOX_ARGS="-e py37 -- tests/api_resources/abstract/test_updateable_api_resource.py::TestUpdateableAPIResource" make test

Run a single test:

TOX_ARGS="-e py37 -- tests/api_resources/abstract/test_updateable_api_resource.py::TestUpdateableAPIResource::test_save" make test

Run the linter with:

make lint

The library uses Black for code formatting. Code must be formatted with Black before PRs are submitted, otherwise CI will fail. Run the formatter with:

make fmt
Issues
  • How to delete a price using API

    How to delete a price using API

    Hello,

    I want to delete a price inside a product, I can do it in the Stripe dashboard, but I can’t do this using API

    Code:

    stripe.Price.delete("price_HLez6Zi58HejNP")
    

    Result:

      File "../src/payments/models.py", line 81, in delete
        stripe.Price.delete(self.stripe_id)
    AttributeError: type object 'Price' has no attribute 'delete'
    

    Thanks

    opened by moskrc 32
  • Allow access to request metadata on success

    Allow access to request metadata on success

    Hey @ob-stripe this is my first stab at getting response headers out of the python bindings.

    I'm trying to follow the same pattern by including a response resource to the returned API models.

    However one tricky part is understanding where the best spot is to place an optional flag to include the response field on returned API resources. Each API request method contains a paramsparameter that directly maps to the API's URL parameters. Placing some kind of include_response flag here would stick out since it won't be going to the API.

    Another thought was using a static variable somewhere and checking that variable within the api_requestor to include the response or not.

    Do you have any opinions here?

    opened by sedouard 27
  • UPDATE: Stripe API proxy support for requests, pycurl, and urllib2 clients

    UPDATE: Stripe API proxy support for requests, pycurl, and urllib2 clients

    In complex enterprise environment, different proxies may be used for communication across the many enterprise network zones, the Internet. Obviously, the HTTP_PROXY and HTTPS_PROXY environment variables are more trouble than help there.

    A clean solution would be introducing API level proxy support that limits the proxy scope to just stripe communication. Everybody else would remain unaffected and could continue using either direct or own, different HTTP proxy configuration.

    This pull request introduces the proxy API support described. The new proxy-example.py file demonstrates the proxy API usage.

    Please consider prompt review of this pull request. Not having the proxy support will affect our project with an externally set, beyond our control hard deadline.

    Happy to address any questions or concerns.

    Thank you!

    approved 
    opened by krassif 24
  • Add support for Google App Engine dev server

    Add support for Google App Engine dev server

    Summary

    Currently the stripe library is not compatible with the App Engine dev server, this fixes that by disabling the ssl revoked cert check when running on the dev app server.

    More detail

    Google App Engine blocks access to many C modules including the socket module. It provides its own implementation but this causes a TypeError when used with the ssl C module.

    This PR skips the ssl preflight check when a TypeError occurs on the App Engine server, this doesn't add much risk as the attacker would have to be in control of the connection between the user and stripe and also have a copy of the pre-heartbleed ssl private key. In any case the check can be bypassed since connections aren't reused and the check is only done once for the lifetime of an instance so an attacker would simply trigger a stripe request on the target website (buy something with a dummy card) to get the check out the way and then start the MITM attack then trigger another stripe transaction and get the secret key.

    Why catch the exception rather than detect the environment?

    If a fix for the underlying issue with the App Engine dev server gets released then the check will work again.

    Feedback

    Not sure whether it is appropriate to include a warning here? If so, what should it say?

    opened by danielchatfield 18
  • Better support for uploading in-memory images

    Better support for uploading in-memory images

    A fairly common use case for file uploads is to upload an image to Stripe that was just uploaded to the server, or to retrieve an image from a URL, then upload it to Stripe. As it stands, the file uploader seems to expect to be given a file stored on disk, which isn't really necessary. More specifically, the file uploader wants something that has a .read method, and a .name method.

    Right now, if I take a StringIO (which supports .read), then monkey-patch it to have .name="foo", this seems to upload fine, and I more or less get the thing I want. This is a bit gross, though. Ideally, we wouldn't require a file name for the file at all, since this doesn't appear to be getting used in any meaningful way. (The upload response or anything else I can find doesn't seem to make reference to the filename.)

    Though it doesn't seem like uploads.stripe.com actually does anything with the file name, it does get unhappy if the parameter is omitted or left blank. As far as I can tell, if I patch stripe-python to just pass a hard-coded dummy value as the file name, this works fine. This is clearly a hack, though. In an ideal world, uploadsrv wouldn't look for a filename at all, though I don't really know if that would be a simple change or not.

    Thoughts on whether this is something we'd want to support, and if so, what the cleanest way of doing this is?

    future 
    opened by praboud 16
  • Try to reuse the HttpClient between requests by default

    Try to reuse the HttpClient between requests by default

    Previously, if the user has not set stripe.default_http_client, a new client would be created for every request. This commit changes the APIRequestor to populate stripe.default_http_client if it had not been set by the user, so the client can be reused between requests.

    r? @brandur-stripe @ob-stripe cc @stripe/api-libraries

    opened by jameshageman-stripe 15
  • Fix ssl import error in GAE

    Fix ssl import error in GAE

    This avoids an ImportError when loading the SSL library in a Google App Engine dev environment. For more details, see: https://code.google.com/p/googleappengine/issues/detail?id=9246

    This PR is a followup from an internal ticket. I'll merge once the reporter has confirmed that this fixes the issue in his environment.

    opened by metcalf 15
  • Implement retry mechanism when using requests

    Implement retry mechanism when using requests

    This PR implements a retry mechanism if any request would fail when using requests. It closes #464.

    More detailed documentation of Retry can be found in the urllib3 documentation

    • Total: The amount of total retries
    • backoff_factor: it will sleep for: {backoff factor} * (2 ^ ({number of total retries} - 1)) between retries
    • status: How many times to retry on bad status codes. The ones on status_forcelist
    • status_forcelist: Bad status codes which it will retry on.
    opened by jonathan-s 14
  • Install started failing for users of older pip

    Install started failing for users of older pip

    @brandur-stripe @ob-stripe Requests 2.14.1 just released and now requires pip >= 8.1.2 and a newish version of setuptools https://github.com/kennethreitz/requests/issues/4006

    As of today, stripe-python will fail to install for users of older packaging infrastructure, including Travis. https://travis-ci.org/stripe/stripe-python/jobs/230553497#L497 https://github.com/kennethreitz/requests/pull/4007#issuecomment-300364756

    We should deploy an emergency release limiting requests to version 2.13.0 and documentation should be added detailing that in the next major release there will be a minimum required version of pip.

    opened by ofek 14
  • Add Stripe client telemetry to request headers

    Add Stripe client telemetry to request headers

    Follows https://github.com/stripe/stripe-ruby/pull/696 and https://github.com/stripe/stripe-php/pull/549 in adding telemetry metadata to request headers.

    The telemetry is disabled by default, and can be enabled like so:

    stripe.enable_telemetry = True
    
    approved 
    opened by jameshageman-stripe 12
  • Add `modify` class method for updateable resources

    Add `modify` class method for updateable resources

    I'd much rather call this method update, but we can't use that name because StripeObject already has an update method, and I'd rather not make this a breaking change. Note that this PR is not ready merge. There are a few resources that are going to need a custom modify method due to URL format.

    approved 
    opened by kyleconroy 12
  • For webhooks, `webhook.request` is both a method and a data attribute

    For webhooks, `webhook.request` is both a method and a data attribute

    Describe the bug

    Incoming webhook events have a request data attribute, but the event instance already has a request bound method, so we end up with a bit of a conflict. The data attribute can still be accessed with event["request"] but it feels weird to need to do that for just that one data attribute and then use dot syntax for everything else.

    >>> event = stripe.Webhook.construct_event(...)
    
    >>> event.request
    <bound method StripeObject.request of <Event event id=<id_omitted> at 0x1035bb450> JSON: { ...
    
    >>> event["request"]
    <StripeObject id=<id_omitted> at 0x102e95810> JSON: {
      "id": "<id_omitted>",
      "idempotency_key": "<idempotency_key_omitted>"
    }
    

    event.request and event["request"] both returning different things is rather confusing, and it took me quite a while to figure out what was going on.

    To Reproduce

    1. Construct a webhook event.
    2. Access event.request.
    3. Access event["request"].
    4. Notice that they are different.

    I would probably consider this less of a "bug" and more of an oversight.

    Expected behavior

    The event.request method should probably be something like event._request so it doesn't conflict with the incoming data. That way I can call event.request and actually get the attribute from the body of the webhook as expected.

    Code snippets

    No response

    OS

    macOS

    Language version

    Python 3.9.10

    Library version

    stripe-python v2.76.0

    API version

    2020-08-27

    Additional context

    No response

    bug future 
    opened by AaronBeaudoin 1
  • Auto-paging returns results 10 by 10, even if limit is set to 100 when I request to expand properties

    Auto-paging returns results 10 by 10, even if limit is set to 100 when I request to expand properties

    Describe the bug

    Bug location

    auto-pagination in python library

    Description

    When I call the charge API using the python library and set the limit to 100, with some filters and property expand, the auto-paging returns results 10 by 10.

    The first API call returns the first 100 items on first page, then auto-paging returns the results 10 by 10.

    Here is the piece of code:

    LIMIT = 100
    charges = stripe.Charge.list(
                limit=LIMIT, created= {'gt': start_after_date}, expand=["data.customer", "data.dispute", "data.invoice", "data.transfer", "data.balance_transaction"])
    
     for charge in charges.auto_paging_iter():
         #do something with charge
    

    However it works ok if you just make the Charge.list call with limit and filter, but the expand, makes the iterator return the results 10 by 10. So expanding the properties seems to be the reason why I am back to the default limit in auto-pagination.

    Is that expected?

    To Reproduce

    • Fetch charge lists using "created" filter greater than a given date.
    • Request to expand ["data.customer", "data.dispute", "data.invoice", "data.transfer", "data.balance_transaction"] in the call.
    • Set the limit to 100.
    • Make the API call
    • start a loop with auto paging
    • See that the results are not sent 100 by 100 but 10 by 10 in the for loop.
    import stripe
    stripe.api_key = "xxx"
    
    LIMIT = 100
    charges = stripe.Charge.list(
                limit=LIMIT, created= {'gt': start_after_date}, expand=["data.customer", "data.dispute", "data.invoice", "data.transfer", "data.balance_transaction"])
    print(len(charges), "charges found")
    
     for charge in charges.auto_paging_iter():
           print(len(charge), "charges found")
    

    Expected behavior

    Auto-paging should return results 100 by 100

    Code snippets

    import stripe
    stripe.api_key = "xxx"
    
    LIMIT = 100
    charges = stripe.Charge.list(
                limit=LIMIT, created= {'gt': start_after_date}, expand=["data.customer", "data.dispute", "data.invoice", "data.transfer", "data.balance_transaction"])
    print(len(charges), "charges found")
    
     for charge in charges.auto_paging_iter():
           print(len(charge), "charges found")
    
    
    
    ### OS
    
    macOS
    
    ### Language version
    
    Python 3.9
    
    ### Library version
    
    stripe-python 3.3.0
    
    ### API version
    
    2020-08-27
    
    ### Additional context
    
    _No response_
    bug 
    opened by kamalmoona 3
  • Setting a List Field to [] When Modifying a Resource Doesn't Actually Empty The List Field

    Setting a List Field to [] When Modifying a Resource Doesn't Actually Empty The List Field

    Describe the bug

    When trying to clear out the list of previously set blocked_categories on a cardholder, calling

    stripe.issuing.Cardholder.modify(
        "ich_...",
        spending_controls={'blocked_categories': []},
        stripe_account="acct_...",
    )
    

    returns successfully but doesn't clear out the blocked_categories on the cardholder and returns a cardholder instance with the previous blocked_categories list still set.

    Instead, it is necessary to replace [] with "":

    stripe.issuing.Cardholder.modify(
        "ich_...",
        spending_controls={'blocked_categories': ""},
        stripe_account="acct_...",
    )
    

    and that successfully clears the list of blocked_categories—however, there is no mention of the need to make this distinction when calling stripe.issuing.Cardholder.modify or any other method in the Stripe API docs or this library's docs and setting a list to empty by setting its value to "" is not valid Python syntax.

    To Reproduce

    1. create a stripe connect account via:
    stripe.Account.create(
        type="custom",
        country="US",
        email="[email protected]",
        requested_capabilities=["transfers", "card_payments", "card_issuing"],
    )
    
    1. complete any requested test KYB information to ensure the account is fully verified and approved
    2. create a cardholder via:
    stripe.issuing.Cardholder.create(
        name="Jane Doe",
        email="[email protected]",
        status="active",
        type="individual",
        billing={
            "name": "Jane Doe",
            "address": {
                "line1": "117 West St",
                "line2": None,
                "city": "New York",
                "state": "NY",
                "country": "US",
                "postal_code": "10006",
            },
        },
        spending_controls={'blocked_categories': ['floor_covering_stores']},
        stripe_account="acct_...",  # id of the account created above
    )
    
    1. attempt to update the cardholder via:
    stripe.issuing.Cardholder.modify(
        "ich_...",  # id of the cardholder created above
        spending_controls={'blocked_categories': []},
        stripe_account="acct_...",  # id of the account created above
    )
    

    Expected behavior

    Setting a list to [] should set that list to empty. It is not intuitive or valid Python syntax to set a list to empty by setting its value to "".

    Code snippets

    See code snippets in the "Describe the bug" and "To Reproduce" sections

    OS

    macOS

    Language version

    Python 3.10.2

    Library version

    stripe-python v2.67.0

    API version

    2019-10-17

    Additional context

    No response

    bug 
    opened by jake-kent 0
  • Import errors

    Import errors

    Hello, I've recently upgraded my stripe library version to the latest v2.67.0 and after checking my app I saw all the stripe related endpoints failing. Checking my AWS Lambda CloudWatch logs I got this message: cannot import name 'test_helpers' from 'stripe.api_resources' While investigating the stripe library in my python environment's site-packages and checking all the imports of the stripe.api_resources I also found other 2 that seem to have import problems according to my PyCharm IDE saying it doesn't find their reference. Below I'm posting the all those that look like to have import issues in the stripe.api_resources init file: from stripe.api_resources import test_helpers from stripe.api_resources.payment_link import PaymentLink from stripe.api_resources.shipping_rate import ShippingRate

    opened by Axomme87 1
  • JSON log formatting

    JSON log formatting

    Hello,

    It would be great to allow users to format logs in json format instead of the hardcoded logfmt format in the library. For those looking to make this work, this is how we did it:

    # strip_log_formatter.py
    import datetime
    import json
    
    from pythonjsonlogger import jsonlogger
    
    
    class StripeJsonLogFormatter(jsonlogger.JsonFormatter):  # pragma: no cover
        def add_fields(self, log_record, record, message_dict):
            """
            This method allows us to inject custom data into resulting log messages
            """
            for field in self._required_fields:
                log_record[field] = record.__dict__.get(field)
            log_record.update(message_dict)
    
            # Add timestamp and application name if not present
            if 'timestamp' not in log_record:
                now = datetime.datetime.utcnow()
                log_record['timestamp'] = now.isoformat()
            if 'application' not in log_record:
                log_record['application'] = 'myapp'
    
            if 'level' not in log_record:
                log_record['level'] = record.levelname
    
            jsonlogger.merge_record_extra(record, log_record, reserved=self._skip_fields)
    

    Reference this class from stripe_log_formatter.py in log ini configuration file as follows:

    [loggers]
    keys=stripe
    
    [handlers]
    keys=stripe_file
    
    [formatters]
    keys=stripe_json
    
    [logger_stripe]
    level=INFO
    handlers=stripe_file
    qualname=stripe
    propagate=0
    
    [handler_stripe_file]
    class=logging.handlers.WatchedFileHandler
    formatter=stripe_json
    args=('/var/log/myapp/stripe.json',)
    
    [formatter_stripe_json]
    class=app.stripe_log_formatter.StripeJsonLogFormatter
    

    And then at import time, monkey patch stripe library:

    # Monkey patch Stripe logfmt formatter
    # Watch for this code if it ever changes, things will break:
    # https://github.com/stripe/stripe-python/blob/v2.67.0/stripe/util.py#L82
    
    old_log_fmt = stripe.util.logfmt
    
    def new_logfmt(props):
        return OrderedDict(sorted(props.items(), key=lambda x: x[0]))
    
    stripe.util.logfmt = new_logfmt
    

    Any chance we can get an ability to configure our own log formatter?

    opened by neilpanchal 0
Releases(v3.4.0)
Beyonic API Python official client library simplified examples using Flask, Django and Fast API.

Beyonic API Python official client library simplified examples using Flask, Django and Fast API.

Harun Mbaabu Mwenda 45 Nov 18, 2021
Python API wrapper library for Convex Value API

convex-value-python Python API wrapper library for Convex Value API. Further Links: Convex Value homepage @ConvexValue on Twitter JB on Twitter Authen

Aaron DeVera 2 May 11, 2022
This an API wrapper library for the OpenSea API written in Python 3.

OpenSea NFT API Python 3 wrapper This an API wrapper library for the OpenSea API written in Python 3. The library provides a simplified interface to f

Attila Tóth 126 Jun 23, 2022
Aio-binance-library - Async library for connecting to the Binance API on Python

aio-binance-library Async library for connecting to the Binance API on Python Th

GRinvest 7 Mar 12, 2022
PRAW, an acronym for "Python Reddit API Wrapper", is a python package that allows for simple access to Reddit's API.

PRAW: The Python Reddit API Wrapper PRAW, an acronym for "Python Reddit API Wrapper", is a Python package that allows for simple access to Reddit's AP

Python Reddit API Wrapper Development 2.8k Jun 28, 2022
PRAW, an acronym for "Python Reddit API Wrapper", is a python package that allows for simple access to Reddit's API.

PRAW: The Python Reddit API Wrapper PRAW, an acronym for "Python Reddit API Wrapper", is a Python package that allows for simple access to Reddit's AP

Python Reddit API Wrapper Development 2.8k Jun 22, 2022
WhatsApp Api Python - This documentation aims to exemplify the use of Moorse Whatsapp API in Python

WhatsApp API Python ChatBot Este repositório contém uma aplicação que se utiliza

Moorse.io 3 Jan 8, 2022
Official python API for Phish.AI public and private API to detect zero-day phishing websites

phish-ai-api Summary Official python API for Phish.AI public and private API to detect zero-day phishing websites How it Works (TLDR) Essentially we h

Phish.AI 168 May 17, 2022
Python API wrapper around Trello's API

A wrapper around the Trello API written in Python. Each Trello object is represented by a corresponding Python object. The attributes of these objects

Richard Kolkovich 892 Jun 17, 2022
A python to scratch API connector. Can fetch data from the API and send it back in cloud variables.

Scratch2py Scratch2py or S2py is a easy to use, versatile tool to communicate with the Scratch API Based of scratchclient by Raihan142857 Installation

null 20 Jun 18, 2022
Async ready API wrapper for Revolt API written in Python.

Mutiny Async ready API wrapper for Revolt API written in Python. Installation Python 3.9 or higher is required To install the library, you can just ru

null 16 Mar 29, 2022
🚀 An asynchronous python API wrapper meant to replace discord.py - Snappy discord api wrapper written with aiohttp & websockets

Pincer An asynchronous python API wrapper meant to replace discord.py ❗ The package is currently within the planning phase ?? Links |Join the discord

Pincer 117 Jun 30, 2022
wyscoutapi is an extremely basic API client for the Wyscout API (v2 & v3) for Python

wyscoutapi wyscoutapi is an extremely basic API client for the Wyscout API (v2 & v3). Usage Install with pip install wyscoutapi. To connect to the Wys

Ben Torvaney 9 Apr 24, 2022
A Python API wrapper for the Twitter API!

PyTweet PyTweet is an api wrapper made for twitter using twitter's api version 2! Installation Windows py3 -m pip install PyTweet Linux python -m pip

TheFarGG 23 May 29, 2022
A new coin listing alert bot using Python, Flask, MongoDB, Telegram API and Binance API

Bzzmans New Coin Listing Detection Bot Architecture About Project Work in progress. This bot basically gets new coin listings from Binance using Binan

Eyüp Barlas 21 May 31, 2022
YARSAW is an Async Python API Wrapper for the Random Stuff API.

Yet Another Random Stuff API Wrapper - YARSAW YARSAW is an Async Python API Wrapper for the Random Stuff API. This module makes it simpler for you to

Bruce 6 Mar 27, 2022
Python API Client for Twitter API v2

?? Python Client For Twitter API v2 ?? Why Twitter Stream ? Twitter-Stream.py a python API client for Twitter API v2 now supports FilteredStream, Samp

Twitivity 27 Apr 29, 2022
EpikCord.py - This is an API Wrapper for Discord's API for Python

EpikCord.py - This is an API Wrapper for Discord's API for Python! We've decided not to fork discord.py and start completely from scratch for a new, better structuring system!

EpikHost 23 Jun 20, 2022
A simple Python API wrapper for Cloudflare Stream's API.

python-cloudflare-stream A basic Python API wrapper for working with Cloudflare Stream. Arbington.com started off using Cloudflare Stream. We used the

Arbington 2 Feb 15, 2022