Metadata-Version: 2.5
Name: aivisibilityskill
Version: 1.0.1
Summary: Official Python client for the aivisibilityskill API: see how ChatGPT, Gemini, AI Overviews, Perplexity, Claude and Grok answer about any brand.
Project-URL: Homepage, https://aivisibilityskill.com/sdk
Project-URL: Documentation, https://api.aivisibilityskill.com/docs
Author-email: aivisibilityskill <support@aivisibilityskill.com>
License-Expression: MIT
License-File: LICENSE
Keywords: ai overviews,ai visibility,chatgpt,generative engine optimization,geo,llm,sdk
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Topic :: Software Development :: Libraries
Classifier: Typing :: Typed
Requires-Python: >=3.9
Requires-Dist: httpx<1,>=0.25
Provides-Extra: dev
Requires-Dist: pytest>=8; extra == 'dev'
Description-Content-Type: text/markdown

# aivisibilityskill

The official Python client for the [aivisibilityskill](https://aivisibilityskill.com) API. Ask ChatGPT, Gemini, Google AI Overviews and AI Mode, Perplexity, Claude and Grok about any brand, in any country, and get back what they said, who they cited and what to fix.

- Safe retries: every check carries an idempotency key, so a retry is never charged twice.
- Webhook signature verification included.
- One dependency (httpx). Python 3.9+. Typed (`py.typed`).

```sh
pip install aivisibilityskill
```

## Quick start

```python
import os
from aivisibilityskill import Aiv

aiv = Aiv(api_key=os.environ["AIV_KEY"])  # aiv_live_... or aiv_test_... (free sample data)

job = aiv.checks.create(
    ["best invoicing app for freelancers"],
    engines=["chatgpt", "gemini", "ai_overviews", "perplexity"],
    locale="en-US",
)
done = aiv.jobs.wait(job["id"])
for answer in done["answers"]:
    print(answer["engine"], [b["name"] for b in answer["brands"]])
```

Get a key at [app.aivisibilityskill.com](https://app.aivisibilityskill.com). Test keys (`aiv_test_...`) are free and return sample answers, so you can build without spending credits.

## Building for your own customers

```python
aiv.checks.create(questions, customer="cus_8421", metadata={"workspace": "acme"})

key = aiv.keys.create("acme", customer="cus_8421", allowed_ips=["203.0.113.0/24"])

csv_text = aiv.usage.csv(from_="2026-11-01", to="2026-11-30", group_by="customer")

# Everything stored for a customer, deleted (runs in the background):
deletion = aiv.customers.delete_data("cus_8421")
aiv.data_deletions.wait(deletion["id"])
```

## Thousands of answers at once

```python
batch = aiv.batches.create(
    two_thousand_questions,
    engines=["chatgpt", "ai_overviews"],
    mode="batch",        # cheapest
    max_age_hours=24,    # reuse answers from the last day at half price
)
done = aiv.batches.wait(batch["id"])  # or listen for the batch.completed webhook
for job_id in done["checks"]:
    job = aiv.jobs.get(job_id)
```

## Webhooks

```python
from aivisibilityskill import verify_webhook, WebhookVerificationError

# Flask: request.get_data(), Django: request.body, FastAPI: await request.body()
try:
    event = verify_webhook(raw_body, request.headers, os.environ["AIV_WEBHOOK_SECRET"])
except WebhookVerificationError:
    return "", 400
if event["type"] == "check.completed":
    job = aiv.jobs.get(event["data"]["id"])
```

During a secret rotation, pass both secrets: `verify_webhook(body, headers, [new_secret, old_secret])`. Deliveries older than 5 minutes are refused as replays.

## Lists

Lists are paged. `iterate()` follows the pages for you:

```python
for job in aiv.jobs.iterate(customer="cus_8421"): ...
for event in aiv.events.iterate(type="check.failed"): ...
for entry in aiv.audit_log.iterate(): ...
```

## Errors

Every failure raises `AivError` with the HTTP `status`, a stable `code` (`insufficient_credits`, `budget_exceeded`, `rate_limited`, ...), a readable `detail` and the `request_id` to quote to support.

```python
from aivisibilityskill import AivError
try:
    aiv.checks.create(questions)
except AivError as err:
    if err.code == "insufficient_credits": ...
```

GET requests and checks are retried on 429, 502, 503, 504 and network errors (twice by default, honouring `Retry-After`). Set `max_retries` and `timeout` in the constructor, or pass your own `httpx.Client`. Use it as a context manager (`with Aiv(...) as aiv:`) to close connections when done.

## Everything else

`aiv.projects` (tracking, schedules, visibility, competitors, sources, facts, history, site checks, research), `aiv.opportunities` and `aiv.fixes` (what to fix and proof it worked), `aiv.actions`, `aiv.webhooks`, `aiv.events`, `aiv.keys`, `aiv.account`, `aiv.locales`, `aiv.pricing()` and `aiv.estimate()`. Responses are the API's JSON as dicts. For anything not wrapped yet: `aiv.request("GET", "/v1/...")`.

API reference: [api.aivisibilityskill.com/docs](https://api.aivisibilityskill.com/docs). Support: support@aivisibilityskill.com.

MIT licensed.
