enconvert 0.0.1__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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Enconvert
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,362 @@
1
+ Metadata-Version: 2.4
2
+ Name: enconvert
3
+ Version: 0.0.1
4
+ Summary: Python SDK for the Enconvert file conversion API
5
+ Author-email: Enconvert <support@enconvert.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://enconvert.com
8
+ Project-URL: Repository, https://github.com/conversionapi/python-sdk
9
+ Keywords: enconvert,pdf,screenshot,conversion,html-to-pdf,url-to-pdf,url-to-screenshot,url-to-markdown,image-convert,document-convert,heic-to-webp,docx-to-pdf,api,sdk
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.9
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Typing :: Typed
19
+ Requires-Python: >=3.9
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Requires-Dist: requests>=2.28
23
+ Provides-Extra: dev
24
+ Requires-Dist: pytest>=7.0; extra == "dev"
25
+ Requires-Dist: mypy>=1.8; extra == "dev"
26
+ Dynamic: license-file
27
+
28
+ # enconvert
29
+
30
+ Python SDK for the [Enconvert](https://enconvert.com) file conversion API.
31
+
32
+ Convert URLs to PDFs, capture screenshots, extract Markdown, crawl whole websites, transform images, and convert documents — all with a single API call. Python 3.9+.
33
+
34
+ ## Install
35
+
36
+ ```bash
37
+ pip install enconvert
38
+ ```
39
+
40
+ ## Quick Start
41
+
42
+ ```python
43
+ from enconvert import Enconvert
44
+
45
+ client = Enconvert(api_key="sk_...")
46
+ ```
47
+
48
+ ### URL to PDF
49
+
50
+ ```python
51
+ result = client.convert_url_to_pdf("https://example.com", save_to="page.pdf")
52
+ print(result.presigned_url)
53
+ ```
54
+
55
+ ### URL to Screenshot
56
+
57
+ ```python
58
+ result = client.convert_url_to_screenshot(
59
+ "https://example.com",
60
+ viewport_width=1440,
61
+ save_to="screenshot.png",
62
+ )
63
+ ```
64
+
65
+ ### URL to Markdown
66
+
67
+ Extract clean GitHub-Flavored Markdown from any URL — strips nav/footer/ads/scripts, keeps the main article content, and adds YAML frontmatter (title, description, url, links, images).
68
+
69
+ ```python
70
+ result = client.convert_url_to_markdown(
71
+ "https://example.com/article",
72
+ save_to="article.md",
73
+ )
74
+ ```
75
+
76
+ ### Website to PDF / Screenshot (whole-site batch)
77
+
78
+ Discover every page of a website (via sitemap, or full crawl on Pro/Business plans), convert each one in the background, and receive a single ZIP. Requires a private API key with crawl access.
79
+
80
+ ```python
81
+ batch = client.convert_website_to_pdf(
82
+ "https://example.com",
83
+ crawl_mode="sitemap", # "auto" (default) | "sitemap" | "full"
84
+ exclude_patterns=["/blog/tag/"], # full crawl mode only
85
+ )
86
+ print(batch.batch_id, batch.url_count, batch.discovery_method)
87
+
88
+ # Block until done and save the ZIP:
89
+ status = client.wait_for_batch(batch.batch_id, save_to="site.zip")
90
+ print(status.completed, "of", status.total, "pages converted")
91
+
92
+ # Or poll yourself:
93
+ s = client.get_batch_status(batch.batch_id)
94
+ if s.status != "processing":
95
+ print(s.zip_download_url)
96
+ ```
97
+
98
+ `convert_website_to_screenshot` works the same way and produces a ZIP of PNGs.
99
+
100
+ ### Image Conversion
101
+
102
+ ```python
103
+ result = client.convert_image(
104
+ "photo.heic",
105
+ output_format="webp",
106
+ save_to="photo.webp",
107
+ )
108
+ ```
109
+
110
+ Any pair among `jpeg`, `png`, `svg`, `heic`, `webp` — plus PDF rasterization:
111
+
112
+ ```python
113
+ client.convert_image("scan.pdf", output_format="jpeg", save_to="scan.jpeg")
114
+ ```
115
+
116
+ ### Document Conversion
117
+
118
+ ```python
119
+ client.convert_document("report.docx", save_to="report.pdf")
120
+ client.convert_document("data.json", output_format="yaml", save_to="data.yaml")
121
+ client.convert_document("notes.md", output_format="html", save_to="notes.html")
122
+ ```
123
+
124
+ Supported inputs: `doc`/`docx`, `xls`/`xlsx`, `ppt`/`pptx`, `odt`, `ods`, `odp`, `ots`, `pages`, `numbers`, `epub`, `html`, `markdown`, `csv`, `json`, `xml`, `yaml`, `toml`
125
+
126
+ The SDK validates every `{input}-to-{output}` pair against the conversions the API actually implements and raises immediately — with the list of valid outputs for that input — instead of sending a doomed request. Introspect programmatically:
127
+
128
+ ```python
129
+ from enconvert import IMPLEMENTED_CONVERSIONS, valid_outputs_for
130
+
131
+ valid_outputs_for("json") # ["csv", "toml", "xml", "yaml"]
132
+ valid_outputs_for("pdf") # ["jpeg"]
133
+ ```
134
+
135
+ ### Supported conversions
136
+
137
+ | Input | Outputs |
138
+ |-------|---------|
139
+ | json | csv, toml, xml, yaml |
140
+ | xml | csv, json |
141
+ | yaml | json |
142
+ | csv | json, xml |
143
+ | toml | json |
144
+ | markdown | html, pdf |
145
+ | html | pdf |
146
+ | doc, excel, ppt, odt, ods, odp, ots, pages, numbers, epub | pdf |
147
+ | jpeg, png, svg, heic, webp | each other (all 20 pairs) |
148
+ | pdf | jpeg |
149
+
150
+ ### Job Status (async polling)
151
+
152
+ ```python
153
+ status = client.get_job_status("job_abc123")
154
+ if status.status == "success":
155
+ print(status.presigned_url)
156
+ ```
157
+
158
+ ## PDF Options
159
+
160
+ ```python
161
+ from enconvert import PdfHeaderFooter, PdfMargins, PdfOptions
162
+
163
+ result = client.convert_url_to_pdf(
164
+ "https://example.com",
165
+ pdf_options=PdfOptions(
166
+ page_size="A4", # or custom dimensions via page_width + page_height
167
+ orientation="landscape",
168
+ margins=PdfMargins(top=10, bottom=10, left=15, right=15),
169
+ header=PdfHeaderFooter(content="Quarterly Report", height=15),
170
+ footer=PdfHeaderFooter(content="Confidential", height=12),
171
+ ),
172
+ save_to="report.pdf",
173
+ )
174
+ ```
175
+
176
+ ## Authenticated Pages (plan-gated)
177
+
178
+ All URL and website conversions accept HTTP Basic Auth, cookies, and custom headers for pages behind a login:
179
+
180
+ ```python
181
+ from enconvert import BrowserCookie, HttpBasicAuth
182
+
183
+ client.convert_url_to_pdf(
184
+ "https://internal.example.com/report",
185
+ auth=HttpBasicAuth(username="user", password="pass"),
186
+ # or cookies / headers:
187
+ cookies=[BrowserCookie(name="session", value="abc123", domain="internal.example.com")],
188
+ headers={"X-Tenant": "acme"},
189
+ save_to="report.pdf",
190
+ )
191
+ ```
192
+
193
+ Do not combine `auth` with an `Authorization` header — the API rejects the conflict.
194
+
195
+ ## Error Handling
196
+
197
+ ```python
198
+ from enconvert import Enconvert, APIError, AuthenticationError, RateLimitError
199
+
200
+ try:
201
+ client.convert_url_to_pdf("https://example.com")
202
+ except AuthenticationError:
203
+ print("Invalid API key")
204
+ except RateLimitError:
205
+ print("Too many requests — slow down")
206
+ except APIError as e:
207
+ print(f"API error [{e.status_code}]: {e.message}")
208
+ ```
209
+
210
+ ## Configuration
211
+
212
+ ```python
213
+ client = Enconvert(
214
+ api_key="sk_...",
215
+ timeout=300.0, # seconds, default
216
+ base_url="https://api.enconvert.com", # default
217
+ )
218
+ ```
219
+
220
+ ## V2 API (`client.v2`)
221
+
222
+ The V2 namespace turns web pages into agent-ready data: render, search, extract, ingest, and monitor. All V2 endpoints require a **private API key** and are plan-gated — a disabled feature or exhausted monthly quota raises `QuotaError` (HTTP 402).
223
+
224
+ ### Perceive — render a URL into artifacts
225
+
226
+ ```python
227
+ op = client.v2.perceive(
228
+ "https://example.com",
229
+ outputs=["markdown", "screenshot", "structured"],
230
+ extract=["tables", "metadata"],
231
+ )
232
+ print(op.outputs["markdown"].url) # 15-min signed URL
233
+ print(op.structured)
234
+
235
+ # Re-sign artifact URLs later:
236
+ again = client.v2.get_perceive_operation(op.operation_id)
237
+
238
+ # Batch (<=10 URLs runs inline; larger returns "queued" — poll):
239
+ batch = client.v2.perceive_batch(
240
+ ["https://a.com", "https://b.com"],
241
+ outputs=["markdown"],
242
+ output_mode="zip",
243
+ )
244
+ done = client.v2.get_perceive_batch(batch.job_id)
245
+ ```
246
+
247
+ ### Discover — enumerate a site's URLs (no rendering)
248
+
249
+ ```python
250
+ found = client.v2.discover(
251
+ "https://example.com",
252
+ mode="hybrid", # "sitemap" | "crawl" | "hybrid"
253
+ max_urls=200,
254
+ exclude_patterns=["/tag/"],
255
+ )
256
+ print(found.total, found.urls)
257
+ ```
258
+
259
+ ### Lookup — web search with optional auto-perceive
260
+
261
+ ```python
262
+ search = client.v2.lookup(
263
+ "best static site generators",
264
+ category="web", # web | news | images | scholar | patents | maps
265
+ num_results=10,
266
+ perceive_top=3, # auto-render top 3 results (uses perceive quota)
267
+ )
268
+ for hit in search.results:
269
+ print(hit.title, hit.url, hit.perceive.outputs if hit.perceive else None)
270
+ ```
271
+
272
+ ### Distill — schema-driven structured extraction
273
+
274
+ ```python
275
+ from enconvert import CssField, CssSchema
276
+
277
+ extraction = client.v2.distill(
278
+ urls=["https://example.com/pricing"],
279
+ schema={"plans": "list of plan names with monthly prices"},
280
+ css_schema=CssSchema( # optional free CSS pass before the LLM tier
281
+ base_selector=".plan-card",
282
+ fields=[
283
+ CssField(name="name", type="text", selector="h3"),
284
+ CssField(name="price", type="text", selector=".price"),
285
+ ],
286
+ ),
287
+ )
288
+ print(extraction.results[0].data, extraction.results[0].extraction_tier)
289
+
290
+ # Or discover-then-distill:
291
+ from enconvert import DistillDiscoverFrom
292
+
293
+ client.v2.distill(
294
+ discover_from=DistillDiscoverFrom(url="https://example.com", mode="sitemap", max_pages=10),
295
+ schema={"title": "page title", "summary": "one-line summary"},
296
+ )
297
+ ```
298
+
299
+ ### Ingest — site to RAG-ready JSONL (always async)
300
+
301
+ ```python
302
+ from enconvert import IngestChunkOptions
303
+
304
+ job = client.v2.ingest(
305
+ mode="sitemap",
306
+ url="https://docs.example.com",
307
+ max_pages=100,
308
+ chunk=IngestChunkOptions(max_words=512, sentence_overlap=1),
309
+ webhook_url="https://my.app/hooks/enconvert",
310
+ )
311
+
312
+ status = client.v2.get_ingest_job(job.job_id) # poll
313
+ if status.status == "completed":
314
+ print(status.output_url) # JSONL
315
+
316
+ client.v2.list_ingest_jobs(limit=20)
317
+ client.v2.cancel_ingest_job(job.job_id) # idempotent
318
+
319
+ # Webhook signing (HMAC):
320
+ secret = client.v2.get_webhook_secret()
321
+ print(secret.secret, secret.signature_header)
322
+ client.v2.rotate_webhook_secret() # invalidates old secret
323
+ client.v2.retry_ingest_webhook(job.job_id) # re-deliver
324
+ ```
325
+
326
+ ### Watch — recurring change monitoring
327
+
328
+ ```python
329
+ watcher = client.v2.create_watcher(
330
+ "https://example.com/pricing",
331
+ frequency_minutes=60, # hourly floor
332
+ diff_mode="auto", # auto | text | structured | tables | metadata
333
+ webhook_url="https://my.app/hooks/changes",
334
+ notify_email=True,
335
+ )
336
+
337
+ client.v2.list_watchers()
338
+ client.v2.get_watcher(watcher.watcher_id)
339
+ client.v2.get_watcher_snapshots(watcher.watcher_id, limit=10)
340
+ client.v2.update_watcher(watcher.watcher_id, status="paused")
341
+ client.v2.update_watcher(watcher.watcher_id, webhook_url="") # clears webhook
342
+ client.v2.delete_watcher(watcher.watcher_id) # soft-delete, idempotent
343
+ ```
344
+
345
+ ### V2 error handling
346
+
347
+ ```python
348
+ from enconvert import QuotaError
349
+
350
+ try:
351
+ client.v2.ingest(urls=["https://example.com"])
352
+ except QuotaError:
353
+ print("Upgrade plan or wait for quota reset")
354
+ ```
355
+
356
+ ## Get an API Key
357
+
358
+ Sign up at [enconvert.com](https://enconvert.com) to get your API key.
359
+
360
+ ## License
361
+
362
+ MIT