Skip to content

Commit 395985a

Browse files
deploy: 6f5eecf
0 parents  commit 395985a

26 files changed

+9063
-0
lines changed

.nojekyll

Whitespace-only changes.

core.html

Lines changed: 1691 additions & 0 deletions
Large diffs are not rendered by default.

core.html.md

Lines changed: 1183 additions & 0 deletions
Large diffs are not rendered by default.

index.html

Lines changed: 839 additions & 0 deletions
Large diffs are not rendered by default.

index.html.md

Lines changed: 277 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,277 @@
1+
# fewsats
2+
3+
4+
<!-- WARNING: THIS FILE WAS AUTOGENERATED! DO NOT EDIT! -->
5+
6+
This library enables AI agents to handle real-world payments
7+
autonomously. It provides a simple interface for AI systems to manage
8+
payment methods, process transactions, and interact with L402 paywalls.
9+
10+
The library provides two main interfaces: 1. Direct payment handling
11+
through the Python SDK 2. AI-native tools through `as_tools()` for
12+
autonomous agents
13+
14+
## Install
15+
16+
Install latest from [pypi](https://pypi.org/project/fewsats/)
17+
18+
``` sh
19+
$ pip install fewsats
20+
```
21+
22+
## Getting Started
23+
24+
The library provides a
25+
[`Fewsats`](https://Fewsats.github.io/fewsats-python/core.html#fewsats)
26+
class to handle payments. You can use handle them manually or use the
27+
`as_tools()` method to create tools for autonomous agents.
28+
29+
### Making Payments
30+
31+
Obtain information about your account and perform payments:
32+
33+
``` python
34+
from fewsats.core import *
35+
```
36+
37+
``` python
38+
fs = Fewsats()
39+
import os
40+
fs = Fewsats(api_key=os.getenv("FEWSATS_LOCAL_API_KEY"), base_url='http://localhost:8000')
41+
42+
fs.payment_methods().json(), fs.balance().json(), fs.me().json()
43+
```
44+
45+
([{'id': 1,
46+
'last4': '4242',
47+
'brand': 'visa',
48+
'exp_month': 12,
49+
'exp_year': 2034,
50+
'is_default': False},
51+
{'id': 4,
52+
'last4': '4242',
53+
'brand': 'Visa',
54+
'exp_month': 12,
55+
'exp_year': 2034,
56+
'is_default': True}],
57+
[{'id': 1, 'balance': 4399, 'currency': 'usd'}],
58+
{'name': 'Pol',
59+
'last_name': 'Alvarez Vecino',
60+
'email': 'pol@fewsats.com',
61+
'id': 1,
62+
'created_at': '2024-08-20T16:13:01.255Z',
63+
'webhook_secret': 'whsec_Kgsdk1xApAOSBcpXViSMNp_MMCRwfNWngoxqotZMHUw',
64+
'test_webhook_secret': 'whsec_Nk997GrUMG9rwEmlef7jlMCMfz2th3chUHtRBkcScIU',
65+
'webhooks': [{'id': 4, 'url': 'https://example.com', 'is_test': False}],
66+
'test_webhooks': []})
67+
68+
The `pay` method uses the information returned by a [L402
69+
Protocol](https://github.com/l402-protocol/l402?tab=readme-ov-file#402-response-format)
70+
`402 Payment Required` response to submit a payment. The L402 flow is
71+
handled by the backend. By default it will also choose the most
72+
convenient payment method, and assume you want to pay the first offer if
73+
multiple are available.
74+
75+
``` python
76+
# Example offer from stock.l402.org
77+
l402_offer = {
78+
"offers":[
79+
{
80+
"amount":1,
81+
"currency":"USD",
82+
"description":"Purchase 1 credit for API access",
83+
"id":"offer_c668e0c0",
84+
"payment_methods":[
85+
"lightning"
86+
],
87+
"title":"1 Credit Package",
88+
}
89+
],
90+
"payment_context_token":"edb53dec-28f5-4cbb-924a-20e9003c20e1",
91+
"payment_request_url":"https://stock.l402.org/l402/payment-request",
92+
"version":"0.2.2"
93+
}
94+
```
95+
96+
``` python
97+
fs.pay_offer(l402_offer['offers'][0]['id'], l402_offer).json()
98+
```
99+
100+
{'id': '87aeda24-9830-49b7-8526-c9d90fd04803',
101+
'created_at': '2025-04-23T12:21:39.922Z',
102+
'status': 'success',
103+
'payment_method': 'lightning'}
104+
105+
Fewsats also supports paying for resources like a lightning invoice
106+
directly. For example:
107+
108+
fs.pay_lightning(invoice='lnbc100n1pn6fsyspp5g2f6hdqxc76wxccq2cd4wekck0nxfucfyvzkvy9fmxezlf3hcl6qdqqcqzpgxqyz5vqrzjqwghf7zxvfkxq5a6sr65g0gdkv768p83mhsnt0msszapamzx2qvuxqqqqz99gpz55yqqqqqqqqqqqqqq9qrzjq25carzepgd4vqsyn44jrk85ezrpju92xyrk9apw4cdjh6yrwt5jgqqqqz99gpz55yqqqqqqqqqqqqqq9qsp5yzvs9czquyf8mjgwf465k0a7g4vh7jqv2cpza3lkygnllxnzk2wq9qxpqysgqnkmhmw05q6qc8urah004jtnkuztpazgg49m3g2wfamexr0m0ayrhla2ephnsm0xan3pweqc3hexeqx2mkfr8d3afwx6rds2r2znf4vgq7new3k',
109+
amount=1, currency='USD', description='Purchase 1 cent for API access')
110+
<Response [200 OK]>
111+
112+
The lightning invoice already contains a payment amount, but the method
113+
requires you to specify the amount you are expecting to pay in cents.
114+
This is done for accounting purposes and convenience, but the amount
115+
paid will be the sats in the invoice.
116+
117+
### Getting Paid
118+
119+
Fewsats also provides methods for receiving payments. You can create
120+
offers for receiving payments as follows.
121+
122+
``` python
123+
# Create offers for receiving payments
124+
offers_data = [{
125+
"id": "offer_example",
126+
"amount": 1,
127+
"currency": "USD",
128+
"description": "Receive payment for your service",
129+
"title": "1 Credit Package",
130+
"payment_methods": ["lightning", "stripe"]
131+
}]
132+
r = fs.create_offers(offers_data)
133+
offers = r.json()
134+
offers
135+
```
136+
137+
{'offers': [{'id': 'offer_example',
138+
'amount': 1,
139+
'currency': 'USD',
140+
'description': 'Receive payment for your service',
141+
'title': '1 Credit Package',
142+
'payment_methods': ['lightning', 'stripe'],
143+
'type': 'one-off'}],
144+
'payment_context_token': '095259cb-e50a-4a4e-a31b-c9da9ef592de',
145+
'payment_request_url': 'http://localhost:8000/v0/l402/payment-request',
146+
'version': '0.2.2'}
147+
148+
You can check if an offer has been paid using the payment context token
149+
as follows.
150+
151+
``` python
152+
fs.get_payment_status(payment_context_token=offers["payment_context_token"]).json()
153+
```
154+
155+
{'payment_context_token': '095259cb-e50a-4a4e-a31b-c9da9ef592de',
156+
'status': 'pending',
157+
'offer_id': None,
158+
'paid_at': None,
159+
'amount': None,
160+
'currency': None}
161+
162+
If you prefer to be notified whenever an offer is paid, you can add a
163+
webhook as follows, and we will call it whenever a payment is made.
164+
165+
``` python
166+
r = fs.add_webhook(webhook_url="https://example.com/webhook")
167+
r.json()
168+
```
169+
170+
{'id': 8, 'url': 'https://example.com/webhook', 'is_test': False}
171+
172+
### AI Agent Integration
173+
174+
We will show how to enable your AI assistant to handle payments using
175+
[Claudette](https://claudette.answer.ai), Answer.ai convenient wrapper
176+
for Claude. You’ll need to export your `ANTHROPIC_API_KEY` as env
177+
variable for this to work.
178+
179+
``` python
180+
from claudette import Chat, models
181+
```
182+
183+
``` python
184+
import os
185+
# os.environ['ANTHROPIC_LOG'] = 'debug'
186+
model = models[1]; model
187+
```
188+
189+
'claude-3-5-sonnet-20240620'
190+
191+
To print every HTTP request and response in full, uncomment the above
192+
line.
193+
194+
``` python
195+
fs.balance()
196+
```
197+
198+
<Response [200 OK]>
199+
200+
``` python
201+
fs.as_tools()
202+
```
203+
204+
[<bound method Fewsats.me of <fewsats.core.Fewsats object>>,
205+
<bound method Fewsats.balance of <fewsats.core.Fewsats object>>,
206+
<bound method Fewsats.payment_methods of <fewsats.core.Fewsats object>>,
207+
<bound method Fewsats.pay_offer_str of <fewsats.core.Fewsats object>>,
208+
<bound method Fewsats.payment_info of <fewsats.core.Fewsats object>>]
209+
210+
``` python
211+
fs.me().json()
212+
```
213+
214+
{'name': 'Pol',
215+
'last_name': 'Alvarez Vecino',
216+
'email': 'pol@fewsats.com',
217+
'id': 1,
218+
'created_at': '2024-08-20T16:13:01.255Z',
219+
'webhook_secret': 'whsec_Kgsdk1xApAOSBcpXViSMNp_MMCRwfNWngoxqotZMHUw',
220+
'test_webhook_secret': 'whsec_Nk997GrUMG9rwEmlef7jlMCMfz2th3chUHtRBkcScIU',
221+
'webhooks': [{'id': 4, 'url': 'https://example.com', 'is_test': False},
222+
{'id': 8, 'url': 'https://example.com/webhook', 'is_test': False}],
223+
'test_webhooks': []}
224+
225+
``` python
226+
chat = Chat(model, sp='You are a helpful assistant that can pay offers.', tools=fs.as_tools())
227+
pr = f"Can you check my details and balance?"
228+
r = chat.toolloop(pr, trace_func=print)
229+
r
230+
```
231+
232+
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)
233+
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)
234+
235+
I’ve successfully retrieved your user information and balance. However,
236+
it seems that the specific details aren’t directly visible in the
237+
function results. This is likely for security reasons.
238+
239+
What I can tell you is that both requests were successful, as indicated
240+
by the \[200 OK\] responses. This means that your account is active and
241+
accessible.
242+
243+
If you need more specific information about your account details or
244+
balance, you might need to log into your account directly through the
245+
official platform or app. They may have additional security measures in
246+
place to protect your sensitive information.
247+
248+
Is there anything else you’d like me to check or any other way I can
249+
assist you with your account?
250+
251+
<details>
252+
253+
- id: `msg_01P6Cf6xpjqDwD12Xo1GSJF6`
254+
- content:
255+
`[{'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'}]`
256+
- model: `claude-3-5-sonnet-20240620`
257+
- role: `assistant`
258+
- stop_reason: `end_turn`
259+
- stop_sequence: `None`
260+
- type: `message`
261+
- usage:
262+
`{'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 823, 'output_tokens': 140}`
263+
264+
</details>
265+
266+
``` python
267+
chat = Chat(model, sp='You are a helpful assistant that can pay offers.', tools=fs.as_tools())
268+
pr = f"Could you pay the cheapest offer using lightning {l402_offer}?"
269+
r = chat.toolloop(pr, trace_func=print)
270+
r
271+
```
272+
273+
``` python
274+
fs.balance()
275+
```
276+
277+
[{'id': 15, 'balance': 5962, 'currency': 'usd'}]

robots.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Sitemap: https://Fewsats.github.io/fewsats-python/sitemap.xml

0 commit comments

Comments
 (0)