Metadata-Version: 2.4
Name: fetcherpay
Version: 1.0.0
Summary: FetcherPay Python SDK
Home-page: https://github.com/fetcherpay/fetcherpay-python
Author: FetcherPay
Author-email: support@fetcherpay.com
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Requires-Python: >=3.8
Description-Content-Type: text/markdown
Requires-Dist: requests>=2.25.0
Requires-Dist: typing-extensions>=4.0.0
Provides-Extra: dev
Requires-Dist: pytest>=6.0; extra == "dev"
Requires-Dist: pytest-cov>=2.0; extra == "dev"
Requires-Dist: black>=21.0; extra == "dev"
Requires-Dist: isort>=5.0; extra == "dev"
Requires-Dist: mypy>=0.910; extra == "dev"
Dynamic: author
Dynamic: author-email
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: home-page
Dynamic: provides-extra
Dynamic: requires-dist
Dynamic: requires-python
Dynamic: summary

# FetcherPay Python SDK

Official Python SDK for the FetcherPay API — One API. Every Rail.

## Installation

```bash
pip install fetcherpay
```

## Quick Start

```python
from fetcherpay import FetcherPay

client = FetcherPay(
    api_key='fp_test_your_key',
    environment='sandbox'  # or 'production'
)

# Create a payment
payment = client.payments.create(
    amount=10000,  # $100.00 in cents
    currency='USD',
    source={'payment_method_id': 'pm_123'},
    destination={'payment_method_id': 'pm_456'},
    rail='auto'  # Auto-select optimal rail
)

print(payment['id'], payment['status'])
```

## Configuration

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `api_key` | str | required | Your FetcherPay API key |
| `environment` | str | 'sandbox' | 'sandbox' or 'production' |
| `base_url` | str | auto | Override base URL |
| `timeout` | int | 30 | Request timeout (seconds) |

## API Reference

### Payments

```python
# Create payment
payment = client.payments.create(
    amount=10000,
    source={'payment_method_id': 'pm_123'},
    destination={'payment_method_id': 'pm_456'},
    idempotency_key='unique-key'
)

# Retrieve payment
payment = client.payments.retrieve('pay_xxx')

# List payments
payments = client.payments.list(limit=10)

# Cancel payment
client.payments.cancel('pay_xxx', reason='Customer request')

# Refund payment
client.payments.refund('pay_xxx', amount=5000, reason='Partial refund')
```

### Ledger

```python
# List accounts
accounts = client.ledger.list_accounts()

# Get account balance
account = client.ledger.retrieve_account('la_xxx')
print(account['balance']['available'])

# List entries
entries = client.ledger.list_entries(account_id='la_xxx')
```

### Payment Methods

```python
# Create bank account
pm = client.payment_methods.create(
    type='bank_account',
    bank_account={
        'account_number': '000123456789',
        'routing_number': '011000015',
        'account_type': 'checking'
    }
)

# List payment methods
methods = client.payment_methods.list()
```

### Webhooks

```python
# Create webhook endpoint
webhook = client.webhooks.create(
    url='https://your-app.com/webhooks',
    events=['payment.settled', 'payment.failed']
)

# Verify webhook signature
is_valid = client.verify_webhook_signature(
    payload,
    signature,  # from X-FetcherPay-Signature header
    webhook['secret']
)
```

## Error Handling

```python
from fetcherpay import (
    FetcherPayError,
    AuthenticationError,
    ValidationError,
    NotFoundError
)

try:
    client.payments.create(...)
except AuthenticationError:
    print('Invalid API key')
except ValidationError as e:
    print(f'Validation failed: {e.param}')
except FetcherPayError as e:
    print(f'API error: {e.type} ({e.status_code})')
```

## Webhook Verification

```python
import json

# In your webhook handler
def handle_webhook(request):
    payload = request.body
    signature = request.headers.get('X-FetcherPay-Signature')
    secret = 'whsec_your_webhook_secret'
    
    if client.verify_webhook_signature(payload, signature, secret):
        event = json.loads(payload)
        if event['type'] == 'payment.settled':
            handle_payment_settled(event['data'])
        return 'OK', 200
    else:
        return 'Invalid signature', 401
```

## License

MIT
