Metadata-Version: 2.4
Name: fourbyfour
Version: 0.2.0
Summary: Official Fourbyfour SDK for Python
Project-URL: Homepage, https://github.com/occupymars/fourbyfour/tree/main/sdks/python#readme
Project-URL: Repository, https://github.com/occupymars/fourbyfour.git
Project-URL: Documentation, https://fourbyfour.dev/docs
Project-URL: Issues, https://github.com/occupymars/fourbyfour/issues
Author: Fourbyfour
License-Expression: MIT
Keywords: fourbyfour,hooks,notifications,sdk,stream
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Typing :: Typed
Requires-Python: >=3.9
Requires-Dist: httpx>=0.25.0
Provides-Extra: dev
Requires-Dist: mypy>=1.0; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.21; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Requires-Dist: ruff>=0.1; extra == 'dev'
Description-Content-Type: text/markdown

# fourbyfour

Official Python SDK for Fourbyfour - Revenue recovery for subscription businesses.

## Installation

```bash
pip install fourbyfour
```

## Quick Start

```python
import os
from fourbyfour import fbf

client = fbf(
    api_key=os.environ["FOURBYFOUR_API_KEY"],
    project_id=os.environ["FOURBYFOUR_PROJECT_ID"],
)

# Start a workflow when payment fails
client.start_workflow({
    "userId": "user_123",
    "intent": "PAYMENT_FAILED",
    "signals": {
        "amountCents": 9900,
        "reason": "card_expired",
    },
})

# Record conversion when payment succeeds
client.resolve_conversion({
    "userId": "user_123",
    "amount": 99.00,
})
```

## Setup

### 1. Get your credentials

Get your API key and Project ID from [fourbyfour.dev](https://fourbyfour.dev).

### 2. Configure environment variables

```bash
# .env
FOURBYFOUR_API_KEY=sk_live_...
FOURBYFOUR_PROJECT_ID=proj_...
```

### 3. Initialize the client

```python
# lib/fourbyfour.py
import os
from fourbyfour import fbf

client = fbf(
    api_key=os.environ["FOURBYFOUR_API_KEY"],
    project_id=os.environ["FOURBYFOUR_PROJECT_ID"],
)
```

## API

### `start_workflow(params)`

Trigger a workflow by sending an intent event.

```python
result = client.start_workflow({
    "userId": "user_123",
    "intent": "PAYMENT_FAILED",
    "signals": {
        "amountCents": 9900,
        "reason": "card_expired",
    },
})

print(result.event_id)            # 'evt_...'
print(result.workflows_triggered)  # ['wf_...']
```

### `resolve_conversion(params)`

Record a successful conversion (payment recovered, trial converted, etc).

```python
result = client.resolve_conversion({
    "userId": "user_123",
    "amount": 99.00,
})

print(result.conversion_id)  # 'conv_...'
print(result.attributed)     # True
```

## Intents

| Intent | Description |
|--------|-------------|
| `SIGNUP_COMPLETED` | User signed up |
| `ONBOARDING_STARTED` | User started onboarding |
| `ONBOARDING_COMPLETED` | User completed onboarding |
| `TRIAL_STARTED` | Trial period began |
| `TRIAL_ENDING` | Trial ending soon |
| `TRIAL_EXPIRED` | Trial has expired |
| `PLAN_SELECTED` | User selected a plan |
| `CHECKOUT_STARTED` | User started checkout |
| `PAYMENT_FAILED` | Payment failed |
| `SUBSCRIPTION_ENDING` | Subscription renewal coming up |
| `SUBSCRIPTION_CANCELLED` | User cancelled subscription |
| `SUBSCRIPTION_DOWNGRADED` | User downgraded plan |

## Type Safety

Use the `Signals` type for type hints:

```python
from fourbyfour import fbf, Signals

client = fbf(
    api_key=os.environ["FOURBYFOUR_API_KEY"],
    project_id=os.environ["FOURBYFOUR_PROJECT_ID"],
)

# Type hints for signal fields
signals: Signals["PAYMENT_FAILED"] = {
    "amountCents": 9900,
    "reason": "card_expired",
}

client.start_workflow({
    "userId": "user_123",
    "intent": "PAYMENT_FAILED",
    "signals": signals,
})
```

## Examples

### Payment Recovery

```python
# When payment fails
client.start_workflow({
    "userId": user.id,
    "intent": "PAYMENT_FAILED",
    "signals": {
        "amountCents": invoice.amount,
        "reason": "card_expired",
        "retryCount": 1,
    },
})

# When user updates card and pays
client.resolve_conversion({
    "userId": user.id,
    "amount": invoice.amount / 100,
})
```

### Trial Conversion

```python
# When trial is ending
client.start_workflow({
    "userId": user.id,
    "intent": "TRIAL_ENDING",
    "signals": {
        "daysRemaining": 3,
        "plan": {"id": "pro", "name": "Pro", "priceCents": 2900},
    },
})

# When user converts to paid
client.resolve_conversion({
    "userId": user.id,
    "amount": 29.00,
})
```

### Churn Prevention

```python
# When user requests cancellation
client.start_workflow({
    "userId": user.id,
    "intent": "SUBSCRIPTION_CANCELLED",
    "signals": {
        "reason": "too_expensive",
        "tenureMonths": 6,
        "plan": {"id": "pro", "name": "Pro", "priceCents": 2900},
    },
})

# If user decides to stay
client.resolve_conversion({
    "userId": user.id,
    "amount": 29.00,
})
```

## Error Handling

```python
from fourbyfour import fbf, FourbyfourError, AuthenticationError, RateLimitError

client = fbf(api_key="...", project_id="...")

try:
    client.start_workflow({
        "userId": "user_123",
        "intent": "PAYMENT_FAILED",
        "signals": {"amountCents": 9900, "reason": "declined"},
    })
except AuthenticationError:
    print("Invalid API key")
except RateLimitError:
    print("Rate limit exceeded, retry later")
except FourbyfourError as e:
    print(f"API error: {e}")
```

## Context Manager

The client can be used as a context manager:

```python
from fourbyfour import fbf

with fbf(api_key="...", project_id="...") as client:
    client.start_workflow({
        "userId": "user_123",
        "intent": "PAYMENT_FAILED",
        "signals": {"amountCents": 9900, "reason": "declined"},
    })
# Connection automatically closed
```

## Documentation

See [fourbyfour.dev/docs](https://fourbyfour.dev/docs) for full documentation.

## License

MIT
