Metadata-Version: 2.4
Name: trackofferz
Version: 0.2.0
Summary: Official Python SDK for the TrackOfferz reporting API.
Project-URL: Homepage, https://trackofferz.com
Project-URL: Documentation, https://trackofferz.com/docs
Project-URL: Source, https://github.com/trackofferz/trackofferz-python
Author-email: SPTSPL <support@trackofferz.com>
License: MIT
Keywords: affiliate,reporting,sdk,tracking,trackofferz
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Typing :: Typed
Requires-Python: >=3.9
Description-Content-Type: text/markdown

# TrackOfferz Python SDK

Official, zero-dependency Python client for the [TrackOfferz](https://trackofferz.com) reporting API.

- **Typed** — dataclass results, ships with `py.typed`.
- **Zero dependencies** — standard library only.
- **Resilient** — automatic retries on 429 (honours `Retry-After`) and transient 5xx.
- **Network-scoped** — every call is limited to your network by the API key.

## Install

```bash
pip install trackofferz
```

## Authenticate

Create a key in the panel under **Settings → API keys** (format `tofz_sk_…`).

```python
from trackofferz import TrackOfferz

client = TrackOfferz(api_key="tofz_sk_...")
```

## Reporting

```python
# Summary (defaults to the last 30 days)
s = client.reports.summary(from_="2026-06-01", to="2026-06-30")
print(s.clicks, s.conversions, s.revenue_cents)

# Breakdown by publisher
for row in client.reports.breakdown(by="publisher"):
    print(row.label, row.conversions, row.payout_cents)

# One page of conversions for a campaign
page = client.reports.conversions(campaign_id=5, page=1, page_size=100)
print(page.total, page.has_next)
for c in page.rows:
    print(c.transaction_id, c.payout_cents, c.status)

# Stream EVERY click across all pages (auto-pagination)
for click in client.reports.iter_clicks(from_="2026-06-01", to="2026-06-30"):
    print(click.transaction_id, click.country_code, click.is_unique)
```

> Money fields are integers in **cents** (`payout_cents=1250` → `$12.50`).
> Date params are `YYYY-MM-DD`. `from_` has a trailing underscore (`from` is a Python keyword) and maps to the `from` query parameter.

## Conversions (ingest)

Record a conversion server-to-server for a click your link already tracked —
the basis of "Track from CMS". The `transaction_id` is the click id captured on
your landing page.

```python
res = client.conversions.create(
    transaction_id="click_abc123",   # the click id (a.k.a. tid)
    event_type="purchase",           # default; also: lead, install, refund, …
    payout=12.50,                    # decimal, or payout_cents=1250
    sale_amount=199.00,
    currency="USD",
    custom_data={"order_id": "SO-9001"},
)
print(res.status, res.conversion_id, res.duplicate)
```

> **Idempotent.** Re-sending the same `transaction_id` returns the existing
> conversion with `duplicate=True` — it never double-counts. Retries on
> `429`/`5xx` are therefore safe and automatic.
>
> The key is **bound to your network**: you can only convert your own clicks.
> A `404` (`click_not_found`) means no click matched the `transaction_id` within
> the attribution window.

## Errors

```python
from trackofferz import (
    AuthenticationError, ValidationError, RateLimitError, APIError, TrackOfferzError,
)

try:
    client.reports.summary(from_="not-a-date")
except ValidationError as e:
    print("bad input:", e.message)
except RateLimitError as e:
    print("slow down; retry after", e.retry_after, "s")
except TrackOfferzError as e:        # base class — catches all of the above
    print(e.status, e.code, e.message)
```

## Configuration

```python
TrackOfferz(
    api_key="tofz_sk_...",
    base_url="https://trackofferz.com/api/v1",  # override for self-hosted
    timeout=30.0,
    max_retries=2,
)
```

Full API reference: <https://trackofferz.com/docs>

---

TrackOfferz is a product by [SPTSPL (S. P. Techno Solution Private Limited)](https://www.sptspl.com).
