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.

Módulo: 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.

No combines 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 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",
})
Aquí solo se respeta 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.
Tres opciones están declaradas pero aún no operativas. 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.

Los diffs de instantáneas contienen contenido de página no confiable. 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:

  1. 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.
  2. Si esa solicitud vuelve con >= 500, el cliente pasa en silencio a GET /v1/convert/status/{job_id}, sondeando cada 3 segundos.
  3. Con success devuelve el resultado. Con failed devuelve *APIError con estado 500 y el mensaje del servidor.
  4. El plazo de sondeo es de 5 minutos, tras los cuales recibes un *APIError con estado 504 y el mensaje Conversion 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)
}
Los lotes de sitios web se quedan fuera a propósito. 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.

Nunca incrustes la clave de API en el código. Léela de una variable de entorno o de tu gestor de secretos, y mantenla en el servidor. Cualquiera que tenga tu clave privada puede ejecutar conversiones contra tu proyecto.

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.