Initial Python SDK release v1.0.0
This commit is contained in:
1
fetcherpay/api/__init__.py
Normal file
1
fetcherpay/api/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
# API modules
|
||||
53
fetcherpay/api/ledger.py
Normal file
53
fetcherpay/api/ledger.py
Normal file
@@ -0,0 +1,53 @@
|
||||
"""
|
||||
Ledger API
|
||||
"""
|
||||
|
||||
from typing import Optional
|
||||
|
||||
|
||||
class LedgerAPI:
|
||||
"""Ledger API client"""
|
||||
|
||||
def __init__(self, client):
|
||||
self.client = client
|
||||
|
||||
def list_accounts(
|
||||
self,
|
||||
limit: int = 25,
|
||||
cursor: Optional[str] = None,
|
||||
type: Optional[str] = None
|
||||
) -> dict:
|
||||
"""List ledger accounts"""
|
||||
params = {'limit': limit}
|
||||
if cursor:
|
||||
params['cursor'] = cursor
|
||||
if type:
|
||||
params['type'] = type
|
||||
|
||||
return self.client._request('GET', '/ledger/accounts', params=params)
|
||||
|
||||
def retrieve_account(self, account_id: str) -> dict:
|
||||
"""Retrieve a ledger account"""
|
||||
return self.client._request('GET', f'/ledger/accounts/{account_id}')
|
||||
|
||||
def list_entries(
|
||||
self,
|
||||
limit: int = 25,
|
||||
cursor: Optional[str] = None,
|
||||
account_id: Optional[str] = None,
|
||||
payment_id: Optional[str] = None
|
||||
) -> dict:
|
||||
"""List ledger entries"""
|
||||
params = {'limit': limit}
|
||||
if cursor:
|
||||
params['cursor'] = cursor
|
||||
if account_id:
|
||||
params['account_id'] = account_id
|
||||
if payment_id:
|
||||
params['payment_id'] = payment_id
|
||||
|
||||
return self.client._request('GET', '/ledger/entries', params=params)
|
||||
|
||||
def retrieve_entry(self, entry_id: str) -> dict:
|
||||
"""Retrieve a ledger entry"""
|
||||
return self.client._request('GET', f'/ledger/entries/{entry_id}')
|
||||
73
fetcherpay/api/payment_methods.py
Normal file
73
fetcherpay/api/payment_methods.py
Normal file
@@ -0,0 +1,73 @@
|
||||
"""
|
||||
Payment Methods API
|
||||
"""
|
||||
|
||||
from typing import Optional, Dict, Any
|
||||
|
||||
|
||||
class PaymentMethodsAPI:
|
||||
"""Payment Methods API client"""
|
||||
|
||||
def __init__(self, client):
|
||||
self.client = client
|
||||
|
||||
def create(
|
||||
self,
|
||||
type: str,
|
||||
bank_account: Optional[Dict[str, Any]] = None,
|
||||
card: Optional[Dict[str, Any]] = None,
|
||||
usdc_wallet: Optional[Dict[str, Any]] = None,
|
||||
metadata: Optional[Dict[str, Any]] = None,
|
||||
idempotency_key: Optional[str] = None
|
||||
) -> dict:
|
||||
"""
|
||||
Create a payment method
|
||||
|
||||
Args:
|
||||
type: 'bank_account', 'card', or 'usdc_wallet'
|
||||
bank_account: Bank account details
|
||||
card: Card details
|
||||
usdc_wallet: USDC wallet details
|
||||
metadata: Optional metadata
|
||||
idempotency_key: Idempotency key
|
||||
"""
|
||||
data = {'type': type}
|
||||
|
||||
if bank_account:
|
||||
data['bank_account'] = bank_account
|
||||
if card:
|
||||
data['card'] = card
|
||||
if usdc_wallet:
|
||||
data['usdc_wallet'] = usdc_wallet
|
||||
if metadata:
|
||||
data['metadata'] = metadata
|
||||
|
||||
return self.client._request(
|
||||
'POST',
|
||||
'/payment-methods',
|
||||
json=data,
|
||||
idempotency_key=idempotency_key
|
||||
)
|
||||
|
||||
def retrieve(self, payment_method_id: str) -> dict:
|
||||
"""Retrieve a payment method"""
|
||||
return self.client._request('GET', f'/payment-methods/{payment_method_id}')
|
||||
|
||||
def list(
|
||||
self,
|
||||
limit: int = 25,
|
||||
cursor: Optional[str] = None,
|
||||
type: Optional[str] = None
|
||||
) -> dict:
|
||||
"""List payment methods"""
|
||||
params = {'limit': limit}
|
||||
if cursor:
|
||||
params['cursor'] = cursor
|
||||
if type:
|
||||
params['type'] = type
|
||||
|
||||
return self.client._request('GET', '/payment-methods', params=params)
|
||||
|
||||
def delete(self, payment_method_id: str) -> None:
|
||||
"""Delete a payment method"""
|
||||
self.client._request('DELETE', f'/payment-methods/{payment_method_id}')
|
||||
133
fetcherpay/api/payments.py
Normal file
133
fetcherpay/api/payments.py
Normal file
@@ -0,0 +1,133 @@
|
||||
"""
|
||||
Payments API
|
||||
"""
|
||||
|
||||
from typing import Optional, Dict, Any, List
|
||||
|
||||
|
||||
class PaymentsAPI:
|
||||
"""Payments API client"""
|
||||
|
||||
def __init__(self, client):
|
||||
self.client = client
|
||||
|
||||
def create(
|
||||
self,
|
||||
amount: int,
|
||||
source: Dict[str, str],
|
||||
destination: Dict[str, str],
|
||||
currency: str = 'USD',
|
||||
rail: str = 'auto',
|
||||
description: Optional[str] = None,
|
||||
metadata: Optional[Dict[str, Any]] = None,
|
||||
idempotency_key: Optional[str] = None
|
||||
) -> Dict[str, Any]:
|
||||
"""
|
||||
Create a new payment
|
||||
|
||||
Args:
|
||||
amount: Amount in cents (e.g., 10000 for $100.00)
|
||||
source: Payment source with payment_method_id
|
||||
destination: Payment destination with payment_method_id
|
||||
currency: Currency code (default: USD)
|
||||
rail: Payment rail (auto, ach, rtp, card, crypto)
|
||||
description: Optional payment description
|
||||
metadata: Optional metadata dictionary
|
||||
idempotency_key: Optional idempotency key
|
||||
|
||||
Returns:
|
||||
Payment object
|
||||
"""
|
||||
data = {
|
||||
'amount': amount,
|
||||
'currency': currency,
|
||||
'rail': rail,
|
||||
'source': source,
|
||||
'destination': destination,
|
||||
}
|
||||
|
||||
if description:
|
||||
data['description'] = description
|
||||
if metadata:
|
||||
data['metadata'] = metadata
|
||||
|
||||
return self.client._request(
|
||||
'POST',
|
||||
'/payments',
|
||||
json=data,
|
||||
idempotency_key=idempotency_key
|
||||
)
|
||||
|
||||
def retrieve(self, payment_id: str) -> Dict[str, Any]:
|
||||
"""Retrieve a payment by ID"""
|
||||
return self.client._request('GET', f'/payments/{payment_id}')
|
||||
|
||||
def list(
|
||||
self,
|
||||
limit: int = 25,
|
||||
cursor: Optional[str] = None,
|
||||
status: Optional[str] = None,
|
||||
rail: Optional[str] = None
|
||||
) -> Dict[str, Any]:
|
||||
"""
|
||||
List payments
|
||||
|
||||
Args:
|
||||
limit: Number of results (1-100)
|
||||
cursor: Pagination cursor
|
||||
status: Filter by status
|
||||
rail: Filter by rail
|
||||
"""
|
||||
params = {'limit': limit}
|
||||
if cursor:
|
||||
params['cursor'] = cursor
|
||||
if status:
|
||||
params['status'] = status
|
||||
if rail:
|
||||
params['rail'] = rail
|
||||
|
||||
return self.client._request('GET', '/payments', params=params)
|
||||
|
||||
def cancel(
|
||||
self,
|
||||
payment_id: str,
|
||||
reason: Optional[str] = None,
|
||||
idempotency_key: Optional[str] = None
|
||||
) -> Dict[str, Any]:
|
||||
"""Cancel a pending payment"""
|
||||
data = {'reason': reason} if reason else {}
|
||||
return self.client._request(
|
||||
'POST',
|
||||
f'/payments/{payment_id}/cancel',
|
||||
json=data,
|
||||
idempotency_key=idempotency_key
|
||||
)
|
||||
|
||||
def refund(
|
||||
self,
|
||||
payment_id: str,
|
||||
amount: Optional[int] = None,
|
||||
reason: Optional[str] = None,
|
||||
idempotency_key: Optional[str] = None
|
||||
) -> Dict[str, Any]:
|
||||
"""
|
||||
Refund a settled payment
|
||||
|
||||
Args:
|
||||
payment_id: Payment ID to refund
|
||||
amount: Amount to refund (omit for full refund)
|
||||
reason: Refund reason
|
||||
idempotency_key: Idempotency key
|
||||
"""
|
||||
data = {}
|
||||
if amount:
|
||||
data['amount'] = amount
|
||||
if reason:
|
||||
data['reason'] = reason
|
||||
|
||||
return self.client._request(
|
||||
'POST',
|
||||
f'/payments/{payment_id}/refund',
|
||||
json=data,
|
||||
idempotency_key=idempotency_key
|
||||
)
|
||||
80
fetcherpay/api/webhooks.py
Normal file
80
fetcherpay/api/webhooks.py
Normal file
@@ -0,0 +1,80 @@
|
||||
"""
|
||||
Webhooks API
|
||||
"""
|
||||
|
||||
from typing import Optional, List, Dict, Any
|
||||
|
||||
|
||||
class WebhooksAPI:
|
||||
"""Webhooks API client"""
|
||||
|
||||
def __init__(self, client):
|
||||
self.client = client
|
||||
|
||||
def create(
|
||||
self,
|
||||
url: str,
|
||||
events: Optional[List[str]] = None,
|
||||
metadata: Optional[Dict[str, Any]] = None,
|
||||
idempotency_key: Optional[str] = None
|
||||
) -> dict:
|
||||
"""
|
||||
Create a webhook endpoint
|
||||
|
||||
Args:
|
||||
url: Endpoint URL
|
||||
events: List of events to subscribe to
|
||||
metadata: Optional metadata
|
||||
idempotency_key: Idempotency key
|
||||
"""
|
||||
data = {'url': url}
|
||||
|
||||
if events:
|
||||
data['events'] = events
|
||||
if metadata:
|
||||
data['metadata'] = metadata
|
||||
|
||||
return self.client._request(
|
||||
'POST',
|
||||
'/webhooks',
|
||||
json=data,
|
||||
idempotency_key=idempotency_key
|
||||
)
|
||||
|
||||
def retrieve(self, webhook_id: str) -> dict:
|
||||
"""Retrieve a webhook endpoint"""
|
||||
return self.client._request('GET', f'/webhooks/{webhook_id}')
|
||||
|
||||
def list(
|
||||
self,
|
||||
limit: int = 25,
|
||||
cursor: Optional[str] = None
|
||||
) -> dict:
|
||||
"""List webhook endpoints"""
|
||||
params = {'limit': limit}
|
||||
if cursor:
|
||||
params['cursor'] = cursor
|
||||
|
||||
return self.client._request('GET', '/webhooks', params=params)
|
||||
|
||||
def update(
|
||||
self,
|
||||
webhook_id: str,
|
||||
url: Optional[str] = None,
|
||||
events: Optional[List[str]] = None,
|
||||
metadata: Optional[Dict[str, Any]] = None
|
||||
) -> dict:
|
||||
"""Update a webhook endpoint"""
|
||||
data = {}
|
||||
if url:
|
||||
data['url'] = url
|
||||
if events:
|
||||
data['events'] = events
|
||||
if metadata:
|
||||
data['metadata'] = metadata
|
||||
|
||||
return self.client._request('PUT', f'/webhooks/{webhook_id}', json=data)
|
||||
|
||||
def delete(self, webhook_id: str) -> None:
|
||||
"""Delete a webhook endpoint"""
|
||||
self.client._request('DELETE', f'/webhooks/{webhook_id}')
|
||||
Reference in New Issue
Block a user