Initial Python SDK release v1.0.0
This commit is contained in:
51
fetcherpay/__init__.py
Normal file
51
fetcherpay/__init__.py
Normal file
@@ -0,0 +1,51 @@
|
||||
"""
|
||||
FetcherPay Python SDK
|
||||
One API. Every Rail.
|
||||
|
||||
Example:
|
||||
>>> from fetcherpay import FetcherPay
|
||||
>>>
|
||||
>>> client = FetcherPay(
|
||||
... api_key='fp_test_your_key',
|
||||
... environment='sandbox'
|
||||
... )
|
||||
>>>
|
||||
>>> payment = client.payments.create(
|
||||
... amount=10000,
|
||||
... currency='USD',
|
||||
... source={'payment_method_id': 'pm_123'},
|
||||
... destination={'payment_method_id': 'pm_456'}
|
||||
... )
|
||||
>>> print(payment.id)
|
||||
"""
|
||||
|
||||
from .client import FetcherPay
|
||||
from .exceptions import (
|
||||
FetcherPayError,
|
||||
AuthenticationError,
|
||||
ValidationError,
|
||||
NotFoundError,
|
||||
)
|
||||
from .types import (
|
||||
Payment,
|
||||
PaymentMethod,
|
||||
LedgerAccount,
|
||||
LedgerEntry,
|
||||
WebhookEndpoint,
|
||||
CreatePaymentRequest,
|
||||
)
|
||||
|
||||
__version__ = '1.0.0'
|
||||
__all__ = [
|
||||
'FetcherPay',
|
||||
'FetcherPayError',
|
||||
'AuthenticationError',
|
||||
'ValidationError',
|
||||
'NotFoundError',
|
||||
'Payment',
|
||||
'PaymentMethod',
|
||||
'LedgerAccount',
|
||||
'LedgerEntry',
|
||||
'WebhookEndpoint',
|
||||
'CreatePaymentRequest',
|
||||
]
|
||||
BIN
fetcherpay/__pycache__/__init__.cpython-311.pyc
Normal file
BIN
fetcherpay/__pycache__/__init__.cpython-311.pyc
Normal file
Binary file not shown.
BIN
fetcherpay/__pycache__/client.cpython-311.pyc
Normal file
BIN
fetcherpay/__pycache__/client.cpython-311.pyc
Normal file
Binary file not shown.
BIN
fetcherpay/__pycache__/exceptions.cpython-311.pyc
Normal file
BIN
fetcherpay/__pycache__/exceptions.cpython-311.pyc
Normal file
Binary file not shown.
BIN
fetcherpay/__pycache__/types.cpython-311.pyc
Normal file
BIN
fetcherpay/__pycache__/types.cpython-311.pyc
Normal file
Binary file not shown.
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}')
|
||||
153
fetcherpay/client.py
Normal file
153
fetcherpay/client.py
Normal file
@@ -0,0 +1,153 @@
|
||||
"""
|
||||
FetcherPay API Client
|
||||
"""
|
||||
|
||||
import hmac
|
||||
import hashlib
|
||||
from typing import Optional
|
||||
import requests
|
||||
from requests.adapters import HTTPAdapter
|
||||
from urllib.parse import urljoin
|
||||
|
||||
from .exceptions import (
|
||||
FetcherPayError,
|
||||
AuthenticationError,
|
||||
ValidationError,
|
||||
NotFoundError,
|
||||
IdempotencyError,
|
||||
)
|
||||
from .api.payments import PaymentsAPI
|
||||
from .api.ledger import LedgerAPI
|
||||
from .api.payment_methods import PaymentMethodsAPI
|
||||
from .api.webhooks import WebhooksAPI
|
||||
|
||||
|
||||
class FetcherPay:
|
||||
"""
|
||||
Main FetcherPay client
|
||||
|
||||
Args:
|
||||
api_key: Your FetcherPay API key
|
||||
environment: 'sandbox' or 'production'
|
||||
base_url: Optional custom base URL
|
||||
timeout: Request timeout in seconds (default: 30)
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
api_key: str,
|
||||
environment: str = 'sandbox',
|
||||
base_url: Optional[str] = None,
|
||||
timeout: int = 30
|
||||
):
|
||||
self.api_key = api_key
|
||||
self.environment = environment
|
||||
self.timeout = timeout
|
||||
|
||||
if base_url:
|
||||
self.base_url = base_url
|
||||
elif environment == 'production':
|
||||
self.base_url = 'https://api.fetcherpay.com/v1'
|
||||
else:
|
||||
self.base_url = 'https://sandbox.fetcherpay.com/v1'
|
||||
|
||||
# Create session with retries
|
||||
self.session = requests.Session()
|
||||
self.session.headers.update({
|
||||
'Authorization': f'Bearer {api_key}',
|
||||
'Content-Type': 'application/json',
|
||||
})
|
||||
|
||||
# Initialize API modules
|
||||
self.payments = PaymentsAPI(self)
|
||||
self.ledger = LedgerAPI(self)
|
||||
self.payment_methods = PaymentMethodsAPI(self)
|
||||
self.webhooks = WebhooksAPI(self)
|
||||
|
||||
def _request(
|
||||
self,
|
||||
method: str,
|
||||
path: str,
|
||||
params: Optional[dict] = None,
|
||||
json: Optional[dict] = None,
|
||||
headers: Optional[dict] = None,
|
||||
idempotency_key: Optional[str] = None
|
||||
) -> dict:
|
||||
"""Make an HTTP request"""
|
||||
url = urljoin(self.base_url, path)
|
||||
|
||||
request_headers = {}
|
||||
if headers:
|
||||
request_headers.update(headers)
|
||||
if idempotency_key:
|
||||
request_headers['Idempotency-Key'] = idempotency_key
|
||||
|
||||
try:
|
||||
response = self.session.request(
|
||||
method=method,
|
||||
url=url,
|
||||
params=params,
|
||||
json=json,
|
||||
headers=request_headers,
|
||||
timeout=self.timeout
|
||||
)
|
||||
|
||||
# Handle errors
|
||||
if response.status_code >= 400:
|
||||
self._handle_error(response)
|
||||
|
||||
return response.json() if response.content else {}
|
||||
|
||||
except requests.exceptions.Timeout:
|
||||
raise FetcherPayError('Request timeout', 'timeout_error')
|
||||
except requests.exceptions.ConnectionError:
|
||||
raise FetcherPayError('Connection error', 'connection_error')
|
||||
|
||||
def _handle_error(self, response):
|
||||
"""Handle API errors"""
|
||||
try:
|
||||
data = response.json()
|
||||
error = data.get('error', {})
|
||||
except:
|
||||
error = {}
|
||||
|
||||
message = error.get('message', 'An error occurred')
|
||||
error_type = error.get('type', 'api_error')
|
||||
param = error.get('param')
|
||||
code = error.get('code')
|
||||
|
||||
if response.status_code == 401:
|
||||
raise AuthenticationError(message)
|
||||
elif response.status_code == 404:
|
||||
raise NotFoundError(message)
|
||||
elif response.status_code == 422:
|
||||
raise ValidationError(message, param)
|
||||
elif response.status_code == 409:
|
||||
raise IdempotencyError(message)
|
||||
else:
|
||||
raise FetcherPayError(message, error_type, response.status_code, param, code)
|
||||
|
||||
def verify_webhook_signature(
|
||||
self,
|
||||
payload: str,
|
||||
signature: str,
|
||||
secret: str
|
||||
) -> bool:
|
||||
"""
|
||||
Verify a webhook signature
|
||||
|
||||
Args:
|
||||
payload: The raw webhook payload string
|
||||
signature: The signature from X-FetcherPay-Signature header
|
||||
secret: Your webhook secret
|
||||
|
||||
Returns:
|
||||
True if signature is valid
|
||||
"""
|
||||
expected = hmac.new(
|
||||
secret.encode('utf-8'),
|
||||
payload.encode('utf-8'),
|
||||
hashlib.sha256
|
||||
).hexdigest()
|
||||
|
||||
return hmac.compare_digest(signature, expected)
|
||||
49
fetcherpay/exceptions.py
Normal file
49
fetcherpay/exceptions.py
Normal file
@@ -0,0 +1,49 @@
|
||||
"""
|
||||
FetcherPay SDK Exceptions
|
||||
"""
|
||||
|
||||
|
||||
class FetcherPayError(Exception):
|
||||
"""Base FetcherPay error"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
message: str,
|
||||
type: str = 'api_error',
|
||||
status_code: int = None,
|
||||
param: str = None,
|
||||
code: str = None
|
||||
):
|
||||
super().__init__(message)
|
||||
self.type = type
|
||||
self.status_code = status_code
|
||||
self.param = param
|
||||
self.code = code
|
||||
|
||||
|
||||
class AuthenticationError(FetcherPayError):
|
||||
"""Authentication failed"""
|
||||
|
||||
def __init__(self, message: str):
|
||||
super().__init__(message, 'authentication_error', 401)
|
||||
|
||||
|
||||
class ValidationError(FetcherPayError):
|
||||
"""Validation failed"""
|
||||
|
||||
def __init__(self, message: str, param: str = None):
|
||||
super().__init__(message, 'validation_error', 422, param)
|
||||
|
||||
|
||||
class NotFoundError(FetcherPayError):
|
||||
"""Resource not found"""
|
||||
|
||||
def __init__(self, message: str):
|
||||
super().__init__(message, 'not_found', 404)
|
||||
|
||||
|
||||
class IdempotencyError(FetcherPayError):
|
||||
"""Idempotency key conflict"""
|
||||
|
||||
def __init__(self, message: str):
|
||||
super().__init__(message, 'idempotency_error', 409)
|
||||
153
fetcherpay/types.py
Normal file
153
fetcherpay/types.py
Normal file
@@ -0,0 +1,153 @@
|
||||
"""
|
||||
FetcherPay SDK Types
|
||||
"""
|
||||
|
||||
from typing import Optional, Dict, Any, List
|
||||
from dataclasses import dataclass
|
||||
from enum import Enum
|
||||
|
||||
|
||||
class PaymentStatus(str, Enum):
|
||||
PENDING = 'pending'
|
||||
AUTHORIZED = 'authorized'
|
||||
PROCESSING = 'processing'
|
||||
SETTLED = 'settled'
|
||||
FAILED = 'failed'
|
||||
CANCELLED = 'cancelled'
|
||||
REFUNDED = 'refunded'
|
||||
PARTIALLY_REFUNDED = 'partially_refunded'
|
||||
|
||||
|
||||
class Rail(str, Enum):
|
||||
AUTO = 'auto'
|
||||
ACH = 'ach'
|
||||
RTP = 'rtp'
|
||||
CARD = 'card'
|
||||
CRYPTO = 'crypto'
|
||||
|
||||
|
||||
class AccountType(str, Enum):
|
||||
ASSET = 'asset'
|
||||
LIABILITY = 'liability'
|
||||
REVENUE = 'revenue'
|
||||
EXPENSE = 'expense'
|
||||
EQUITY = 'equity'
|
||||
|
||||
|
||||
@dataclass
|
||||
class Fee:
|
||||
amount: int
|
||||
rate: str
|
||||
|
||||
|
||||
@dataclass
|
||||
class TimelineEvent:
|
||||
status: str
|
||||
timestamp: str
|
||||
detail: str
|
||||
|
||||
|
||||
@dataclass
|
||||
class Refund:
|
||||
id: str
|
||||
payment_id: str
|
||||
amount: int
|
||||
reason: Optional[str]
|
||||
status: str
|
||||
created_at: str
|
||||
|
||||
|
||||
@dataclass
|
||||
class Payment:
|
||||
id: str
|
||||
object: str
|
||||
status: PaymentStatus
|
||||
amount: int
|
||||
currency: str
|
||||
rail: str
|
||||
rail_selected: str
|
||||
description: Optional[str]
|
||||
source: Dict[str, Any]
|
||||
destination: Dict[str, Any]
|
||||
fee: Optional[Fee]
|
||||
timeline: List[TimelineEvent]
|
||||
ledger_entry_ids: List[str]
|
||||
refunds: List[Refund]
|
||||
idempotency_key: Optional[str]
|
||||
metadata: Dict[str, Any]
|
||||
created_at: str
|
||||
updated_at: str
|
||||
|
||||
|
||||
@dataclass
|
||||
class PaymentMethod:
|
||||
id: str
|
||||
object: str
|
||||
type: str
|
||||
status: str
|
||||
bank_account: Optional[Dict[str, Any]]
|
||||
card: Optional[Dict[str, Any]]
|
||||
usdc_wallet: Optional[Dict[str, Any]]
|
||||
metadata: Dict[str, Any]
|
||||
created_at: str
|
||||
|
||||
|
||||
@dataclass
|
||||
class LedgerBalance:
|
||||
pending: int
|
||||
posted: int
|
||||
available: int
|
||||
|
||||
|
||||
@dataclass
|
||||
class LedgerAccount:
|
||||
id: str
|
||||
object: str
|
||||
name: str
|
||||
type: AccountType
|
||||
currency: str
|
||||
balance: LedgerBalance
|
||||
metadata: Dict[str, Any]
|
||||
created_at: str
|
||||
updated_at: str
|
||||
|
||||
|
||||
@dataclass
|
||||
class LedgerEntry:
|
||||
id: str
|
||||
object: str
|
||||
journal_id: str
|
||||
account_id: str
|
||||
payment_id: Optional[str]
|
||||
entry_type: str
|
||||
amount: int
|
||||
currency: str
|
||||
status: str
|
||||
description: Optional[str]
|
||||
metadata: Dict[str, Any]
|
||||
created_at: str
|
||||
|
||||
|
||||
@dataclass
|
||||
class WebhookEndpoint:
|
||||
id: str
|
||||
object: str
|
||||
url: str
|
||||
events: List[str]
|
||||
status: str
|
||||
secret: str
|
||||
metadata: Dict[str, Any]
|
||||
created_at: str
|
||||
|
||||
|
||||
@dataclass
|
||||
class ListResponse:
|
||||
data: List[Any]
|
||||
has_more: bool
|
||||
next_cursor: Optional[str]
|
||||
|
||||
|
||||
# Request types
|
||||
CreatePaymentRequest = Dict[str, Any]
|
||||
CreatePaymentMethodRequest = Dict[str, Any]
|
||||
CreateWebhookRequest = Dict[str, Any]
|
||||
Reference in New Issue
Block a user