|
| 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 | +fs.payment_methods().json(), fs.balance().json(), fs.me().json() |
| 42 | +``` |
| 43 | + |
| 44 | + ([{'id': 1, |
| 45 | + 'last4': '4242', |
| 46 | + 'brand': 'visa', |
| 47 | + 'exp_month': 12, |
| 48 | + 'exp_year': 2034, |
| 49 | + 'is_default': False}, |
| 50 | + {'id': 4, |
| 51 | + 'last4': '4242', |
| 52 | + 'brand': 'Visa', |
| 53 | + 'exp_month': 12, |
| 54 | + 'exp_year': 2034, |
| 55 | + 'is_default': True}], |
| 56 | + [{'id': 1, 'balance': 4464, 'currency': 'usd'}], |
| 57 | + {'name': 'Pol', |
| 58 | + 'last_name': 'Alvarez Vecino', |
| 59 | + 'email': 'pol@fewsats.com', |
| 60 | + 'billing_info': None, |
| 61 | + 'id': 1, |
| 62 | + 'created_at': '2024-08-20T16:13:01.255Z', |
| 63 | + 'webhook_url': 'https://example.com/webhook'}) |
| 64 | + |
| 65 | +The `pay` method uses the information returned by a [L402 |
| 66 | +Protocol](https://github.com/l402-protocol/l402?tab=readme-ov-file#402-response-format) |
| 67 | +`402 Payment Required` response to submit a payment. The L402 flow is |
| 68 | +handled by the backend. By default it will also choose the most |
| 69 | +convenient payment method, and assume you want to pay the first offer if |
| 70 | +multiple are available. |
| 71 | + |
| 72 | +``` python |
| 73 | +# Example offer from stock.l402.org |
| 74 | +l402_offer = { |
| 75 | + "offers":[ |
| 76 | + { |
| 77 | + "amount":1, |
| 78 | + "balance":1, |
| 79 | + "currency":"USD", |
| 80 | + "description":"Purchase 1 credit for API access", |
| 81 | + "offer_id":"offer_c668e0c0", |
| 82 | + "payment_methods":[ |
| 83 | + "lightning" |
| 84 | + ], |
| 85 | + "title":"1 Credit Package", |
| 86 | + "type":"top-up" |
| 87 | + } |
| 88 | + ], |
| 89 | + "payment_context_token":"edb53dec-28f5-4cbb-924a-20e9003c20e1", |
| 90 | + "payment_request_url":"https://stock.l402.org/l402/payment-request", |
| 91 | + "terms_url":"https://link-to-terms.com", |
| 92 | + "version":"0.2.1" |
| 93 | +} |
| 94 | +``` |
| 95 | + |
| 96 | +``` python |
| 97 | +fs.pay_offer(l402_offer).json() |
| 98 | +``` |
| 99 | + |
| 100 | + {'id': 121, |
| 101 | + 'created_at': '2025-02-10T11:04:48.083Z', |
| 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 | + "offer_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': [{'offer_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': 'a175fd73-cb68-4a22-8685-b236eff2f1a0', |
| 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': 'a175fd73-cb68-4a22-8685-b236eff2f1a0', |
| 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 set up a |
| 163 | +webhook as follows, and we will call it whenever a payment is made. |
| 164 | + |
| 165 | +``` python |
| 166 | +r = fs.set_webhook(webhook_url="https://example.com/webhook") |
| 167 | +r.json() |
| 168 | +``` |
| 169 | + |
| 170 | + {'name': 'Pol', |
| 171 | + 'last_name': 'Alvarez Vecino', |
| 172 | + 'email': 'pol@fewsats.com', |
| 173 | + 'billing_info': None, |
| 174 | + 'id': 1, |
| 175 | + 'created_at': '2024-08-20T16:13:01.255Z', |
| 176 | + 'webhook_url': 'https://example.com/webhook'} |
| 177 | + |
| 178 | +### AI Agent Integration |
| 179 | + |
| 180 | +We will show how to enable your AI assistant to handle payments using |
| 181 | +[Claudette](https://claudette.answer.ai), Answer.ai convenient wrapper |
| 182 | +for Claude. You’ll need to export your `ANTHROPIC_API_KEY` as env |
| 183 | +variable for this to work. |
| 184 | + |
| 185 | +``` python |
| 186 | +from claudette import Chat, models |
| 187 | +``` |
| 188 | + |
| 189 | +``` python |
| 190 | +import os |
| 191 | +# os.environ['ANTHROPIC_LOG'] = 'debug' |
| 192 | +model = models[1]; model |
| 193 | +``` |
| 194 | + |
| 195 | + 'claude-3-5-sonnet-20240620' |
| 196 | + |
| 197 | +To print every HTTP request and response in full, uncomment the above |
| 198 | +line. |
| 199 | + |
| 200 | +``` python |
| 201 | +fs.balance() |
| 202 | +``` |
| 203 | + |
| 204 | + [{'id': 15, 'balance': 5963, 'currency': 'usd'}] |
| 205 | + |
| 206 | +``` python |
| 207 | +chat = Chat(model, sp='You are a helpful assistant that can pay offers.', tools=fs.as_tools()) |
| 208 | +pr = f"Could you pay the cheapest offer using lightning {l402_offer}?" |
| 209 | +r = chat.toolloop(pr, trace_func=print) |
| 210 | +r |
| 211 | +``` |
| 212 | + |
| 213 | + Message(id='msg_01P2WhNQy4r7pTdqeLhv25uo', content=[TextBlock(text="Certainly! I can help you pay for the cheapest offer using Lightning. Based on the information you've provided, there's only one offer available, so we'll proceed with that one. Let's use the `pay` function to complete this transaction.\n\nFirst, let's organize the information we have:\n\n1. There's one offer for 1 credit at $0.01 (1 cent).\n2. The payment method is Lightning.\n3. We have a payment context token and a payment request URL.\n\nNow, let's call the `pay` function with the required parameters:", type='text'), ToolUseBlock(id='toolu_01KqP7nL9J48keGPJoPS2yGf', input={'purl': 'https://stock.l402.org/l402/payment-request', 'pct': 'edb53dec-28f5-4cbb-924a-20e9003c20e1', 'amount': 1, 'balance': 1, 'currency': 'USD', 'description': 'Purchase 1 credit for API access', 'offer_id': 'offer_c668e0c0', 'payment_methods': ['lightning'], 'title': '1 Credit Package', 'type': 'top-up'}, name='pay', type='tool_use')], model='claude-3-5-sonnet-20240620', role='assistant', stop_reason='tool_use', stop_sequence=None, type='message', usage=In: 1002; Out: 395; Cache create: 0; Cache read: 0; Total: 1397) |
| 214 | + Message(id='msg_01Tm57TAVcqN4Gh1dV7NdR4b', content=[TextBlock(text="Great news! The payment has been successfully processed. Here's a summary of the transaction:\n\n1. Payment Status: Success\n2. Amount Paid: 1 cent (USD)\n3. Payment Method: Lightning\n4. Title: 1 Credit Package\n5. Description: Purchase 1 credit for API access\n6. Type: Top-up\n7. Transaction ID: 253\n8. Created At: 2024-12-26T15:21:23.413Z\n\nThe payment has been completed successfully using the Lightning network. You should now have 1 credit added to your API access. Is there anything else you'd like to know about this transaction or any other assistance you need?", type='text')], model='claude-3-5-sonnet-20240620', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 1952; Out: 156; Cache create: 0; Cache read: 0; Total: 2108) |
| 215 | + |
| 216 | +Great news! The payment has been successfully processed. Here’s a |
| 217 | +summary of the transaction: |
| 218 | + |
| 219 | +1. Payment Status: Success |
| 220 | +2. Amount Paid: 1 cent (USD) |
| 221 | +3. Payment Method: Lightning |
| 222 | +4. Title: 1 Credit Package |
| 223 | +5. Description: Purchase 1 credit for API access |
| 224 | +6. Type: Top-up |
| 225 | +7. Transaction ID: 253 |
| 226 | +8. Created At: 2024-12-26T15:21:23.413Z |
| 227 | + |
| 228 | +The payment has been completed successfully using the Lightning network. |
| 229 | +You should now have 1 credit added to your API access. Is there anything |
| 230 | +else you’d like to know about this transaction or any other assistance |
| 231 | +you need? |
| 232 | + |
| 233 | +<details> |
| 234 | + |
| 235 | +- id: `msg_01Tm57TAVcqN4Gh1dV7NdR4b` |
| 236 | +- content: |
| 237 | + `[{'text': "Great news! The payment has been successfully processed. Here's a summary of the transaction:\n\n1. Payment Status: Success\n2. Amount Paid: 1 cent (USD)\n3. Payment Method: Lightning\n4. Title: 1 Credit Package\n5. Description: Purchase 1 credit for API access\n6. Type: Top-up\n7. Transaction ID: 253\n8. Created At: 2024-12-26T15:21:23.413Z\n\nThe payment has been completed successfully using the Lightning network. You should now have 1 credit added to your API access. Is there anything else you'd like to know about this transaction or any other assistance you need?", 'type': 'text'}]` |
| 238 | +- model: `claude-3-5-sonnet-20240620` |
| 239 | +- role: `assistant` |
| 240 | +- stop_reason: `end_turn` |
| 241 | +- stop_sequence: `None` |
| 242 | +- type: `message` |
| 243 | +- usage: |
| 244 | + `{'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 1952, 'output_tokens': 156}` |
| 245 | + |
| 246 | +</details> |
| 247 | + |
| 248 | +``` python |
| 249 | +fs.balance() |
| 250 | +``` |
| 251 | + |
| 252 | + [{'id': 15, 'balance': 5962, 'currency': 'usd'}] |
0 commit comments