Skip to main content

fewsats

This library enables AI agents to handle real-world payments autonomously. It provides a simple interface for AI systems to manage payment methods, process transactions, and interact with L402 paywalls.

The library provides two main interfaces: 1. Direct payment handling through the Python SDK 2. AI-native tools through as_tools() for autonomous agents

Install

Install latest from pypi

$ pip install fewsats

Getting Started

The library provides a Fewsats class to handle payments. You can use handle them manually or use the as_tools() method to create tools for autonomous agents.

Making Payments

Obtain information about your account and perform payments:

from fewsats.core import *
fs = Fewsats()
import os
fs = Fewsats(api_key=os.getenv("FEWSATS_LOCAL_API_KEY"), base_url='http://localhost:8000')

fs.payment_methods().json(), fs.balance().json(), fs.me().json()
([{'id': 1,
   'last4': '4242',
   'brand': 'visa',
   'exp_month': 12,
   'exp_year': 2034,
   'is_default': False},
  {'id': 4,
   'last4': '4242',
   'brand': 'Visa',
   'exp_month': 12,
   'exp_year': 2034,
   'is_default': True}],
 [{'id': 1, 'balance': 4421, 'currency': 'usd'}],
 {'name': 'Pol',
  'last_name': 'Alvarez Vecino',
  'email': 'pol@fewsats.com',
  'billing_info': None,
  'id': 1,
  'created_at': '2024-08-20T16:13:01.255Z',
  'webhook_url': 'https://example.com'})

The pay method uses the information returned by a L402 Protocol 402 Payment Required response to submit a payment. The L402 flow is handled by the backend. By default it will also choose the most convenient payment method, and assume you want to pay the first offer if multiple are available.

# Example offer from stock.l402.org
l402_offer = {
   "offers":[
      {
         "amount":1,
         "currency":"USD",
         "description":"Purchase 1 credit for API access",
         "id":"offer_c668e0c0",
         "payment_methods":[
            "lightning"
         ],
         "title":"1 Credit Package",
      }
   ],
   "payment_context_token":"edb53dec-28f5-4cbb-924a-20e9003c20e1",
   "payment_request_url":"https://stock.l402.org/l402/payment-request",
   "version":"0.2.2"
}
fs.pay_offer(l402_offer['offers'][0]['id'], l402_offer).json()
{'id': 164,
 'created_at': '2025-03-10T14:53:03.282Z',
 'status': 'success',
 'payment_method': 'lightning'}

Fewsats also supports paying for resources like a lightning invoice directly. For example:

fs.pay_lightning(invoice='lnbc100n1pn6fsyspp5g2f6hdqxc76wxccq2cd4wekck0nxfucfyvzkvy9fmxezlf3hcl6qdqqcqzpgxqyz5vqrzjqwghf7zxvfkxq5a6sr65g0gdkv768p83mhsnt0msszapamzx2qvuxqqqqz99gpz55yqqqqqqqqqqqqqq9qrzjq25carzepgd4vqsyn44jrk85ezrpju92xyrk9apw4cdjh6yrwt5jgqqqqz99gpz55yqqqqqqqqqqqqqq9qsp5yzvs9czquyf8mjgwf465k0a7g4vh7jqv2cpza3lkygnllxnzk2wq9qxpqysgqnkmhmw05q6qc8urah004jtnkuztpazgg49m3g2wfamexr0m0ayrhla2ephnsm0xan3pweqc3hexeqx2mkfr8d3afwx6rds2r2znf4vgq7new3k',
                  amount=1, currency='USD', description='Purchase 1 cent for API access')
<Response [200 OK]>

The lightning invoice already contains a payment amount, but the method requires you to specify the amount you are expecting to pay in cents. This is done for accounting purposes and convenience, but the amount paid will be the sats in the invoice.

Getting Paid

Fewsats also provides methods for receiving payments. You can create offers for receiving payments as follows.

# Create offers for receiving payments
offers_data = [{
   "id": "offer_example",
   "amount": 1,
   "currency": "USD",
   "description": "Receive payment for your service",
   "title": "1 Credit Package",
   "payment_methods": ["lightning", "stripe"]
}]
r = fs.create_offers(offers_data)
offers = r.json()
offers
{'offers': [{'offer_id': 'offer_example',
   'amount': 1,
   'currency': 'USD',
   'description': 'Receive payment for your service',
   'title': '1 Credit Package',
   'payment_methods': ['lightning', 'stripe'],
   'type': 'one-off'}],
 'payment_context_token': 'a175fd73-cb68-4a22-8685-b236eff2f1a0',
 'payment_request_url': 'http://localhost:8000/v0/l402/payment-request',
 'version': '0.2.2'}

You can check if an offer has been paid using the payment context token as follows.

fs.get_payment_status(payment_context_token=offers["payment_context_token"]).json()
{'payment_context_token': 'a175fd73-cb68-4a22-8685-b236eff2f1a0',
 'status': 'pending',
 'offer_id': None,
 'paid_at': None,
 'amount': None,
 'currency': None}

If you prefer to be notified whenever an offer is paid, you can add a webhook as follows, and we will call it whenever a payment is made.

r = fs.add_webhook(webhook_url="https://example.com/webhook")
r.json()
{'name': 'Pol',
 'last_name': 'Alvarez Vecino',
 'email': 'pol@fewsats.com',
 'billing_info': None,
 'id': 1,
 'created_at': '2024-08-20T16:13:01.255Z',
 'webhook_url': 'https://example.com/webhook'}

AI Agent Integration

We will show how to enable your AI assistant to handle payments using Claudette, Answer.ai convenient wrapper for Claude. You’ll need to export your ANTHROPIC_API_KEY as env variable for this to work.

from claudette import Chat, models
import os
# os.environ['ANTHROPIC_LOG'] = 'debug'
model = models[1]; model
'claude-3-5-sonnet-20240620'

To print every HTTP request and response in full, uncomment the above line.

fs.balance()
<Response [200 OK]>
fs.as_tools()
[<bound method Fewsats.me of <fewsats.core.Fewsats object>>,
 <bound method Fewsats.balance of <fewsats.core.Fewsats object>>,
 <bound method Fewsats.payment_methods of <fewsats.core.Fewsats object>>,
 <bound method Fewsats.pay_lightning of <fewsats.core.Fewsats object>>,
 <bound method Fewsats.payment_info of <fewsats.core.Fewsats object>>]
fs.me().json()
{'name': 'Pol',
 'last_name': 'Alvarez Vecino',
 'email': 'pol@fewsats.com',
 'billing_info': None,
 'id': 1,
 'created_at': '2024-08-20T16:13:01.255Z',
 'webhook_url': 'https://example.com/asdfagasdfaasdfa'}
chat = Chat(model, sp='You are a helpful assistant that can pay offers.', tools=fs.as_tools())
pr = f"Can you check my details and balance?"
r = chat.toolloop(pr, trace_func=print)
r
Message(id='msg_01RhcqEB5U2gWTCFAjGJemnq', content=[TextBlock(text="Certainly! I'd be happy to check your details and balance for you. To do this, I'll need to use two separate functions: one to retrieve your user information and another to check your wallet balance. Let me do that for you right away.", type='text'), ToolUseBlock(id='toolu_014fq5xHbzmtBVNpTBbNa1G3', input={}, name='me', type='tool_use'), ToolUseBlock(id='toolu_01BBGf2gQ1wNz3T9X4SsuX1G', input={}, name='balance', type='tool_use')], model='claude-3-5-sonnet-20240620', role='assistant', stop_reason='tool_use', stop_sequence=None, type='message', usage=In: 649; Out: 104; Cache create: 0; Cache read: 0; Total: 753)
Message(id='msg_01P6Cf6xpjqDwD12Xo1GSJF6', content=[TextBlock(text="I've successfully retrieved your user information and balance. However, it seems that the specific details aren't directly visible in the function results. This is likely for security reasons. \n\nWhat I can tell you is that both requests were successful, as indicated by the [200 OK] responses. This means that your account is active and accessible.\n\nIf you need more specific information about your account details or balance, you might need to log into your account directly through the official platform or app. They may have additional security measures in place to protect your sensitive information.\n\nIs there anything else you'd like me to check or any other way I can assist you with your account?", type='text')], model='claude-3-5-sonnet-20240620', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 823; Out: 140; Cache create: 0; Cache read: 0; Total: 963)

I’ve successfully retrieved your user information and balance. However, it seems that the specific details aren’t directly visible in the function results. This is likely for security reasons.

What I can tell you is that both requests were successful, as indicated by the [200 OK] responses. This means that your account is active and accessible.

If you need more specific information about your account details or balance, you might need to log into your account directly through the official platform or app. They may have additional security measures in place to protect your sensitive information.

Is there anything else you’d like me to check or any other way I can assist you with your account?

  • id: msg_01P6Cf6xpjqDwD12Xo1GSJF6
  • content: [{'text': "I've successfully retrieved your user information and balance. However, it seems that the specific details aren't directly visible in the function results. This is likely for security reasons. \n\nWhat I can tell you is that both requests were successful, as indicated by the [200 OK] responses. This means that your account is active and accessible.\n\nIf you need more specific information about your account details or balance, you might need to log into your account directly through the official platform or app. They may have additional security measures in place to protect your sensitive information.\n\nIs there anything else you'd like me to check or any other way I can assist you with your account?", 'type': 'text'}]
  • model: claude-3-5-sonnet-20240620
  • role: assistant
  • stop_reason: end_turn
  • stop_sequence: None
  • type: message
  • usage: {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 823, 'output_tokens': 140}
chat = Chat(model, sp='You are a helpful assistant that can pay offers.', tools=fs.as_tools())
pr = f"Could you pay the cheapest offer using lightning {l402_offer}?"
r = chat.toolloop(pr, trace_func=print)
r
fs.balance()
[{'id': 15, 'balance': 5962, 'currency': 'usd'}]

Metadata

Release files for fewsats 0.0.22

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for fewsats 0.0.22
File Size Uploaded Provenance
fewsats-0.0.22.tar.gz 20.1 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for fewsats 0.0.22
File Interpreter ABI Platform
fewsats-0.0.22-py3-none-any.whl Python 3 none any Details

Total release size: 36.1 kB

Release files / fewsats-0.0.22.tar.gz

Download URL fewsats-0.0.22.tar.gz
Size 20.1 kB
Tags Source
SHA-256 checksum
How to use checksums
84e100e8228cb8e6d7ba9f1d2a824b429287bdc565baf2bb45e8446044aeb141
BLAKE2b-256 checksum
How to use checksums
e08e123cf2abe2c91d9a1924b296f3b175fef9e72bde88253e2d47d5837584c8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.3

Release files / fewsats-0.0.22-py3-none-any.whl

Download URL fewsats-0.0.22-py3-none-any.whl
Size 16.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b788d7c2e87c48e9ddc65a7052b8e2bf4aa4808ab60b27bed55f24fde5f67089
BLAKE2b-256 checksum
How to use checksums
9686cbd6cd6aa45be45b813212d963bc7adb6981e3b394e89bb8470066ab6b8f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.3

Security for fewsats 0.0.22

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page