seoscoreapi 1.3.0__tar.gz → 1.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {seoscoreapi-1.3.0 → seoscoreapi-1.4.0}/PKG-INFO +31 -2
- {seoscoreapi-1.3.0 → seoscoreapi-1.4.0}/README.md +30 -1
- {seoscoreapi-1.3.0 → seoscoreapi-1.4.0}/pyproject.toml +1 -1
- {seoscoreapi-1.3.0 → seoscoreapi-1.4.0}/seoscoreapi/__init__.py +100 -2
- {seoscoreapi-1.3.0 → seoscoreapi-1.4.0}/seoscoreapi.egg-info/PKG-INFO +31 -2
- {seoscoreapi-1.3.0 → seoscoreapi-1.4.0}/seoscoreapi.egg-info/SOURCES.txt +0 -0
- {seoscoreapi-1.3.0 → seoscoreapi-1.4.0}/seoscoreapi.egg-info/dependency_links.txt +0 -0
- {seoscoreapi-1.3.0 → seoscoreapi-1.4.0}/seoscoreapi.egg-info/requires.txt +0 -0
- {seoscoreapi-1.3.0 → seoscoreapi-1.4.0}/seoscoreapi.egg-info/top_level.txt +0 -0
- {seoscoreapi-1.3.0 → seoscoreapi-1.4.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: seoscoreapi
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.4.0
|
|
4
4
|
Summary: Python client for SEO Score API — audit any URL for SEO issues with one function call
|
|
5
5
|
Author-email: SEO Score API <info@seoscoreapi.com>
|
|
6
6
|
License: MIT
|
|
@@ -31,7 +31,7 @@ pip install seoscoreapi
|
|
|
31
31
|
```python
|
|
32
32
|
from seoscoreapi import audit, signup
|
|
33
33
|
|
|
34
|
-
# Get a free API key (
|
|
34
|
+
# Get a free API key (2 audits/day, no credit card)
|
|
35
35
|
key = signup("you@example.com")
|
|
36
36
|
|
|
37
37
|
# Run an audit
|
|
@@ -83,6 +83,35 @@ add_monitor(
|
|
|
83
83
|
|
|
84
84
|
Slack incoming-webhook URLs are auto-formatted as Block Kit messages; any other https endpoint receives the raw event JSON.
|
|
85
85
|
|
|
86
|
+
## Deep Audits (Pro/Ultra)
|
|
87
|
+
|
|
88
|
+
A deep, AI-assisted audit scoring a URL across 9 dimensions (~150 AI checks). It
|
|
89
|
+
runs asynchronously — submit, then poll — or use `deep_audit` to block for the result:
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
import seoscoreapi as seo
|
|
93
|
+
|
|
94
|
+
# One call, waits for the result (handles the queue + backpressure for you):
|
|
95
|
+
result = seo.deep_audit(
|
|
96
|
+
"https://yoursite.com", API_KEY,
|
|
97
|
+
business_type="saas", # tunes which checks apply
|
|
98
|
+
on_progress=lambda s: print(s["status"], s.get("queue_position", s.get("progress"))),
|
|
99
|
+
)
|
|
100
|
+
print(result["scores"]["lai_score"], result["scores"]["section_scores"])
|
|
101
|
+
|
|
102
|
+
# Or drive the job yourself:
|
|
103
|
+
job = seo.site_audit("https://yoursite.com", API_KEY)
|
|
104
|
+
status = seo.get_site_audit(job["job_id"], API_KEY)
|
|
105
|
+
# status["status"] -> queued | running | completed | failed
|
|
106
|
+
# queued -> {"queue_position", "eta_seconds"}
|
|
107
|
+
# done -> {"result"}
|
|
108
|
+
|
|
109
|
+
seo.engine_usage(API_KEY) # remaining deep-audit + SERP quota
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Deep audits require a **Pro** ($39/mo, 20/mo) or **Ultra** ($99/mo, 100/mo) key.
|
|
113
|
+
Full engine reference: [engine.seoscoreapi.com/docs](https://engine.seoscoreapi.com/docs).
|
|
114
|
+
|
|
86
115
|
## Full Documentation
|
|
87
116
|
|
|
88
117
|
[seoscoreapi.com/docs](https://seoscoreapi.com/docs)
|
|
@@ -13,7 +13,7 @@ pip install seoscoreapi
|
|
|
13
13
|
```python
|
|
14
14
|
from seoscoreapi import audit, signup
|
|
15
15
|
|
|
16
|
-
# Get a free API key (
|
|
16
|
+
# Get a free API key (2 audits/day, no credit card)
|
|
17
17
|
key = signup("you@example.com")
|
|
18
18
|
|
|
19
19
|
# Run an audit
|
|
@@ -65,6 +65,35 @@ add_monitor(
|
|
|
65
65
|
|
|
66
66
|
Slack incoming-webhook URLs are auto-formatted as Block Kit messages; any other https endpoint receives the raw event JSON.
|
|
67
67
|
|
|
68
|
+
## Deep Audits (Pro/Ultra)
|
|
69
|
+
|
|
70
|
+
A deep, AI-assisted audit scoring a URL across 9 dimensions (~150 AI checks). It
|
|
71
|
+
runs asynchronously — submit, then poll — or use `deep_audit` to block for the result:
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
import seoscoreapi as seo
|
|
75
|
+
|
|
76
|
+
# One call, waits for the result (handles the queue + backpressure for you):
|
|
77
|
+
result = seo.deep_audit(
|
|
78
|
+
"https://yoursite.com", API_KEY,
|
|
79
|
+
business_type="saas", # tunes which checks apply
|
|
80
|
+
on_progress=lambda s: print(s["status"], s.get("queue_position", s.get("progress"))),
|
|
81
|
+
)
|
|
82
|
+
print(result["scores"]["lai_score"], result["scores"]["section_scores"])
|
|
83
|
+
|
|
84
|
+
# Or drive the job yourself:
|
|
85
|
+
job = seo.site_audit("https://yoursite.com", API_KEY)
|
|
86
|
+
status = seo.get_site_audit(job["job_id"], API_KEY)
|
|
87
|
+
# status["status"] -> queued | running | completed | failed
|
|
88
|
+
# queued -> {"queue_position", "eta_seconds"}
|
|
89
|
+
# done -> {"result"}
|
|
90
|
+
|
|
91
|
+
seo.engine_usage(API_KEY) # remaining deep-audit + SERP quota
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Deep audits require a **Pro** ($39/mo, 20/mo) or **Ultra** ($99/mo, 100/mo) key.
|
|
95
|
+
Full engine reference: [engine.seoscoreapi.com/docs](https://engine.seoscoreapi.com/docs).
|
|
96
|
+
|
|
68
97
|
## Full Documentation
|
|
69
98
|
|
|
70
99
|
[seoscoreapi.com/docs](https://seoscoreapi.com/docs)
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "seoscoreapi"
|
|
7
|
-
version = "1.
|
|
7
|
+
version = "1.4.0"
|
|
8
8
|
description = "Python client for SEO Score API — audit any URL for SEO issues with one function call"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = {text = "MIT"}
|
|
@@ -17,14 +17,19 @@ Usage:
|
|
|
17
17
|
Full docs: https://seoscoreapi.com/docs
|
|
18
18
|
"""
|
|
19
19
|
|
|
20
|
-
from
|
|
20
|
+
from __future__ import annotations # lazy annotations so `list[str]` works on Python 3.8
|
|
21
|
+
|
|
22
|
+
import time
|
|
23
|
+
from typing import Callable, Optional
|
|
21
24
|
|
|
22
25
|
import requests
|
|
23
26
|
|
|
24
27
|
BASE_URL = "https://seoscoreapi.com"
|
|
25
|
-
|
|
28
|
+
ENGINE_URL = "https://engine.seoscoreapi.com"
|
|
29
|
+
__version__ = "1.4.0"
|
|
26
30
|
|
|
27
31
|
_HEADERS = {"User-Agent": f"seoscoreapi-python/{__version__}"}
|
|
32
|
+
_TIMEOUT = 30 # seconds — default per-request timeout for engine calls
|
|
28
33
|
|
|
29
34
|
|
|
30
35
|
def signup(email: str) -> str:
|
|
@@ -130,3 +135,96 @@ def history_domains(api_key: str) -> list:
|
|
|
130
135
|
r = requests.get(f"{BASE_URL}/history/domains", headers={"X-API-Key": api_key, **_HEADERS})
|
|
131
136
|
r.raise_for_status()
|
|
132
137
|
return r.json()["domains"]
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
# --- Deep Audits (engine.seoscoreapi.com) — Pro/Ultra -----------------------
|
|
141
|
+
|
|
142
|
+
def site_audit(url: str, api_key: str, **options) -> dict:
|
|
143
|
+
"""Start a Deep Audit (Pro/Ultra). Asynchronous — returns a job
|
|
144
|
+
``{"job_id", "status", "poll"}``; poll it with :func:`get_site_audit`.
|
|
145
|
+
|
|
146
|
+
Optional keyword args: ``business_type``, ``is_local``,
|
|
147
|
+
``connected_integrations``, ``webhook_url``.
|
|
148
|
+
"""
|
|
149
|
+
r = requests.post(
|
|
150
|
+
f"{ENGINE_URL}/site-audit",
|
|
151
|
+
json={"url": url, **options},
|
|
152
|
+
headers={"X-API-Key": api_key, **_HEADERS},
|
|
153
|
+
timeout=_TIMEOUT,
|
|
154
|
+
)
|
|
155
|
+
r.raise_for_status()
|
|
156
|
+
return r.json()
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def get_site_audit(job_id: str, api_key: str) -> dict:
|
|
160
|
+
"""Poll a deep audit job. Returns ``status`` plus ``queue_position``/
|
|
161
|
+
``eta_seconds`` while queued, ``progress``/``stage`` while running, and
|
|
162
|
+
``result`` when completed (or ``error`` when failed)."""
|
|
163
|
+
r = requests.get(
|
|
164
|
+
f"{ENGINE_URL}/site-audit/{job_id}",
|
|
165
|
+
headers={"X-API-Key": api_key, **_HEADERS},
|
|
166
|
+
timeout=_TIMEOUT,
|
|
167
|
+
)
|
|
168
|
+
r.raise_for_status()
|
|
169
|
+
return r.json()
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def deep_audit(
|
|
173
|
+
url: str,
|
|
174
|
+
api_key: str,
|
|
175
|
+
*,
|
|
176
|
+
poll_interval: float = 5.0,
|
|
177
|
+
timeout: float = 600.0,
|
|
178
|
+
on_progress: Optional[Callable[[dict], None]] = None,
|
|
179
|
+
**options,
|
|
180
|
+
) -> dict:
|
|
181
|
+
"""Start a deep audit and block until it finishes; return the result dict.
|
|
182
|
+
|
|
183
|
+
Handles queue backpressure (429 + ``Retry-After``) and honors the server's
|
|
184
|
+
ETA between polls. Raises ``TimeoutError`` if it doesn't finish within
|
|
185
|
+
``timeout`` seconds, or ``RuntimeError`` if the audit fails.
|
|
186
|
+
"""
|
|
187
|
+
deadline = time.monotonic() + timeout
|
|
188
|
+
while True: # submit, retrying on backpressure
|
|
189
|
+
r = requests.post(
|
|
190
|
+
f"{ENGINE_URL}/site-audit",
|
|
191
|
+
json={"url": url, **options},
|
|
192
|
+
headers={"X-API-Key": api_key, **_HEADERS},
|
|
193
|
+
timeout=_TIMEOUT,
|
|
194
|
+
)
|
|
195
|
+
if r.status_code == 429:
|
|
196
|
+
retry = float(r.headers.get("Retry-After", 5))
|
|
197
|
+
if time.monotonic() + retry > deadline:
|
|
198
|
+
raise TimeoutError("Timed out waiting for queue capacity")
|
|
199
|
+
time.sleep(retry)
|
|
200
|
+
continue
|
|
201
|
+
r.raise_for_status()
|
|
202
|
+
job = r.json()
|
|
203
|
+
break
|
|
204
|
+
|
|
205
|
+
while True: # poll to completion
|
|
206
|
+
if time.monotonic() > deadline:
|
|
207
|
+
raise TimeoutError("Timed out waiting for audit to complete")
|
|
208
|
+
status = get_site_audit(job["job_id"], api_key)
|
|
209
|
+
if on_progress:
|
|
210
|
+
on_progress(status)
|
|
211
|
+
state = status.get("status")
|
|
212
|
+
if state == "completed":
|
|
213
|
+
return status["result"]
|
|
214
|
+
if state == "failed":
|
|
215
|
+
raise RuntimeError(status.get("error", "Audit failed"))
|
|
216
|
+
if state == "queued" and status.get("eta_seconds"):
|
|
217
|
+
time.sleep(min(status["eta_seconds"], 15.0))
|
|
218
|
+
else:
|
|
219
|
+
time.sleep(poll_interval)
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def engine_usage(api_key: str) -> dict:
|
|
223
|
+
"""Remaining engine quota (deep audits + SERP) for this key."""
|
|
224
|
+
r = requests.get(
|
|
225
|
+
f"{ENGINE_URL}/usage",
|
|
226
|
+
headers={"X-API-Key": api_key, **_HEADERS},
|
|
227
|
+
timeout=_TIMEOUT,
|
|
228
|
+
)
|
|
229
|
+
r.raise_for_status()
|
|
230
|
+
return r.json()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: seoscoreapi
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.4.0
|
|
4
4
|
Summary: Python client for SEO Score API — audit any URL for SEO issues with one function call
|
|
5
5
|
Author-email: SEO Score API <info@seoscoreapi.com>
|
|
6
6
|
License: MIT
|
|
@@ -31,7 +31,7 @@ pip install seoscoreapi
|
|
|
31
31
|
```python
|
|
32
32
|
from seoscoreapi import audit, signup
|
|
33
33
|
|
|
34
|
-
# Get a free API key (
|
|
34
|
+
# Get a free API key (2 audits/day, no credit card)
|
|
35
35
|
key = signup("you@example.com")
|
|
36
36
|
|
|
37
37
|
# Run an audit
|
|
@@ -83,6 +83,35 @@ add_monitor(
|
|
|
83
83
|
|
|
84
84
|
Slack incoming-webhook URLs are auto-formatted as Block Kit messages; any other https endpoint receives the raw event JSON.
|
|
85
85
|
|
|
86
|
+
## Deep Audits (Pro/Ultra)
|
|
87
|
+
|
|
88
|
+
A deep, AI-assisted audit scoring a URL across 9 dimensions (~150 AI checks). It
|
|
89
|
+
runs asynchronously — submit, then poll — or use `deep_audit` to block for the result:
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
import seoscoreapi as seo
|
|
93
|
+
|
|
94
|
+
# One call, waits for the result (handles the queue + backpressure for you):
|
|
95
|
+
result = seo.deep_audit(
|
|
96
|
+
"https://yoursite.com", API_KEY,
|
|
97
|
+
business_type="saas", # tunes which checks apply
|
|
98
|
+
on_progress=lambda s: print(s["status"], s.get("queue_position", s.get("progress"))),
|
|
99
|
+
)
|
|
100
|
+
print(result["scores"]["lai_score"], result["scores"]["section_scores"])
|
|
101
|
+
|
|
102
|
+
# Or drive the job yourself:
|
|
103
|
+
job = seo.site_audit("https://yoursite.com", API_KEY)
|
|
104
|
+
status = seo.get_site_audit(job["job_id"], API_KEY)
|
|
105
|
+
# status["status"] -> queued | running | completed | failed
|
|
106
|
+
# queued -> {"queue_position", "eta_seconds"}
|
|
107
|
+
# done -> {"result"}
|
|
108
|
+
|
|
109
|
+
seo.engine_usage(API_KEY) # remaining deep-audit + SERP quota
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Deep audits require a **Pro** ($39/mo, 20/mo) or **Ultra** ($99/mo, 100/mo) key.
|
|
113
|
+
Full engine reference: [engine.seoscoreapi.com/docs](https://engine.seoscoreapi.com/docs).
|
|
114
|
+
|
|
86
115
|
## Full Documentation
|
|
87
116
|
|
|
88
117
|
[seoscoreapi.com/docs](https://seoscoreapi.com/docs)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|