The official Pictify SDK for Go provides an idiomatic Go interface for the Pictify API — generate images, PDFs, and GIFs from raw HTML, live URLs, and reusable templates.
Keep your API key secret. Read it from an environment variable (e.g. os.Getenv("PICTIFY_API_KEY")) and never expose it in client-side code or public repositories.
img, err := client.RenderHTML(ctx, &pictify.RenderHTMLOptions{ HTML: `<div class="card">Hello</div>`, CSS: ".card { padding: 40px; color: #0ea5e9; }", // injected as <style> before the HTML Width: 1200, // default 1280 Height: 630, // default 720 Selector: ".card", // optional: crop to an element Format: pictify.FormatPNG, // png (default), jpg, jpeg, webp, pdf})if err != nil { log.Fatal(err)}fmt.Println(img.URL)
The /image endpoint accepts a single html field, so any CSS you pass is injected into a <style> tag prepended to the HTML. Format maps to the endpoint’s fileExtension.
Templates can have multiple layout variants (e.g. landscape, square, story) created via AI Resize in the Pictify editor. Render several at once with RenderLayouts (max 20). Use "default" for the base layout. Layouts that can’t be rendered are returned in result.Errors rather than failing the whole call.
To render a GIF from a template, set TemplateID (and optionally Variables). The source must be animated; a static source returns a render error (HTTP 422).
POST /templates/{uid}/batch-render returns immediately (HTTP 202) with a BatchID. The job runs asynchronously — poll GetBatchResults to track progress.
Rendered URLs are not returned by the poll endpoint; they are delivered via the render.completed webhook. The poll response reports each item’s Index, Success, and variable names (plus an Error on failures).
// Create a template from HTML. Variables are auto-discovered from {{name}} tokens.tmpl, err := client.CreateTemplate(ctx, &pictify.CreateTemplateOptions{ HTML: `<div style="padding:20px">Hi {{firstName}}</div>`, Name: "Welcome Card", Width: 600, Height: 200,})if err != nil { log.Fatal(err)}fmt.Println(tmpl.UID)for _, v := range tmpl.VariableDefinitions { fmt.Printf(" - %s (%s)\n", v.Name, v.Type)}// Fetch a single template by UID.tmpl, err = client.GetTemplate(ctx, "XL13XACH2V")if err != nil { log.Fatal(err)}fmt.Printf("%s: %s (%dx%d)\n", tmpl.UID, tmpl.Name, tmpl.Width, tmpl.Height)// List templates with pagination.list, err := client.ListTemplates(ctx, &pictify.ListTemplatesOptions{ Page: 1, Limit: 20, // max 100, default 12 Sort: "newest", // newest | oldest | name})if err != nil { log.Fatal(err)}for _, t := range list.Templates { fmt.Printf("%s: %s\n", t.UID, t.Name)}fmt.Printf("page %d of %d (%d total)\n", list.Pagination.Page, list.Pagination.TotalPages, list.Pagination.Total)
Template keys by UID (not id) and declares variables in VariableDefinitions. Any unknown engine-specific fields are preserved in Template.Extra (a map[string]json.RawMessage).
HTTP errors are mapped to typed errors. Each one embeds *PictifyError, so you can match either the concrete type or the base with errors.As. The error message resolves as body.error → body.message → HTTP status text.
Status
Error type
401
*AuthenticationError
402
*QuotaExceededError
404
*TemplateNotFoundError
422 / other 4xx
*RenderError (422 carries field-level Errors)
429
*QuotaExceededError (when code == "quota_exceeded") or *RateLimitError
5xx
*ServerError
transport failure
*NetworkError
timeout / context deadline
*TimeoutError
import ( "errors" "github.com/pictify-io/pictify-go")result, err := client.Render(ctx, opts)if err != nil { var authErr *pictify.AuthenticationError var notFoundErr *pictify.TemplateNotFoundError var rateLimitErr *pictify.RateLimitError var quotaErr *pictify.QuotaExceededError var renderErr *pictify.RenderError var serverErr *pictify.ServerError var networkErr *pictify.NetworkError switch { case errors.As(err, &authErr): log.Println("invalid API key") case errors.As(err, ¬FoundErr): log.Println("template not found") case errors.As(err, &rateLimitErr): log.Printf("rate limited; retry after %ds", rateLimitErr.RetryAfter) case errors.As(err, "aErr): log.Println("render quota exceeded") case errors.As(err, &renderErr): log.Printf("render failed: %s (%v)", renderErr.Message, renderErr.Errors) case errors.As(err, &serverErr): log.Printf("server error: %s", serverErr.Message) case errors.As(err, &networkErr): log.Printf("network error: %v", networkErr.Err) default: log.Printf("error: %v", err) }}
Only 5xx and network failures are retried (with exponential backoff); 4xx responses are never retried.
Render MP4 video — or animated GIF — from video templates, generate new templates with AI, or upload a Remotion scene you wrote. Video calls use a longer per-call timeout internally (render 5m, authoring 3m); context deadlines still cancel earlier.
videos, _ := client.ListVideoTemplates(ctx)video, err := client.RenderVideo(ctx, &pictify.RenderVideoOptions{ TemplateID: videos[0].UID, Variables: map[string]any{"title": "Welcome, Maya!"}, Format: pictify.VideoFormatGIF, // or VideoFormatMP4 (default)})fmt.Println(video.URL)generated, err := client.GenerateVideoTemplate(ctx, &pictify.GenerateVideoTemplateOptions{ Prompt: "An 8 second product launch teaser — dark, electric, type-driven",})// The compile gate runs BEFORE saving: invalid tsx returns a *RenderError// with the compiler errors in .Errors, and nothing is created.template, err := client.CreateVideoTemplate(ctx, &pictify.CreateVideoTemplateOptions{ Name: "My scene", TSX: sceneSource, DurationSeconds: 8,})