enconvert 0.0.1 → 0.1.0
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.
- checksums.yaml +4 -4
- data/README.md +316 -308
- data/lib/enconvert/v2.rb +762 -688
- data/lib/enconvert/v2_results.rb +144 -130
- data/lib/enconvert/version.rb +5 -5
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7245afabefb24e84a42769dc04a0dfe1693db85f6a98576dcd1d68a6c3fe4722
|
|
4
|
+
data.tar.gz: 5a5aecb734881a6e44680d749efc8813894bc9e75acf26871c6992a35fdaa9ef
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '008838d207976db15e7bdf12df5fde2b3820ac20141421ed2d880d80d9808891005fc7f5e7e85af8f1fd9861bfd59ca28c82c0f3f1df7bf9c0394b6835c617fa'
|
|
7
|
+
data.tar.gz: c220ba5c98cc41e920aff61f59310ab3c846f831bdf679bf6ba182150780b120906b22b2af5ea147932a8ecda9a6e404a74a7999127649616415742abce58064
|
data/README.md
CHANGED
|
@@ -1,308 +1,316 @@
|
|
|
1
|
-
# Enconvert Ruby SDK
|
|
2
|
-
|
|
3
|
-
Honest eyes for your AI agent — the Ruby SDK for [Enconvert](https://enconvert.com). Ruby 3.0+.
|
|
4
|
-
|
|
5
|
-
Read any web page or file into clean Markdown, JSON, or screenshots, and get a `render_quality` score (0.0–1.0) on **every** read — so a blocked, challenge, or empty-SPA page comes back flagged with a low score and warnings, never mistaken for real content. Perceive, discover, look up, distill, ingest, and watch the web; convert 40+ file and document formats through the same key.
|
|
6
|
-
|
|
7
|
-
> Wiring an agent (Claude, Cursor, Windsurf, n8n, …)? The [MCP server](https://enconvert.com/mcp) is the native path — `npx @enconvert/mcp setup`. This SDK is the programmatic REST path for everything else.
|
|
8
|
-
|
|
9
|
-
## Install
|
|
10
|
-
|
|
11
|
-
```bash
|
|
12
|
-
gem install enconvert
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
Or add to your Gemfile:
|
|
16
|
-
|
|
17
|
-
```ruby
|
|
18
|
-
gem "enconvert"
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
## Quick Start
|
|
22
|
-
|
|
23
|
-
```ruby
|
|
24
|
-
require "enconvert"
|
|
25
|
-
|
|
26
|
-
client = Enconvert::Client.new(api_key: "sk_...")
|
|
27
|
-
|
|
28
|
-
# Read a page the way your agent should — with a quality score attached.
|
|
29
|
-
op = client.v2.perceive("https://example.com", outputs: %w[markdown structured])
|
|
30
|
-
puts op.outputs["markdown"].url, op.render_quality # e.g. 0.93
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
---
|
|
34
|
-
|
|
35
|
-
# V2 — agent-ready data (`client.v2`)
|
|
36
|
-
|
|
37
|
-
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 `Enconvert::QuotaError` (HTTP 402).
|
|
38
|
-
|
|
39
|
-
Every render carries `render_quality` (0.0–1.0). A low score means the page didn't render cleanly (challenge page, cookie wall, empty shell); the content is still returned, flagged, so a bad read never quietly enters your agent's context.
|
|
40
|
-
|
|
41
|
-
### Perceive — render a URL into artifacts
|
|
42
|
-
|
|
43
|
-
```ruby
|
|
44
|
-
op = client.v2.perceive(
|
|
45
|
-
"https://example.com",
|
|
46
|
-
outputs: %w[markdown screenshot structured],
|
|
47
|
-
extract: %w[tables metadata]
|
|
48
|
-
)
|
|
49
|
-
puts op.render_quality # honesty score, 0.0–1.0
|
|
50
|
-
puts op.outputs["markdown"].url # 15-min signed URL
|
|
51
|
-
puts op.structured
|
|
52
|
-
|
|
53
|
-
# Re-sign artifact URLs later:
|
|
54
|
-
again = client.v2.get_perceive_operation(op.operation_id)
|
|
55
|
-
|
|
56
|
-
# Batch (<=1000 URLs; small batches run inline, larger return "queued" — poll):
|
|
57
|
-
batch = client.v2.perceive_batch(
|
|
58
|
-
["https://a.com", "https://b.com"],
|
|
59
|
-
outputs: ["markdown"],
|
|
60
|
-
output_mode: "zip"
|
|
61
|
-
)
|
|
62
|
-
done = client.v2.get_perceive_batch(batch.job_id)
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
)
|
|
74
|
-
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
client.v2.
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
client.v2.
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
|
230
|
-
|
|
231
|
-
|
|
|
232
|
-
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
###
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
1
|
+
# Enconvert Ruby SDK
|
|
2
|
+
|
|
3
|
+
Honest eyes for your AI agent — the Ruby SDK for [Enconvert](https://enconvert.com). Ruby 3.0+.
|
|
4
|
+
|
|
5
|
+
Read any web page or file into clean Markdown, JSON, or screenshots, and get a `render_quality` score (0.0–1.0) on **every** read — so a blocked, challenge, or empty-SPA page comes back flagged with a low score and warnings, never mistaken for real content. Perceive, discover, look up, distill, ingest, and watch the web; convert 40+ file and document formats through the same key.
|
|
6
|
+
|
|
7
|
+
> Wiring an agent (Claude, Cursor, Windsurf, n8n, …)? The [MCP server](https://enconvert.com/mcp) is the native path — `npx @enconvert/mcp setup`. This SDK is the programmatic REST path for everything else.
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
gem install enconvert
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Or add to your Gemfile:
|
|
16
|
+
|
|
17
|
+
```ruby
|
|
18
|
+
gem "enconvert"
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Quick Start
|
|
22
|
+
|
|
23
|
+
```ruby
|
|
24
|
+
require "enconvert"
|
|
25
|
+
|
|
26
|
+
client = Enconvert::Client.new(api_key: "sk_...")
|
|
27
|
+
|
|
28
|
+
# Read a page the way your agent should — with a quality score attached.
|
|
29
|
+
op = client.v2.perceive("https://example.com", outputs: %w[markdown structured])
|
|
30
|
+
puts op.outputs["markdown"].url, op.render_quality # e.g. 0.93
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
# V2 — agent-ready data (`client.v2`)
|
|
36
|
+
|
|
37
|
+
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 `Enconvert::QuotaError` (HTTP 402).
|
|
38
|
+
|
|
39
|
+
Every render carries `render_quality` (0.0–1.0). A low score means the page didn't render cleanly (challenge page, cookie wall, empty shell); the content is still returned, flagged, so a bad read never quietly enters your agent's context.
|
|
40
|
+
|
|
41
|
+
### Perceive — render a URL into artifacts
|
|
42
|
+
|
|
43
|
+
```ruby
|
|
44
|
+
op = client.v2.perceive(
|
|
45
|
+
"https://example.com",
|
|
46
|
+
outputs: %w[markdown screenshot structured],
|
|
47
|
+
extract: %w[tables metadata]
|
|
48
|
+
)
|
|
49
|
+
puts op.render_quality # honesty score, 0.0–1.0
|
|
50
|
+
puts op.outputs["markdown"].url # 15-min signed URL
|
|
51
|
+
puts op.structured
|
|
52
|
+
|
|
53
|
+
# Re-sign artifact URLs later:
|
|
54
|
+
again = client.v2.get_perceive_operation(op.operation_id)
|
|
55
|
+
|
|
56
|
+
# Batch (<=1000 URLs; small batches run inline, larger return "queued" — poll):
|
|
57
|
+
batch = client.v2.perceive_batch(
|
|
58
|
+
["https://a.com", "https://b.com"],
|
|
59
|
+
outputs: ["markdown"],
|
|
60
|
+
output_mode: "zip"
|
|
61
|
+
)
|
|
62
|
+
done = client.v2.get_perceive_batch(batch.job_id)
|
|
63
|
+
|
|
64
|
+
# Direct download: the response body IS the artifact bytes (no signed URL).
|
|
65
|
+
# Requires exactly one artifact-producing output; metadata rides in headers.
|
|
66
|
+
direct = client.v2.perceive_direct("https://example.com", outputs: ["markdown"])
|
|
67
|
+
puts direct.filename, direct.content_type, direct.content.bytesize
|
|
68
|
+
|
|
69
|
+
# Re-download a stored artifact from an earlier operation:
|
|
70
|
+
raw = client.v2.download_perceive_artifact(op.operation_id, output: "markdown")
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Discover — enumerate a site's URLs (no rendering)
|
|
74
|
+
|
|
75
|
+
```ruby
|
|
76
|
+
found = client.v2.discover(
|
|
77
|
+
"https://example.com",
|
|
78
|
+
mode: "hybrid", # "sitemap" | "crawl" | "hybrid"
|
|
79
|
+
max_urls: 200,
|
|
80
|
+
exclude_patterns: ["/tag/"]
|
|
81
|
+
)
|
|
82
|
+
puts found.total, found.urls
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Lookup — web search with optional auto-perceive
|
|
86
|
+
|
|
87
|
+
```ruby
|
|
88
|
+
search = client.v2.lookup(
|
|
89
|
+
"best static site generators",
|
|
90
|
+
category: "web", # web | news | images | scholar | patents | maps
|
|
91
|
+
num_results: 10,
|
|
92
|
+
perceive_top: 3 # auto-render top 3 results (uses perceive quota)
|
|
93
|
+
)
|
|
94
|
+
search.results.each { |hit| puts hit.title, hit.url, hit.perceive&.render_quality }
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Distill — schema-driven structured extraction
|
|
98
|
+
|
|
99
|
+
```ruby
|
|
100
|
+
extraction = client.v2.distill(
|
|
101
|
+
urls: ["https://example.com/pricing"],
|
|
102
|
+
schema: { plans: "list of plan names with monthly prices" },
|
|
103
|
+
css_schema: { # optional free CSS pass before the LLM tier
|
|
104
|
+
base_selector: ".plan-card",
|
|
105
|
+
fields: [
|
|
106
|
+
{ name: "name", type: "text", selector: "h3" },
|
|
107
|
+
{ name: "price", type: "text", selector: ".price" }
|
|
108
|
+
]
|
|
109
|
+
}
|
|
110
|
+
)
|
|
111
|
+
puts extraction.results.first.data, extraction.results.first.extraction_tier
|
|
112
|
+
|
|
113
|
+
# Or discover-then-distill:
|
|
114
|
+
client.v2.distill(
|
|
115
|
+
discover_from: { url: "https://example.com", mode: "sitemap", max_pages: 10 },
|
|
116
|
+
schema: { title: "page title", summary: "one-line summary" }
|
|
117
|
+
)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Ingest — site or files to RAG-ready JSONL (always async)
|
|
121
|
+
|
|
122
|
+
Turn a whole site — or a set of uploaded documents — into chunked, RAG-ready JSONL through one pipeline.
|
|
123
|
+
|
|
124
|
+
```ruby
|
|
125
|
+
# From a site:
|
|
126
|
+
job = client.v2.ingest(
|
|
127
|
+
mode: "sitemap",
|
|
128
|
+
url: "https://docs.example.com",
|
|
129
|
+
max_pages: 100,
|
|
130
|
+
chunk: { max_words: 512, sentence_overlap: 1 },
|
|
131
|
+
webhook_url: "https://my.app/hooks/enconvert"
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
# Or from uploaded files (PDF, DOCX, PPTX, XLSX, CSV, HTML, EPUB, TXT/MD, legacy/ODF office):
|
|
135
|
+
file_job = client.v2.ingest_files(
|
|
136
|
+
["handbook.pdf", "notes.docx"],
|
|
137
|
+
chunk: { max_words: 512, sentence_overlap: 1 }
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
status = client.v2.get_ingest_job(job.job_id) # poll
|
|
141
|
+
puts status.output_url if status.status == "completed" # JSONL
|
|
142
|
+
|
|
143
|
+
client.v2.list_ingest_jobs(limit: 20)
|
|
144
|
+
client.v2.cancel_ingest_job(job.job_id) # idempotent
|
|
145
|
+
|
|
146
|
+
# Webhook signing (HMAC):
|
|
147
|
+
secret = client.v2.get_webhook_secret
|
|
148
|
+
puts secret.secret, secret.signature_header
|
|
149
|
+
client.v2.rotate_webhook_secret # invalidates old secret
|
|
150
|
+
client.v2.retry_ingest_webhook(job.job_id) # re-deliver
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Watch — recurring change monitoring
|
|
154
|
+
|
|
155
|
+
```ruby
|
|
156
|
+
watcher = client.v2.create_watcher(
|
|
157
|
+
"https://example.com/pricing",
|
|
158
|
+
frequency_minutes: 60, # hourly floor
|
|
159
|
+
diff_mode: "auto", # auto | text | structured | tables | metadata
|
|
160
|
+
webhook_url: "https://my.app/hooks/changes",
|
|
161
|
+
notify_email: true
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
client.v2.list_watchers
|
|
165
|
+
client.v2.get_watcher(watcher.watcher_id)
|
|
166
|
+
client.v2.get_watcher_snapshots(watcher.watcher_id, limit: 10)
|
|
167
|
+
client.v2.update_watcher(watcher.watcher_id, status: "paused")
|
|
168
|
+
client.v2.update_watcher(watcher.watcher_id, webhook_url: "") # clears webhook
|
|
169
|
+
client.v2.delete_watcher(watcher.watcher_id) # soft-delete, idempotent
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### V2 error handling
|
|
173
|
+
|
|
174
|
+
```ruby
|
|
175
|
+
begin
|
|
176
|
+
client.v2.ingest(mode: "sitemap", url: "https://example.com")
|
|
177
|
+
rescue Enconvert::QuotaError
|
|
178
|
+
warn "Upgrade plan or wait for quota reset"
|
|
179
|
+
end
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
# File conversion
|
|
185
|
+
|
|
186
|
+
The same key also converts 40+ formats. Two "anything → X" endpoints auto-detect the input; the format-specific endpoints below give you a validated, typed path.
|
|
187
|
+
|
|
188
|
+
### Anything to Markdown / PDF
|
|
189
|
+
|
|
190
|
+
```ruby
|
|
191
|
+
# Any document → clean Markdown (a RAG-ingestion building block):
|
|
192
|
+
client.convert_to_markdown("report.docx", save_to: "report.md")
|
|
193
|
+
# PDF, DOCX, PPTX, XLSX, CSV, HTML, EPUB, TXT/MD, and legacy/ODF office. (Images not supported.)
|
|
194
|
+
|
|
195
|
+
# Almost anything → PDF:
|
|
196
|
+
client.convert_to_pdf("slides.pptx", save_to: "slides.pdf")
|
|
197
|
+
# office/ODF/Pages/Numbers/RTF/CSV, HTML, Markdown, text, images, SVG, EPUB, or a PDF passthrough.
|
|
198
|
+
# Only pdf_options[:grayscale] is honored on this endpoint:
|
|
199
|
+
client.convert_to_pdf("scan.pdf", pdf_options: { grayscale: true }, save_to: "gray.pdf")
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### Image conversion
|
|
203
|
+
|
|
204
|
+
```ruby
|
|
205
|
+
result = client.convert_image("photo.heic", output_format: "webp", save_to: "photo.webp")
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Any pair among `jpeg`, `png`, `svg`, `heic`, `webp` — plus PDF rasterization (`pdf` → `jpeg`). Unsupported pairs raise before any request is made:
|
|
209
|
+
|
|
210
|
+
```ruby
|
|
211
|
+
Enconvert.valid_outputs_for("json") # => ["csv", "toml", "xml", "yaml"]
|
|
212
|
+
Enconvert.valid_outputs_for("pdf") # => ["jpeg"]
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Document & data conversion
|
|
216
|
+
|
|
217
|
+
```ruby
|
|
218
|
+
client.convert_document("report.docx", save_to: "report.pdf")
|
|
219
|
+
client.convert_document("data.json", output_format: "yaml", save_to: "data.yaml")
|
|
220
|
+
client.convert_document("notes.md", output_format: "html", save_to: "notes.html")
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
Supported inputs: `doc`/`docx`, `xls`/`xlsx`, `ppt`/`pptx`, `odt`, `ods`, `odp`, `ots`, `pages`, `numbers`, `html`, `markdown`, `csv`, `json`, `xml`, `yaml`, `toml`. (EPUB → use `convert_to_pdf` / `convert_to_markdown`.)
|
|
224
|
+
|
|
225
|
+
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.
|
|
226
|
+
|
|
227
|
+
### Supported conversions
|
|
228
|
+
|
|
229
|
+
| Input | Outputs |
|
|
230
|
+
|-------|---------|
|
|
231
|
+
| json | csv, toml, xml, yaml |
|
|
232
|
+
| xml | csv, json |
|
|
233
|
+
| yaml | json |
|
|
234
|
+
| csv | json, xml |
|
|
235
|
+
| toml | json |
|
|
236
|
+
| markdown | html, pdf |
|
|
237
|
+
| html | pdf |
|
|
238
|
+
| doc, excel, ppt, odt, ods, odp, ots, pages, numbers | pdf |
|
|
239
|
+
| jpeg, png, svg, heic, webp | each other (all 20 pairs) |
|
|
240
|
+
| pdf | jpeg |
|
|
241
|
+
|
|
242
|
+
### URL to PDF / Screenshot / Markdown
|
|
243
|
+
|
|
244
|
+
```ruby
|
|
245
|
+
client.convert_url_to_pdf("https://example.com", save_to: "page.pdf")
|
|
246
|
+
client.convert_url_to_screenshot("https://example.com", viewport_width: 1440, save_to: "shot.png")
|
|
247
|
+
client.convert_url_to_markdown("https://example.com/article", save_to: "article.md")
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### Website to PDF / Screenshot (whole-site batch)
|
|
251
|
+
|
|
252
|
+
Discover every page of a website (sitemap, or full crawl on higher plans), convert each in the background, and receive a single ZIP. Requires a private API key with crawl access.
|
|
253
|
+
|
|
254
|
+
```ruby
|
|
255
|
+
batch = client.convert_website_to_pdf("https://example.com", crawl_mode: "sitemap")
|
|
256
|
+
status = client.wait_for_batch(batch.batch_id, save_to: "site.zip")
|
|
257
|
+
puts "#{status.completed} of #{status.total} pages converted"
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
`convert_website_to_screenshot` works the same way and produces a ZIP of PNGs.
|
|
261
|
+
|
|
262
|
+
### PDF options & authenticated pages
|
|
263
|
+
|
|
264
|
+
```ruby
|
|
265
|
+
client.convert_url_to_pdf(
|
|
266
|
+
"https://internal.example.com/report",
|
|
267
|
+
pdf_options: { page_size: "A4", orientation: "landscape", margins: { top: 10, bottom: 10 } },
|
|
268
|
+
auth: { username: "user", password: "pass" }, # or cookies / headers, plan-gated
|
|
269
|
+
save_to: "report.pdf"
|
|
270
|
+
)
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
Do not combine `auth` with an `Authorization` header — the API rejects the conflict.
|
|
274
|
+
|
|
275
|
+
### Job status (async polling)
|
|
276
|
+
|
|
277
|
+
```ruby
|
|
278
|
+
status = client.get_job_status("job_abc123")
|
|
279
|
+
puts status.presigned_url if status.status == "success"
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
---
|
|
283
|
+
|
|
284
|
+
## Error Handling
|
|
285
|
+
|
|
286
|
+
```ruby
|
|
287
|
+
begin
|
|
288
|
+
client.v2.perceive("https://example.com")
|
|
289
|
+
rescue Enconvert::AuthenticationError
|
|
290
|
+
warn "Invalid API key"
|
|
291
|
+
rescue Enconvert::QuotaError
|
|
292
|
+
warn "Plan feature off or quota exhausted"
|
|
293
|
+
rescue Enconvert::RateLimitError
|
|
294
|
+
warn "Too many requests — slow down"
|
|
295
|
+
rescue Enconvert::APIError => e
|
|
296
|
+
warn "API error [#{e.status_code}]: #{e.message}"
|
|
297
|
+
end
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
## Configuration
|
|
301
|
+
|
|
302
|
+
```ruby
|
|
303
|
+
client = Enconvert::Client.new(
|
|
304
|
+
api_key: "sk_...",
|
|
305
|
+
timeout: 300, # seconds, default
|
|
306
|
+
base_url: "https://api.enconvert.com" # override, default shown
|
|
307
|
+
)
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
## Get an API Key
|
|
311
|
+
|
|
312
|
+
Sign up at [enconvert.com](https://enconvert.com). Free tier: 100 ops/month, no credit card.
|
|
313
|
+
|
|
314
|
+
## License
|
|
315
|
+
|
|
316
|
+
MIT
|