SDK de Conversión de Archivos para Go#
github.com/conversionapi/go-sdk es el cliente oficial de EnConvert para Go 1.21 y posteriores. Se importa como paquete enconvert y no arrastra ninguna dependencia de terceros: todo funciona sobre net/http, encoding/json y mime/multipart. Doce métodos del cliente cubren conversión de archivos, renderizado de URLs y lotes de sitios completos (DOCX a PDF, HEIC a WebP, URL a PDF, URL a Markdown), y el espacio de nombres client.V2 añade veintitrés métodos de inteligencia web para percibir, descubrir, buscar, destilar, ingerir y vigilar páginas. Cada llamada recibe primero un context.Context, así que la cancelación y los plazos siguen en tus manos.
github.com/conversionapi/go-sdk · Paquete: enconvert · Fuente: conversionapi/go-sdk · Go: 1.21+ · Dependencias: ninguna
Instalación#
go get github.com/conversionapi/go-sdk
La ruta del módulo termina en go-sdk pero el paquete se llama enconvert, así que impórtalo con un nombre explícito: import enconvert "github.com/conversionapi/go-sdk".
Inicio rápido#
package main
import (
"context"
"fmt"
"log"
"os"
enconvert "github.com/conversionapi/go-sdk"
)
func main() {
client, err := enconvert.New(os.Getenv("ENCONVERT_API_KEY"))
if err != nil {
log.Fatal(err)
}
ctx := context.Background()
result, err := client.ConvertURLToPDF(ctx, "https://example.com", enconvert.URLToPDFOptions{SaveTo: "page.pdf"})
if err != nil {
log.Fatal(err)
}
fmt.Println(result.Filename, result.PresignedURL)
}
New devuelve un error solo cuando la clave de API está vacía; consulta Configuración para las opciones funcionales. Leer una página como debería leerla un agente, con una puntuación de calidad adjunta, es una sola llamada al espacio de nombres V2:
op, err := client.V2.Perceive(ctx, "https://example.com", enconvert.PerceiveOptions{
Outputs: []enconvert.PerceiveOutputName{enconvert.PerceiveOutputMarkdown},
})
fmt.Println(op.Outputs["markdown"].URL, *op.RenderQuality) // p. ej. 0.93
Cada fragmento de abajo asume un client y un ctx construidos exactamente así.
Qué expone el cliente#
Doce métodos cuelgan de *enconvert.Client y se corresponden 1:1 con endpoints REST. Las opciones siempre se pasan como un valor de struct, nunca como un puntero, así que el valor cero (enconvert.URLToPDFOptions{}) significa "todos los valores predeterminados", y los números y booleanos opcionales son campos puntero en toda la superficie: usa los ayudantes enconvert.Int, enconvert.Bool, enconvert.Float64 y enconvert.String en lugar de una variable local desechable.
| Método | Endpoint | Devuelve |
|---|---|---|
ConvertURLToPDF(ctx, url, opts) |
POST /v1/convert/url-to-pdf |
ConversionResult |
ConvertURLToScreenshot(ctx, url, opts) |
POST /v1/convert/url-to-screenshot |
ConversionResult |
ConvertURLToMarkdown(ctx, url, opts) |
POST /v1/convert/url-to-markdown |
ConversionResult |
ConvertImage(ctx, file, opts) |
POST /v1/convert/{from}-to-{to} |
ConversionResult |
ConvertDocument(ctx, file, opts) |
POST /v1/convert/{from}-to-{to} |
ConversionResult |
ConvertToMarkdown(ctx, file, opts) |
POST /v1/convert/anything-to-markdown |
ConversionResult |
ConvertToPDF(ctx, file, opts) |
POST /v1/convert/anything-to-pdf |
ConversionResult |
ConvertWebsiteToPDF(ctx, url, opts) |
POST /v1/convert/website-to-pdf |
BatchSubmission |
ConvertWebsiteToScreenshot(ctx, url, opts) |
POST /v1/convert/website-to-screenshot |
BatchSubmission |
GetJobStatus(ctx, jobID) |
GET /v1/convert/status/{jobID} |
JobStatus |
GetBatchStatus(ctx, batchID) |
GET /v1/convert/batch/{batchID} |
BatchStatus |
WaitForBatch(ctx, batchID, opts) |
GET /v1/convert/batch/{batchID} (sondeado) |
BatchStatus |
client.V2 guarda veintitrés métodos más repartidos en seis grupos de capacidades:
| Grupo | Métodos | Ruta base |
|---|---|---|
| Perceive | Perceive, PerceiveDirect, GetPerceiveOperation, DownloadPerceiveArtifact, PerceiveBatch, GetPerceiveBatch |
/v2/perceive |
| Discover | Discover |
/v2/discover |
| Lookup | Lookup |
/v2/lookup |
| Distill | Distill |
/v2/distill |
| Ingest | Ingest, IngestFiles, GetIngestJob, ListIngestJobs, CancelIngestJob, RetryIngestWebhook, GetWebhookSecret, RotateWebhookSecret |
/v2/ingest |
| Watch | CreateWatcher, ListWatchers, GetWatcher, GetWatcherSnapshots, UpdateWatcher, DeleteWatcher |
/v2/watch |
Conversión de archivos#
Las subidas aceptan cualquier FileSource: enconvert.FilePath("report.docx") para una ruta en disco (el nombre base decide el formato de entrada y el tipo MIME), enconvert.FileBytes(buf) para bytes en bruto sin nombre (se suben como upload.bin, application/octet-stream), o enconvert.FileInput{Data: buf, Filename: "report.docx"} para bytes en bruto con un nombre de archivo explícito y un ContentType opcional.
ConvertURLToPDF#
Renderiza a PDF cualquier URL accesible.
result, err := client.ConvertURLToPDF(ctx, "https://example.com", enconvert.URLToPDFOptions{
SinglePage: enconvert.Bool(false),
PDFOptions: &enconvert.PDFOptions{PageSize: "A4", Orientation: "landscape"},
URLRenderOptions: enconvert.URLRenderOptions{ViewportWidth: enconvert.Int(1440)},
SaveTo: "report.pdf",
})
| Opción | Tipo | Predeterminado | Descripción |
|---|---|---|---|
SaveTo |
string |
-- | Ruta local a la que transmitir el PDF. Los directorios padre se crean por ti. |
SinglePage |
*bool |
true |
true renderiza una única página continua. false pagina usando PDFOptions.PageSize. |
PDFOptions |
*PDFOptions |
-- | Tamaño de página, orientación, márgenes, escala, escala de grises, encabezado, pie. Consulta Opciones de PDF. |
ViewportWidth, ViewportHeight |
*int |
1920, 1080 |
Tamaño del viewport del navegador en píxeles. |
LoadMedia |
*bool |
true |
Espera a las imágenes y el vídeo antes de capturar. |
EnableScroll |
*bool |
true |
Hace scroll de arriba abajo para disparar la carga diferida. |
OutputFilename |
string |
automático | Sustituye el nombre de archivo generado. |
Auth |
*HTTPBasicAuth |
-- | Credenciales HTTP Basic para páginas tras un inicio de sesión. |
Cookies, Headers |
[]BrowserCookie, map[string]string |
-- | Cookies inyectadas antes de renderizar (máximo 50) y encabezados de solicitud adicionales (máximo 20, los hop-by-hop se rechazan). |
Todo lo que va de ViewportWidth hacia abajo vive en el struct embebido URLRenderOptions, compartido por todos los métodos basados en URL.
Auth con un encabezado Authorization. La API rechaza el conflicto en lugar de adivinar cuál de los dos querías.
ConvertURLToScreenshot y ConvertURLToMarkdown#
Captura un PNG de cualquier URL, o extrae Markdown limpio con sabor GitHub y frontmatter YAML (título, descripción, url, enlaces, imágenes). El conversor de Markdown elimina navegación, pies de página, anuncios y scripts, y conserva el cuerpo principal del artículo.
shot, err := client.ConvertURLToScreenshot(ctx, "https://example.com", enconvert.URLToScreenshotOptions{
URLRenderOptions: enconvert.URLRenderOptions{ViewportWidth: enconvert.Int(1440)},
SaveTo: "shot.png",
})
article, err := client.ConvertURLToMarkdown(ctx, "https://example.com/article",
enconvert.URLToMarkdownOptions{SaveTo: "article.md"})
Ambos toman las mismas URLRenderOptions que ConvertURLToPDF, más SaveTo. Ninguno acepta SinglePage ni PDFOptions.
ConvertImage#
Convierte entre jpeg, png, svg, heic y webp en cualquier dirección, o rasteriza un PDF a JPEG.
// Desde una ruta
result, err := client.ConvertImage(ctx, enconvert.FilePath("photo.heic"),
enconvert.ConvertImageOptions{OutputFormat: "webp", SaveTo: "photo.webp"})
// Desde bytes que ya están en memoria
buf, _ := os.ReadFile("photo.heic")
result, err = client.ConvertImage(ctx, enconvert.FileInput{Data: buf, Filename: "photo.heic"},
enconvert.ConvertImageOptions{OutputFormat: "webp", SaveTo: "photo.webp"})
| Opción | Tipo | Obligatorio | Descripción |
|---|---|---|---|
OutputFormat |
string |
Sí | jpeg, png, svg, heic o webp. jpg se acepta como alias de jpeg. |
SaveTo |
string |
-- | Ruta local a la que transmitir el resultado. |
OutputFilename |
string |
-- | Sustituye el nombre de archivo generado. |
El formato de entrada sale de la extensión del nombre de archivo (.jpg, .jpeg, .png, .svg, .heic, .webp, .pdf). Los pares no admitidos fallan localmente, antes de cualquier llamada de red, con un error que enumera lo que sí está disponible:
enconvert.ValidOutputsFor("pdf") // []string{"jpeg"}
enconvert.ValidOutputsFor("json") // []string{"csv", "toml", "xml", "yaml"}
ConvertDocument#
Convierte documentos y formatos de datos. OutputFormat vale pdf por defecto cuando se deja vacío.
// docx a pdf
_, err := client.ConvertDocument(ctx, enconvert.FilePath("report.docx"),
enconvert.ConvertDocumentOptions{SaveTo: "report.pdf"})
// json a yaml
_, err = client.ConvertDocument(ctx, enconvert.FilePath("data.json"),
enconvert.ConvertDocumentOptions{OutputFormat: "yaml", SaveTo: "data.yaml"})
Entradas admitidas: .doc, .docx, .xls, .xlsx, .ppt, .pptx, .html, .htm, .odt, .ods, .odp, .ots, .pages, .numbers, .md, .markdown, .csv, .json, .xml, .yaml, .yml, .toml.
| Opción | Tipo | Predeterminado | Descripción |
|---|---|---|---|
OutputFormat |
string |
"pdf" |
Formato de destino. yml, htm, md y jpg se normalizan a sus nombres canónicos. |
SaveTo |
string |
-- | Ruta local a la que transmitir el resultado. |
OutputFilename |
string |
-- | Sustituye el nombre de archivo generado. |
PDFOptions |
*PDFOptions |
-- | Configuración de página. Solo tiene sentido cuando la salida es PDF. |
Los 43 pares implementados, expuestos como el mapa enconvert.ImplementedConversions, son: json a csv, toml, xml, yaml; xml a csv, json; yaml a json; csv a json, xml; toml a json; markdown a html, pdf; html a pdf; doc, excel, ppt, odt, ods, odp, ots, pages y numbers a pdf; los 20 pares ordenados entre jpeg, png, svg, heic, webp; y pdf a jpeg.
EPUB no tiene un par de documentos propio. Envía los archivos .epub a través de ConvertToPDF o ConvertToMarkdown en su lugar.
ConvertToMarkdown#
Detecta automáticamente la entrada en el servidor y devuelve Markdown limpio. Este es el bloque de construcción de ingesta para RAG: PDF, DOCX, PPTX, XLSX, CSV, HTML, EPUB, TXT y MD, más formatos de ofimática heredados y ODF.
_, err := client.ConvertToMarkdown(ctx, enconvert.FilePath("handbook.pdf"),
enconvert.ConvertToMarkdownOptions{SaveTo: "handbook.md"})
ConvertToMarkdownOptions tiene dos campos, SaveTo y OutputFilename. Este endpoint no admite imágenes y no tiene opciones de PDF. La salida conserva la jerarquía de encabezados del documento, así que un chunker semántico puede dividir por encabezados en lugar de por recuentos arbitrarios de caracteres.
ConvertToPDF#
Detecta automáticamente la entrada en el servidor y devuelve un PDF: ofimática, ODF, Pages, Numbers, RTF, CSV, HTML, Markdown, texto plano, imágenes rasterizadas, SVG, EPUB o un PDF existente pasado directamente para normalizarlo.
_, err := client.ConvertToPDF(ctx, enconvert.FilePath("slides.pptx"),
enconvert.ConvertToPDFOptions{SaveTo: "slides.pdf"})
// Paso directo de PDF, convertido a escala de grises
_, err = client.ConvertToPDF(ctx, enconvert.FilePath("scan.pdf"), enconvert.ConvertToPDFOptions{
PDFOptions: &enconvert.PDFOptions{Grayscale: enconvert.Bool(true)},
SaveTo: "scan-gray.pdf",
})
PDFOptions.Grayscale. Cualquier otro campo de geometría se ignora en anything-to-pdf. Usa ConvertDocument o ConvertURLToPDF cuando necesites tamaño de página, orientación, márgenes, escala, encabezados o pies.
ConvertToPDFOptions tiene tres campos: SaveTo, OutputFilename y PDFOptions.
ConvertWebsiteToPDF y ConvertWebsiteToScreenshot#
Descubre todas las páginas de un sitio, convierte cada una en segundo plano y recoge un único ZIP. Ambos son solo asíncronos: devuelven un BatchSubmission, y sondeas con GetBatchStatus o bloqueas con WaitForBatch. Hace falta una clave de API privada con acceso de rastreo.
batch, err := client.ConvertWebsiteToPDF(ctx, "https://example.com", enconvert.WebsiteToPDFOptions{
WebsiteConversionOptions: enconvert.WebsiteConversionOptions{CrawlMode: enconvert.CrawlModeSitemap},
})
status, err := client.WaitForBatch(ctx, batch.BatchID, enconvert.WaitForBatchOptions{SaveTo: "site.zip"})
fmt.Println(status.Completed, "of", status.Total, "pages converted")
| Opción | Tipo | Predeterminado | Descripción |
|---|---|---|---|
CrawlMode |
CrawlMode |
auto |
CrawlModeAuto, CrawlModeSitemap (solo sitemap.xml) o CrawlModeFull (sitemap más rastreo BFS). |
IncludePatterns |
[]string |
-- | Rastrea solo las URLs que casan con estos patrones, en modo de rastreo completo. |
ExcludePatterns |
[]string |
-- | Omite las URLs que casan con estos patrones, en modo de rastreo completo. |
NotificationEmail |
string |
propietario del proyecto | Dirección avisada cuando termina el lote. |
CallbackURL |
string |
-- | Webhook al que se hace POST cuando termina el lote. |
SinglePage |
*bool |
valor del servidor | Solo PDF. Página continua frente a paginada. |
PDFOptions |
*PDFOptions |
-- | Solo PDF. Se aplica a cada página. |
Todo lo de URLRenderOptions se acepta aquí también, y se envía por página solo cuando lo fijas. WaitForBatchOptions toma Interval (predeterminado 5 segundos), Timeout (predeterminado 30 minutos) y SaveTo. Reventar el tiempo de espera devuelve un *APIError con estado 504; un lote terminado sin ZIP devuelve uno con estado 500. ConvertWebsiteToScreenshot es idéntico menos SinglePage y PDFOptions, y produce un ZIP de PNGs.
Inteligencia web (V2)#
Cada lectura de V2 lleva una puntuación RenderQuality de 0.0 a 1.0, expuesta como un *float64 en PerceiveResult, DistillItem, WatcherSnapshot y el resultado de descarga directa. Una puntuación baja significa que la página no se renderizó limpiamente: una página de desafío, un muro de cookies, el shell vacío de una SPA, un error HTTP. El contenido vuelve igualmente, marcado, junto a un mapa Deductions que nombra cada penalización que se activó y un slice Warnings, de modo que una lectura defectuosa nunca entra sin ruido en el contexto de tu agente. Todos los métodos de V2 requieren una clave de API privada; las claves públicas se rechazan. Usa la puntuación como barrera antes de confiar en nada:
if op.RenderQuality != nil && *op.RenderQuality < 0.6 {
log.Printf("low quality read of %s: %v", op.URL, op.Deductions)
}
Perceive#
Renderiza una URL y produce los artefactos que pidas. Síncrono, con URLs de artefacto firmadas durante 15 minutos.
op, err := client.V2.Perceive(ctx, "https://example.com", enconvert.PerceiveOptions{
Outputs: []enconvert.PerceiveOutputName{enconvert.PerceiveOutputMarkdown, enconvert.PerceiveOutputStructured},
Extract: []enconvert.PerceiveExtractName{enconvert.PerceiveExtractTables, enconvert.PerceiveExtractMetadata},
Viewport: &enconvert.PerceiveViewport{Width: enconvert.Int(1440)},
})
fmt.Println(op.OperationID, op.Outputs["markdown"].URL, op.Structured, op.ExtractionTier)
// Vuelve a firmar las URLs de los artefactos más tarde
again, err := client.V2.GetPerceiveOperation(ctx, op.OperationID)
| Opción | Tipo | Predeterminado | Descripción |
|---|---|---|---|
Outputs |
[]PerceiveOutputName |
markdown, structured |
markdown, html_cleaned, html_raw, screenshot, screenshot_full_page, pdf, links, images, structured. |
Extract |
[]PerceiveExtractName |
-- | tables, prices, contacts, metadata, main_content, headings, structured_data, technologies, all. |
Schema |
map[string]any |
-- | Esquema JSON para la extracción estructurada a través del nivel de LLM. |
WaitFor, WaitTimeoutMs |
string, *int |
30000 ms |
Un selector CSS, opcionalmente con el prefijo css:, o js:<expr>, y su presupuesto (de 0 a 60000). |
JSCode |
string |
-- | JavaScript ejecutado tras la navegación, máximo 20000 caracteres. |
Viewport |
*PerceiveViewport |
1920 x 1080 | Width de 320 a 3840, Height de 240 a 2160. |
Headers, Cookies, Auth |
map[string]string, []BrowserCookie, *HTTPBasicAuth |
-- | Encabezados de solicitud, cookies inyectadas, credenciales HTTP Basic. |
CacheMode |
PerceiveCacheMode |
enabled |
enabled (caché de 1 hora), bypass, refresh. |
PDFOptions |
*PDFOptions |
-- | Solo tiene sentido cuando Outputs incluye pdf. |
BlockResources |
[]PerceiveResourceType |
-- | image, media, font, stylesheet, script, xhr, fetch, websocket, manifest, other. |
RespectRobots, Mobile |
*bool |
valor del servidor | Respeta robots.txt; emula un dispositivo móvil. |
OnlyMainContent |
*bool |
true |
Elimina navegación, encabezado, pie y avisos de cookies del artefacto markdown y del extracto main_content. Ponlo en false para la página completa. |
DirectDownload |
*bool |
false |
Transmite bytes en bruto en lugar de un sobre JSON. Es preferible PerceiveDirect. |
ProxyURL, Geolocation y ActionChain las acepta el struct de Go y se serializan, pero el servidor responde actualmente 422 para las tres. Déjalas sin fijar.
Transmitir un único artefacto directamente al disco se salta el sobre JSON. PerceiveDirect valida localmente que pediste exactamente una salida que produce artefacto:
direct, err := client.V2.PerceiveDirect(ctx, "https://example.com", enconvert.PerceiveOptions{
Outputs: []enconvert.PerceiveOutputName{enconvert.PerceiveOutputPDF},
})
os.WriteFile(direct.Filename, direct.Content, 0o644)
// Vuelve a descargar más tarde un artefacto almacenado. Pasa "" cuando la operación produjo solo uno.
saved, err := client.V2.DownloadPerceiveArtifact(ctx, direct.OperationID, enconvert.PerceiveOutputPDF)
PerceiveDirectResult lleva Content, ContentType, Filename, OperationID, ObjectKey, CacheHit, RenderQuality, SourceStatusCode, ContentHash y WarningsCount, todos leídos de los encabezados de la respuesta. Un *APIError con 410 desde DownloadPerceiveArtifact significa que el artefacto ha superado su ventana de retención.
Los lotes aceptan hasta 1000 URLs con un único bloque de opciones compartido. Los lotes pequeños terminan inline; los mayores vuelven como queued, así que sondea GetPerceiveBatch hasta que Status sea PerceiveBatchStatusCompleted y lee Zip o Items:
batch, err := client.V2.PerceiveBatch(ctx, []string{"https://a.example", "https://b.example"},
enconvert.PerceiveBatchOptions{OutputMode: enconvert.PerceiveBatchOutputZip})
done, err := client.V2.GetPerceiveBatch(ctx, batch.JobID)
OutputMode es PerceiveBatchOutputManifest (predeterminado) o PerceiveBatchOutputZip. DirectDownload se rechaza con 422 en los lotes.
Discover#
Enumera las URLs de un sitio desde su sitemap, un rastreo HTTP o ambos. No se arranca ningún navegador, así que es rápido y barato.
found, err := client.V2.Discover(ctx, "https://example.com", enconvert.DiscoverOptions{
Mode: enconvert.DiscoverModeHybrid, MaxURLs: enconvert.Int(200), ExcludePatterns: []string{"/tag/"},
})
fmt.Println(found.Total, found.Truncated, found.Sources)
| Opción | Tipo | Predeterminado | Descripción |
|---|---|---|---|
Mode |
DiscoverMode |
hybrid |
DiscoverModeSitemap, DiscoverModeCrawl o DiscoverModeHybrid (sitemap más rastreo HTTP). |
MaxURLs, MaxDepth |
*int |
100, 2 |
De 1 a 1000 URLs, profundidad de rastreo de 1 a 5. |
IncludePatterns, ExcludePatterns |
[]string |
-- | Lista de permitidos por regex y luego de denegados, con semántica de re.search, máximo 50 cada una. |
SameDomainOnly |
*bool |
true |
Se queda en el dominio de la URL semilla. |
RespectRobots |
*bool |
valor del servidor | Respeta robots.txt. |
DiscoverResult te da URL, Mode, Total, URLs, PagesCrawled, Truncated, RobotsRespected, Sources (recuentos brutos por fuente antes de deduplicar) y Warnings.
Lookup#
Búsqueda web categorizada, renderizando opcionalmente los primeros resultados en el mismo viaje de ida y vuelta.
search, err := client.V2.Lookup(ctx, "best static site generators", enconvert.LookupOptions{
Category: enconvert.LookupCategoryWeb, NumResults: enconvert.Int(10), PerceiveTop: enconvert.Int(3),
})
for _, hit := range search.Results {
fmt.Println(hit.Position, hit.Title, hit.URL)
if hit.Perceive != nil {
fmt.Println(hit.Perceive.Outputs["markdown"].URL)
}
}
| Opción | Tipo | Predeterminado | Descripción |
|---|---|---|---|
Category |
LookupCategory |
web |
web, news, images, scholar, patents, maps. |
Country, Locale |
string |
-- | Código de país gl de Google (us, in) e idioma de interfaz hl (en). |
TimeFilter |
LookupTimeFilter |
-- | hour, day, week, month, year. |
NumResults, Page |
*int |
10, 1 |
De 1 a 100 resultados, página de 1 a 10. |
Location |
string |
-- | Ubicación en texto libre, por ejemplo Austin, Texas. |
Autocorrect |
*bool |
true |
Deja que el proveedor corrija erratas de la consulta. |
PerceiveTop |
*int |
0 |
De 0 a 10. Ejecuta un renderizado completo en el navegador de las N primeras URLs de resultados y adjunta cada PerceiveResult inline. |
LookupResult lleva además AnswerBox, KnowledgeGraph, PerceiveOperationIDs y Warnings.
Distill#
Extracción estructurada guiada por esquema. Proporciona exactamente uno de URLs (máximo 50) o DiscoverFrom; Schema siempre es obligatorio. Ambas reglas se comprueban localmente antes de que salga ninguna solicitud.
extraction, err := client.V2.Distill(ctx, enconvert.DistillOptions{
URLs: []string{"https://example.com/pricing"},
Schema: map[string]any{"plans": "list of plan names with monthly prices"},
CSSSchema: &enconvert.CSSSchema{
BaseSelector: ".plan-card",
Fields: []enconvert.CSSField{
{Name: "name", Type: enconvert.CSSFieldText, Selector: "h3"},
{Name: "price", Type: enconvert.CSSFieldText, Selector: ".price"},
},
},
})
first := extraction.Results[0]
fmt.Println(first.Data, first.ExtractionTier, first.FieldsFromCSS, first.FieldsFromLLM)
El CSSSchema opcional se ejecuta primero y responde todo lo que puede con selectores simples; solo los campos que no cubre escalan al nivel de LLM, y ExtractionTier informa de qué niveles respondieron realmente (css, llm, mixed o none). CSSField.Type es uno de text, attribute, html, regex, nested, list o nested_list, anidado hasta 5 niveles de profundidad.
Cambia URLs por DiscoverFrom para descubrir y luego destilar en una sola llamada. DistillDiscoverFrom toma URL, Mode (predeterminado hybrid) y MaxPages (de 1 a 50, predeterminado 10, que limita tanto el descubrimiento como la destilación):
_, err = client.V2.Distill(ctx, enconvert.DistillOptions{
DiscoverFrom: &enconvert.DistillDiscoverFrom{URL: "https://example.com", MaxPages: enconvert.Int(10)},
Schema: map[string]any{"title": "page title", "summary": "one-line summary"},
})
Ingest#
Convierte un sitio, una lista de URLs o una pila de documentos subidos en JSONL fragmentado y listo para RAG. Siempre asíncrono.
job, err := client.V2.Ingest(ctx, enconvert.IngestOptions{
Mode: enconvert.IngestModeSitemap,
URL: "https://docs.example.com",
MaxPages: enconvert.Int(100),
Chunk: &enconvert.IngestChunkOptions{MaxWords: enconvert.Int(512), SentenceOverlap: enconvert.Int(1)},
WebhookURL: "https://my.app/hooks/enconvert",
})
status, err := client.V2.GetIngestJob(ctx, job.JobID)
if status.Status == enconvert.IngestStatusCompleted {
fmt.Println(status.TotalChunks, status.OutputURL)
}
| Opción | Tipo | Predeterminado | Descripción |
|---|---|---|---|
Mode |
IngestMode |
urls |
IngestModeURLs, IngestModeSitemap, IngestModeCrawl, IngestModeFiles. |
URL |
string |
-- | URL semilla. Obligatoria para sitemap y crawl, prohibida para urls. |
URLs |
[]string |
-- | URLs explícitas, máximo 1000. Obligatorias para urls, prohibidas en los demás casos. |
MaxPages, MaxDepth |
*int |
50, 2 |
Tope de descubrimiento de 1 a 1000 para sitemap y crawl, profundidad de 1 a 5. |
SameDomainOnly |
*bool |
true |
Se queda en el dominio de la URL semilla. |
IncludePatterns, ExcludePatterns |
[]string |
-- | Lista de permitidos por regex y luego de denegados. |
RespectRobots |
*bool |
valor del servidor | Respeta robots.txt. |
WaitFor, WaitTimeoutMs |
string, *int |
30000 ms |
Selector o expresión js: que se espera por página, y su presupuesto (de 0 a 60000). |
Chunk |
*IngestChunkOptions |
-- | MaxWords de 32 a 4000, predeterminado 512. SentenceOverlap de 0 a 10, predeterminado 1. |
WebhookURL |
string |
-- | Webhook de finalización, firmado con HMAC. |
Las reglas de modo y URL anteriores se comprueban en el cliente: Ingest devuelve un error simple de Go, no un viaje a la API, si envías URLs con Mode: IngestModeSitemap.
Los archivos subidos recorren el mismo pipeline y el mismo ciclo de vida de trabajo:
fileJob, err := client.V2.IngestFiles(ctx,
[]enconvert.FileSource{enconvert.FilePath("handbook.pdf"), enconvert.FilePath("notes.docx")},
enconvert.IngestFilesOptions{Chunk: &enconvert.IngestChunkOptions{MaxWords: enconvert.Int(512)}})
Se aceptan PDF, DOCX, PPTX, XLSX, CSV, HTML, EPUB, TXT y MD, y archivos de ofimática heredados u ODF; hace falta al menos un archivo. Gestión de trabajos y fontanería de webhooks:
list, err := client.V2.ListIngestJobs(ctx, enconvert.V2ListOptions{Limit: enconvert.Int(20)})
canceled, err := client.V2.CancelIngestJob(ctx, job.JobID) // idempotente
secret, err := client.V2.GetWebhookSecret(ctx) // Secret, SignatureHeader, SignatureScheme, ...
rotated, err := client.V2.RotateWebhookSecret(ctx) // las firmas antiguas dejan de verificarse al instante
retry, err := client.V2.RetryIngestWebhook(ctx, job.JobID)
RetryIngestWebhook responde 409 cuando el trabajo no está completado y 400 cuando no tiene webhook configurado. V2ListOptions toma Skip y Limit (de 1 a 100, predeterminado 20).
Watch#
Vuelve a renderizar una página con una cadencia fija y recibe un aviso cuando cambia.
watcher, err := client.V2.CreateWatcher(ctx, "https://example.com/pricing", enconvert.WatchCreateOptions{
FrequencyMinutes: enconvert.Int(60),
DiffMode: enconvert.WatchDiffAuto,
WebhookURL: "https://my.app/hooks/changes",
})
history, err := client.V2.GetWatcherSnapshots(ctx, watcher.WatcherID, enconvert.SnapshotListOptions{Limit: enconvert.Int(10)})
for _, snap := range history.Snapshots {
fmt.Println(snap.CheckedAt, snap.HasChanges, snap.ChangeCount, snap.Changes)
}
| Opción | Tipo | Predeterminado | Descripción |
|---|---|---|---|
FrequencyMinutes |
*int |
60 |
De 60 a 43200. El mínimo de una hora es estricto. |
DiffMode |
WatchDiffMode |
auto |
WatchDiffAuto, WatchDiffText, WatchDiffStructured, WatchDiffTables, WatchDiffMetadata. |
TrackFields |
map[string]any |
-- | Subconjunto de campos o selectores entregado al motor de diff. |
WebhookURL, NotifyEmail |
string, *bool |
--, true |
Webhook de cambios firmado con HMAC, y si se envía correo al propietario del proyecto. |
// Un puntero a la cadena vacía limpia el webhook; nil lo deja como está.
_, err = client.V2.UpdateWatcher(ctx, watcher.WatcherID, enconvert.WatcherUpdate{
Status: enconvert.WatcherStatusPaused, WebhookURL: enconvert.String(""),
})
_, err = client.V2.DeleteWatcher(ctx, watcher.WatcherID) // borrado suave, idempotente
UpdateWatcher requiere al menos un campo y devuelve un error simple de Go si le entregas un struct vacío. Status solo acepta WatcherStatusActive o WatcherStatusPaused; el borrado se hace con DeleteWatcher, que devuelve el vigilante marcado como eliminado con estado deleted. ListWatchers y GetWatcher completan el grupo.
WatcherSnapshot.Changes es un slice de mapas en bruto tomados de la página vigilada. Escapa los valores antes de renderizarlos en cualquier parte.
Opciones de PDF#
PDFOptions lo comparten ConvertURLToPDF, ConvertDocument, ConvertWebsiteToPDF, PerceiveOptions y (solo para Grayscale) ConvertToPDF. Solo se envían los campos que fijas.
opts := &enconvert.PDFOptions{
PageSize: "A4",
Orientation: "landscape",
Margins: &enconvert.PDFMargins{Top: enconvert.Float64(10), Bottom: enconvert.Float64(10)},
Scale: enconvert.Float64(0.9),
Footer: &enconvert.PDFHeaderFooter{Content: "Confidential", Height: enconvert.Float64(20)},
}
| Campo | Tipo | Descripción |
|---|---|---|
PageSize |
string |
"A4", "A3", "Letter", "Legal" y compañía. |
PageWidth, PageHeight |
*float64 |
Fíjalos juntos para anular PageSize. |
Orientation |
string |
"portrait" o "landscape". Por defecto es vertical. |
Margins |
*PDFMargins |
Top, Bottom, Left, Right, cada uno un *float64 en puntos. Los cuatro son opcionales. |
Scale |
*float64 |
Escala de renderizado, por ejemplo 0.9 para el 90%. |
Grayscale |
*bool |
Posprocesa el PDF a escala de grises. |
Header, Footer |
*PDFHeaderFooter |
Cada uno tiene Content (máximo 2000 caracteres) y Height. |
Manejo de errores#
Go no tiene clases de excepción, así que todo fallo de la API es un único tipo concreto, *enconvert.APIError, más tres predicados. Error() se representa como "[<status>] <message>".
result, err := client.ConvertURLToPDF(ctx, "https://example.com", enconvert.URLToPDFOptions{})
switch {
case err == nil:
fmt.Println(result.PresignedURL)
case enconvert.IsAuthenticationError(err):
log.Println("invalid or missing API key")
case enconvert.IsRateLimitError(err):
log.Println("too many requests, back off and retry")
case enconvert.IsQuotaError(err):
log.Println("request rejected with 402")
default:
var apiErr *enconvert.APIError
if errors.As(err, &apiErr) {
log.Printf("api error [%d]: %s", apiErr.StatusCode, apiErr.Message)
} else {
log.Println(err) // fallo de red, cancelación del contexto, validación local
}
}
| Comprobación | Se lanza en | Código de estado |
|---|---|---|
IsAuthenticationError(err) |
Clave inválida, ausente o revocada | 401, 403 (ambos registrados como 401) |
IsQuotaError(err) |
Cualquier respuesta que la API conteste con 402 |
402 |
IsRateLimitError(err) |
Límite de tasa superado | 429 |
errors.As(err, &apiErr) |
Cualquier otro 4xx o 5xx | el código real |
Los errores que nunca llegan a la red, como un par de conversión no admitido, una llamada a Distill con URLs y DiscoverFrom a la vez, o una llamada a PerceiveDirect que pide dos artefactos, vuelven como valores error simples de errors.New o fmt.Errorf, no como *APIError. Los códigos de respuesta están catalogados en la referencia de códigos de error.
Recuperación de tiempos de espera#
Los renderizados largos de URLs y las conversiones de documentos grandes pueden sobrevivir al techo de 60 a 120 segundos de un proxy inverso incluso cuando el trabajo termina bien en el servidor. El SDK se abre paso a base de sondeo, sin código por tu parte:
- Antes de cada conversión de un solo archivo y de una sola URL, el cliente genera un UUIDv4 y lo envía como
job_id. - Si esa solicitud vuelve con
>= 500, el cliente pasa en silencio aGET /v1/convert/status/{job_id}, sondeando cada 3 segundos. - Con
successdevuelve el resultado. Confaileddevuelve*APIErrorcon estado500y el mensaje del servidor. - El plazo de sondeo es de 5 minutos, tras los cuales recibes un
*APIErrorcon estado504y el mensajeConversion timed out.
ConversionResult.JobID siempre queda poblado, incluso cuando la vía síncrona tuvo éxito y la respuesta lo omitió, así que puedes entregárselo tú mismo a GetJobStatus:
status, err := client.GetJobStatus(ctx, result.JobID)
switch status.Status {
case enconvert.JobStatusSuccess:
fmt.Println(status.PresignedURL)
case enconvert.JobStatusFailed:
log.Println(status.Error)
}
ConvertWebsiteToPDF y ConvertWebsiteToScreenshot no tienen fila por trabajo que sondear, así que un 5xx ahí sale a la superficie de inmediato en lugar de reintentarse. Los métodos de V2 tampoco usan la vía alternativa de trabajos. El sondeo se ejecuta dentro del context.Context que pasas, así que cancelar el contexto aborta la espera al instante.
Configuración#
client, err := enconvert.New(os.Getenv("ENCONVERT_API_KEY"),
enconvert.WithTimeout(300*time.Second),
enconvert.WithBaseURL("https://api.enconvert.com"),
)
| Entrada del constructor | Tipo | Predeterminado | Descripción |
|---|---|---|---|
apiKey (primer argumento) |
string |
obligatorio | Clave de API privada. New devuelve un error cuando está vacía. |
WithTimeout(d) |
time.Duration |
300 * time.Second |
Fija Timeout en el *http.Client interno, cubriendo también las descargas. |
WithBaseURL(u) |
string |
https://api.enconvert.com |
Sustitución para un gateway autoalojado. Las barras finales se eliminan. |
Los plazos por llamada se superponen al tiempo de espera del cliente a través del contexto: envuélvelo con context.WithTimeout(context.Background(), 30*time.Second) y pásalo como primer argumento.
El cliente se puede compartir entre goroutines con seguridad: guarda un *http.Client y ningún estado mutable por solicitud. Construye uno al arrancar y reutilízalo. Consulta autenticación para los tipos de clave y la rotación.
Forma del resultado#
Las conversiones de un solo archivo y de una sola URL devuelven un ConversionResult:
type ConversionResult struct {
PresignedURL string // URL de descarga firmada de la salida
ObjectKey string // clave del objeto en el almacenamiento
Filename string // nombre de archivo del lado del servidor
FileSize *int64 // bytes, nil cuando la API lo omite
ConversionTimeSeconds *float64 // nil cuando la API lo omite
JobID string // siempre lo fija el cliente
}
Las URLs prefirmadas son de corta duración. Pasa SaveTo para que el SDK transmita los bytes al disco por ti, o busca la URL tú mismo y guarda el archivo en tu propio bucket si necesitas acceso a largo plazo. La descarga deliberadamente no lleva tu clave de API, ya que una URL prefirmada se autentica sola y reenviar la clave a un host de almacenamiento la filtraría.
Los artefactos de V2 llegan como valores V2OutputArtifact indexados por nombre de salida, cada uno con URL (prefirmada durante 15 minutos y vuelta a firmar en cada GET de estado), ObjectKey, SizeBytes, ContentType y ExpiresIn (900 segundos por defecto). PerceiveResult los envuelve con los metadatos de honestidad: RenderQuality, StatusCode, Deductions, CacheHit, Warnings, ContentHash, URLFinal, Structured, ExtractionTier, Tokens, CostCents, DurationMs y OptionsEcho, que devuelve como eco las opciones que el servidor respetó realmente, con los secretos reducidos a booleanos.
Código fuente e incidencias#
- Módulo y fuente: github.com/conversionapi/go-sdk
- Versión: expuesta en tiempo de ejecución como la constante
enconvert.Version - Licencia: MIT, sin dependencias de terceros
Lectura relacionada: todos los SDKs, resumen de V2, perceive, discover, lookup, distill, ingest, watch, resumen de endpoints, parámetros y opciones y tu panel de control para las claves.
Preguntas frecuentes#
¿Cómo convierto archivos en Go?#
Ejecuta go get github.com/conversionapi/go-sdk, construye un cliente con enconvert.New(os.Getenv("ENCONVERT_API_KEY")) y luego llama a un método tipado como ConvertDocument, ConvertImage o ConvertURLToPDF. Pasa SaveTo en el struct de opciones y el SDK transmite el archivo terminado directamente a esa ruta, creando los directorios padre que hagan falta.
¿Cómo convierto una URL a PDF en Go?#
Llama a client.ConvertURLToPDF(ctx, url, enconvert.URLToPDFOptions{SaveTo: "page.pdf"}). Fija SinglePage: enconvert.Bool(false) para paginar en lugar de producir una única página continua, y pasa PDFOptions para el tamaño de página, la orientación, los márgenes, la escala, la escala de grises, los encabezados y los pies.
¿Cómo convierto DOCX a PDF en Go?#
client.ConvertDocument(ctx, enconvert.FilePath("report.docx"), enconvert.ConvertDocumentOptions{SaveTo: "report.pdf"}). El formato de salida vale pdf por defecto, así que puedes dejar OutputFormat vacío. El mismo método gestiona entradas XLSX, PPTX, ODT, ODS, ODP, OTS, Pages, Numbers, HTML, Markdown, CSV, JSON, XML, YAML y TOML.
¿Cómo convierto HEIC a WebP en Go?#
client.ConvertImage(ctx, enconvert.FilePath("photo.heic"), enconvert.ConvertImageOptions{OutputFormat: "webp", SaveTo: "photo.webp"}). El formato de entrada se lee de la extensión del nombre de archivo, y los 20 pares ordenados entre jpeg, png, svg, heic y webp funcionan igual. Los pares no admitidos fallan localmente antes de enviar ninguna solicitud.
¿El SDK de Go arrastra alguna dependencia de terceros?#
No. go.mod declara el módulo y un mínimo de Go 1.21, y nada más. El cliente está construido sobre net/http, encoding/json, mime/multipart y crypto/rand de la librería estándar, así que no añade ninguna cadena de suministro transitiva a tu build.
¿Cómo extraigo una página web a Markdown limpio en Go?#
Dos opciones. client.ConvertURLToMarkdown devuelve Markdown con sabor GitHub y frontmatter YAML, y es la vía más simple. client.V2.Perceive con Outputs: []enconvert.PerceiveOutputName{enconvert.PerceiveOutputMarkdown} te da el mismo Markdown más una puntuación RenderQuality, Deductions, Warnings y la opción de añadir capturas de pantalla, enlaces o extracción estructurada en el mismo renderizado.
¿Qué significa la calidad de renderizado y por qué debería revisarla?#
RenderQuality es un *float64 de 0.0 a 1.0 adjunto a cada lectura de V2. Baja cuando la página no se renderizó con honestidad: un desafío antibot, un muro de inicio de sesión, un aviso de cookies sobre un shell vacío o un estado de error HTTP. El contenido se sigue devolviendo en lugar de tragárselo, así que revisa la puntuación (y el mapa Deductions que nombra cada penalización) antes de darle el texto a un modelo.
¿Cómo fijo un tiempo de espera por solicitud o cancelo una conversión en Go?#
Todos los métodos reciben primero un context.Context. Envuélvelo con context.WithTimeout o context.WithCancel para controlarlo llamada a llamada; WithTimeout en el constructor fija el tiempo de espera de base del cliente HTTP para todas las llamadas, incluida la descarga de un archivo con SaveTo.
¿Qué pasa cuando una conversión larga choca con el tiempo de espera del proxy?#
El SDK envía un job_id generado por el cliente con cada conversión de un solo archivo y de una sola URL. Si la solicitud devuelve >= 500, sondea GET /v1/convert/status/{job_id} cada 3 segundos durante hasta 5 minutos, devolviendo el resultado con success y un *APIError con failed. Superar el plazo produce un *APIError con estado 504. Los envíos de lotes de sitios web se saltan deliberadamente esta vía alternativa.
¿Puedo enviar el SDK de Go dentro de un cliente de escritorio o móvil?#
No. Se autentica con una clave de API privada, y los endpoints de V2 rechazan las claves públicas sin más. Mantén el cliente en un servidor que controles y deja que tu aplicación hable con él. Consulta autenticación para el modelo de claves.
¿El cliente de Go es seguro de usar desde varias goroutines?#
Sí. *enconvert.Client envuelve un único *http.Client y no mantiene estado mutable por solicitud, así que construye uno al arrancar y compártelo en todas partes.