Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
53c7649
update user agent to match newer version of mobile app
j027 Sep 1, 2024
ce99b0e
Add initial support for getting the eligibility token. This might nee…
j027 Sep 2, 2024
7051504
add models and json handling for eligibility token, including the fee…
j027 Sep 5, 2024
c935bf9
add handling for eligibility token
j027 Sep 5, 2024
d60f28c
bump version in user agent to match latest version of venmo app
j027 Sep 20, 2024
5982a34
Merge branch 'mmohades:master' into master
j027 Sep 22, 2024
9ad1706
getting close with headers.json i think?
joshhubert-dsp Sep 25, 2025
4b0de5d
ruffed up
joshhubert-dsp Nov 7, 2025
22a759f
cleanup
joshhubert-dsp Nov 9, 2025
a44e2ce
eligibility token fix
joshhubert-dsp Nov 11, 2025
932b8ff
Client/ApiClient cleanup
joshhubert-dsp Nov 11, 2025
0bce707
starting to convert to pydantic
joshhubert-dsp Nov 11, 2025
cc2a7a8
checkpoint converting to pydantic
joshhubert-dsp Nov 11, 2025
d2f75c1
pydantic everything
joshhubert-dsp Nov 12, 2025
5898ba4
cleanup getting ready for packaging
joshhubert-dsp Nov 13, 2025
8c1b4ab
Client.login_from_env
joshhubert-dsp Nov 13, 2025
8971137
Update README.md
joshhubert-dsp Nov 13, 2025
56bcc5f
Update README.md
joshhubert-dsp Nov 13, 2025
3c24ef8
EligibilityToken.ineligible_reason
joshhubert-dsp Nov 13, 2025
1338788
docstrings updated
joshhubert-dsp Nov 15, 2025
73f54f7
ApiClient is sole owner of device_id, OTP step-up error
joshhubert-dsp Nov 15, 2025
f752e68
error_code oopsie
joshhubert-dsp Dec 5, 2025
356835e
headers
joshhubert-dsp Dec 11, 2025
899cd28
update headers, transfer amount fix
joshhubert-dsp Feb 10, 2026
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

.idea/

# Created by https://www.gitignore.io/api/macos,linux,django,python,pycharm
Expand Down
89 changes: 63 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,61 @@
# Venmo API
# Python Venmo API - Updated Fork

This is a fork of mmohades' [python venmo api](https://github.com/mmohades/Venmo.git)
package, which is no longer maintained, and therefore some features/payloads (notably
payments) no longer worked. I took the liberty of fixing payment functionality, adding
additional endpoints, and refactoring it almost beyond recognition. To be specific, this
uses the mobile Venmo app API, the browser version is quite different.

## FORK UPDATES

- Payments work again! Credit to [Joseph Charles](https://github.com/j027/Venmo) for
adding eligibility token support and laying the groundwork.
- Added `PaymentApi.get_transfer_destinations()` and `PaymentApi.initiate_transfer()`
for standard/instant transfers to bank/card.
- Requires Python 3.11+, using a pyproject.toml (`uv` friendly) and modern language
features.
- The data models now use `pydantic-v2`, removing a bunch of boilerplate.
- Set the env var `LOGGING_SESSION` to print the raw requests sent and responses
received.
- `venmo.Client` has context manager dunder methods for `with` block logout using a
stored access token.
- I got rid of the threaded-async callback functionality, because it added complexity
that I didn't see as useful. In my experience Venmo is now quick to pump the brakes
on anyone hitting the API too rapidly. This manifests in the dreaded 403 response:
"OAuth2 Exception: Unable to complete your request. Please try again later", locking
you out of your account with a variable cooldown time.
- Request headers now mirror the actual app's as closely as possible. The default
headers live in `default_headers.json`.
- All code docstrings have been updated with changes.

## TODO

- Update Sphinx docs.
- Get the original creator's blessing to submit package to PyPi with a new name.

## Device ID Rigmarole

In my experience, the random device IDs generated by default are no longer accepted by
the API. I had to grab my iPhone's actual device ID from the app's request headers to
get it to cooperate. I did that using the `mitmproxy` command line tool,
routing my phone's WiFi connection through the proxy, and grabbing it from the aptly
named header `device-id` present in any request to `https://api.venmo.com/v1`.
Good instructions [here](https://blog.sayan.page/mitm-proxy-on-ios/). Luckily you only
have to do this once, the ID is fixed.

Disclaimer: This is an individual effort and is not PayPal/Venmo sponsored or maintained.
```bash
$ brew install mitmproxy
# You'll route your WiFi through your desktop IP address, port 8080
$ mitmweb --listen-host 0.0.0.0 --listen-port 8080 --web-port 8081
```

# ORIGINAL README BELOW

Disclaimer: This is an individual effort and is not PayPal/Venmo sponsored or maintained.

## Introduction

This is a wrapper for the Venmo API. This library provides a Python interface for the Venmo API. It's compatible with Python versions 3.6+.
This library provides a Python wrapper for the Venmo API, using synchronous requests.

## Installing

Expand Down Expand Up @@ -41,7 +92,7 @@ print("My token:", access_token)

The following is an example of initializing and working with the api client.

```python
```python
access_token = "YOUR_ACCESS_TOKEN"

# Initialize api client using an access-token
Expand All @@ -50,17 +101,9 @@ client = Client(access_token=access_token)
# Search for users. You get a maximum of 50 results per request.
users = client.user.search_for_users(query="Peter")
for user in users:
print(user.username)

# Or pass a callback to make it multi-threaded
def callback(users):
for user in users:
print(user.username)
print(user.username)
```

client.user.search_for_users(query="peter",
callback=callback,
limit=10)
```
##### Revoke token

Keep this in mind that your access token never expires! You will need to revoke it yoursef:
Expand All @@ -69,17 +112,15 @@ Keep this in mind that your access token never expires! You will need to revoke
client.log_out("Bearer a40fsdfhsfhdsfjhdkgljsdglkdsfj3j3i4349t34j7d")
```



##### Payment methods

Get all your payment methods to use one's id for sending_money

````python
```python
payment_methods = client.payment.get_payment_methods()
for payment_method in payment_methods:
print(payment_method.to_json())
````
```

##### Sending or requesting money

Expand All @@ -101,13 +142,9 @@ client.payment.send_money(amount=13.68,
Getting a user's transactions (only the ones that are visible to you, e.g, their `public` transactions)

```python
def callback(transactions_list):
for transaction in transactions_list:
print(transaction)

# callback is optional. Max number of transactions per request is 50.
client.user.get_user_transactions(user_id='0000000000000000000',
callback=callback)
# Max number of transactions per request is 50.
client.user.get_user_transactions(user_id='0000000000000000000')
```

##### Friends list
Expand Down Expand Up @@ -140,8 +177,8 @@ while transactions:

## Contributing

Contributions of all sizes are welcome. You can help with the wrapper documentation located in /docs. You can also help by [reporting bugs](https://github.com/mmohades/VenmoApi/issues/new). You can add more routes to both [Venmo Unofficial API Documentation](https://github.com/mmohades/VenmoApiDocumentation) and the `venmo-api` wrapper.
Contributions of all sizes are welcome. You can help with the wrapper documentation located in /docs. You can also help by [reporting bugs](https://github.com/mmohades/VenmoApi/issues/new). You can add more routes to both [Venmo Unofficial API Documentation](https://github.com/mmohades/VenmoApiDocumentation) and the `venmo-api` wrapper.

## Venmo Unofficial API Documentation

You can find and contribute to the [Venmo Unofficial API Documentation](https://github.com/mmohades/VenmoApiDocumentation).
You can find and contribute to the [Venmo Unofficial API Documentation](https://github.com/mmohades/VenmoApiDocumentation).
8 changes: 8 additions & 0 deletions default_headers.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"Host": "api.venmo.com",
"User-Agent": "Venmo/26.1.0 (iPhone; iOS 18.6.2; Scale/3.0)",
"Accept": "application/json; charset=utf-8",
"Accept-Language": "en-US;q=1.0",
"Accept-Encoding": "gzip;q=1.0,compress;q=0.5",
"Connection": "keep-alive"
}
23 changes: 11 additions & 12 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,40 +17,39 @@

# -- Project information -----------------------------------------------------

project = 'Venmo'
copyright = '2020, Mark Mohades'
author = 'Mark Mohades'
project = "Venmo"
copyright = "2020, Mark Mohades"
author = "Mark Mohades"

# The full version, including alpha/beta/rc tags
release = '0.1.0'
release = "1.0.0"


# -- General configuration ---------------------------------------------------

# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
]
extensions = []

# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
templates_path = ["_templates"]

# List of patterns, relative to source directory, that match files and
# list of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]


# -- Options for HTML output -------------------------------------------------

# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'alabaster'
html_theme = "alabaster"

# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
master_doc = 'index'
html_static_path = ["_static"]
master_doc = "index"
17 changes: 2 additions & 15 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,6 @@ The following is an example of initializing and working with the api client.
for user in users:
print(user.username)

# Or pass a callback to make it multi-threaded
def callback(users):
for user in users:
print(user.username)

client.user.search_for_users(query="peter",
callback=callback,
limit=10)

Revoke token
""""""""""""
Expand Down Expand Up @@ -111,13 +103,8 @@ Getting a user's transactions (only the ones that are visible to you, e.g, their

.. code-block:: python

def callback(transactions_list):
for transaction in transactions_list:
print(transaction)

# callback is optional. Max number of transactions per request is 50.
client.user.get_user_transactions(user_id='0000000000000000000',
callback=callback)
# Max number of transactions per request is 50.
client.user.get_user_transactions(user_id='0000000000000000000')

Friends list
""""""""""""
Expand Down
48 changes: 48 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
[project]
name = "venmo-api"
version = "1.0.0"
description = "Venmo API client for Python"
readme = "README.md"
authors = [
{ name = "Mark Mohades"},
{ name = "Joseph Charles"},
{ name = "Josh Hubert", email= "102703352+joshhubert-dsp@users.noreply.github.com" }
]
maintainers = [
{ name = "Josh Hubert", email= "102703352+joshhubert-dsp@users.noreply.github.com" }
]
license = "GPL-3.0-only"
license-files = [
"LICENSE"
]
classifiers = [
'Development Status :: 3 - Alpha',
'Intended Audience :: Developers',
'Operating System :: OS Independent',
'Natural Language :: English',
'Topic :: Software Development :: Libraries :: Python Modules',
'Topic :: Internet',
'Programming Language :: Python',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.11',
'Programming Language :: Python :: 3.12',
'Programming Language :: Python :: 3.13'
]
requires-python = ">=3.11,<3.14"
dependencies = [
"devtools>=0.12.2",
"orjson>=3.11.3",
"pydantic>=2.12.4",
"requests>=2.32.5",
"rich>=14.2.0",
]

[build-system]
requires = ["setuptools", "wheel"]
build-backend = "setuptools.build_meta"

[tool.setuptools]
package-dir = { "" = "." }

[tool.setuptools.packages.find]
where = ["."]
1 change: 0 additions & 1 deletion requirements.txt

This file was deleted.

51 changes: 0 additions & 51 deletions setup.py

This file was deleted.

Loading