Go
Generate images from a template with net/http from the standard library. Imejis returns the finished image directly in the response, so there is nothing to poll and no webhook to receive.
Set two environment variables first: IMEJIS_API_KEY (from your dashboard) and IMEJIS_DESIGN_ID (any design's id). Then send the fields you want to change as component.property pairs: headline.text, title.color, image.image. Only the fields you send change; everything else keeps its designed value, and a design's overridable fields are listed in its Share / API panel.
Every block below is a copy-paste runnable program, and every one of them is executed in Docker against a real render service before it ships.
Generate a single imageGenerate a single image
One POST, one image. The response body is the rendered image itself, with nothing to poll and no webhook to receive.
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"os"
)
// A stored render (delivery=hosted or delivery=signed).
type stored struct {
URL string `json:"url"`
ExpiresAt string `json:"expiresAt"`
Format string `json:"format"`
File struct {
Size int `json:"size"`
} `json:"file"`
}
// One /bulk response: results in the order the items were sent.
type bulkResponse struct {
Results []struct {
Index int `json:"index"`
Format string `json:"format"`
URL string `json:"url"`
Error string `json:"error"`
} `json:"results"`
Summary map[string]int `json:"summary"`
}
func envOr(key, fallback string) string {
if v := os.Getenv(key); v != "" {
return v
}
return fallback
}
func apiKey() string { return os.Getenv("IMEJIS_API_KEY") }
func designID() string { return os.Getenv("IMEJIS_DESIGN_ID") }
func baseURL() string { return envOr("IMEJIS_RENDER_URL", "https://render.imejis.io") }
// The size to render on a multi-size design; "master"/absent is the base size.
func variationID() string { return envOr("IMEJIS_VARIATION_ID", "story") }
// render POSTs `body` to `path` with the render key and returns the response.
func render(path string, params url.Values, body any) *http.Response {
payload, err := json.Marshal(body)
if err != nil {
panic(err)
}
endpoint := baseURL() + path
if len(params) > 0 {
endpoint += "?" + params.Encode()
}
req, err := http.NewRequest("POST", endpoint, bytes.NewBuffer(payload))
if err != nil {
panic(err)
}
req.Header.Set("dma-api-key", apiKey())
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
return res
}
// readAll drains a response body (the rendered image, or a JSON envelope).
func readAll(res *http.Response) []byte {
defer res.Body.Close()
out, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
return out
}
// save writes the rendered bytes to disk.
func save(name string, data []byte) {
if err := os.WriteFile(name, data, 0o644); err != nil {
panic(err)
}
}
// decode parses a JSON response envelope into `target`.
func decode(data []byte, target any) {
if err := json.Unmarshal(data, target); err != nil {
panic(err)
}
}
func main() {
// Render one image. The response body IS the image — no polling, no webhook.
res := render("/v1/"+designID(), nil, map[string]string{
"headline.text": "Hello from Go",
"subtitle.text": "Rendered in one request",
})
image := readAll(res)
save("output.jpg", image)
fmt.Println("single:", res.StatusCode, len(image), "bytes")
}Every output format png jpeg webp and pdfEvery output format: PNG, JPEG, WebP and PDF
Pick the output with ?format=. PNG and WebP keep transparency, JPEG is the smallest lossy option, and PDF is a single print-ready page. ?quality= applies to JPEG only.
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"os"
)
// A stored render (delivery=hosted or delivery=signed).
type stored struct {
URL string `json:"url"`
ExpiresAt string `json:"expiresAt"`
Format string `json:"format"`
File struct {
Size int `json:"size"`
} `json:"file"`
}
// One /bulk response: results in the order the items were sent.
type bulkResponse struct {
Results []struct {
Index int `json:"index"`
Format string `json:"format"`
URL string `json:"url"`
Error string `json:"error"`
} `json:"results"`
Summary map[string]int `json:"summary"`
}
func envOr(key, fallback string) string {
if v := os.Getenv(key); v != "" {
return v
}
return fallback
}
func apiKey() string { return os.Getenv("IMEJIS_API_KEY") }
func designID() string { return os.Getenv("IMEJIS_DESIGN_ID") }
func baseURL() string { return envOr("IMEJIS_RENDER_URL", "https://render.imejis.io") }
// The size to render on a multi-size design; "master"/absent is the base size.
func variationID() string { return envOr("IMEJIS_VARIATION_ID", "story") }
// render POSTs `body` to `path` with the render key and returns the response.
func render(path string, params url.Values, body any) *http.Response {
payload, err := json.Marshal(body)
if err != nil {
panic(err)
}
endpoint := baseURL() + path
if len(params) > 0 {
endpoint += "?" + params.Encode()
}
req, err := http.NewRequest("POST", endpoint, bytes.NewBuffer(payload))
if err != nil {
panic(err)
}
req.Header.Set("dma-api-key", apiKey())
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
return res
}
// readAll drains a response body (the rendered image, or a JSON envelope).
func readAll(res *http.Response) []byte {
defer res.Body.Close()
out, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
return out
}
// save writes the rendered bytes to disk.
func save(name string, data []byte) {
if err := os.WriteFile(name, data, 0o644); err != nil {
panic(err)
}
}
// decode parses a JSON response envelope into `target`.
func decode(data []byte, target any) {
if err := json.Unmarshal(data, target); err != nil {
panic(err)
}
}
func main() {
// Every output format, with JPEG quality. PNG and WebP keep transparency;
// PDF is a single print-ready page. quality only affects JPEG.
for _, format := range []string{"png", "jpeg", "webp", "pdf"} {
params := url.Values{"format": {format}}
if format == "jpeg" {
params.Set("quality", "85")
}
r := render("/v1/"+designID(), params, map[string]string{
"headline.text": "Format: " + format,
})
bytesRead := readAll(r)
save("output."+format, bytesRead)
fmt.Println("formats:", format, r.Header.Get("content-type"), len(bytesRead))
}
}Render multiple sizes from one templateRender multiple sizes from one template
A multi-size design carries several canvases: an OG image, a square post, a vertical story. ?variation=<id> picks which one you get back; omit it for the base size.
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"os"
)
// A stored render (delivery=hosted or delivery=signed).
type stored struct {
URL string `json:"url"`
ExpiresAt string `json:"expiresAt"`
Format string `json:"format"`
File struct {
Size int `json:"size"`
} `json:"file"`
}
// One /bulk response: results in the order the items were sent.
type bulkResponse struct {
Results []struct {
Index int `json:"index"`
Format string `json:"format"`
URL string `json:"url"`
Error string `json:"error"`
} `json:"results"`
Summary map[string]int `json:"summary"`
}
func envOr(key, fallback string) string {
if v := os.Getenv(key); v != "" {
return v
}
return fallback
}
func apiKey() string { return os.Getenv("IMEJIS_API_KEY") }
func designID() string { return os.Getenv("IMEJIS_DESIGN_ID") }
func baseURL() string { return envOr("IMEJIS_RENDER_URL", "https://render.imejis.io") }
// The size to render on a multi-size design; "master"/absent is the base size.
func variationID() string { return envOr("IMEJIS_VARIATION_ID", "story") }
// render POSTs `body` to `path` with the render key and returns the response.
func render(path string, params url.Values, body any) *http.Response {
payload, err := json.Marshal(body)
if err != nil {
panic(err)
}
endpoint := baseURL() + path
if len(params) > 0 {
endpoint += "?" + params.Encode()
}
req, err := http.NewRequest("POST", endpoint, bytes.NewBuffer(payload))
if err != nil {
panic(err)
}
req.Header.Set("dma-api-key", apiKey())
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
return res
}
// readAll drains a response body (the rendered image, or a JSON envelope).
func readAll(res *http.Response) []byte {
defer res.Body.Close()
out, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
return out
}
// save writes the rendered bytes to disk.
func save(name string, data []byte) {
if err := os.WriteFile(name, data, 0o644); err != nil {
panic(err)
}
}
// decode parses a JSON response envelope into `target`.
func decode(data []byte, target any) {
if err := json.Unmarshal(data, target); err != nil {
panic(err)
}
}
func main() {
// One template, many sizes. ?variation=<id> picks the size; omit it for the
// base. The ids are listed in the design's Share / API panel.
sized := render("/v1/"+designID(), url.Values{
"format": {"png"},
"variation": {variationID()},
}, map[string]string{"headline.text": "Story size"})
sizedBytes := readAll(sized)
save("output-story.png", sizedBytes)
fmt.Println("variation:", sized.StatusCode, len(sizedBytes), "bytes")
}An image url for img tags email and thumbnailsAn image URL for <img> tags, email and thumbnails
The same render as a plain GET URL, with the field values in the query string. Drop it into an <img src>, an HTML email, or a Slack message and it renders fresh every time it is fetched.
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"os"
)
// A stored render (delivery=hosted or delivery=signed).
type stored struct {
URL string `json:"url"`
ExpiresAt string `json:"expiresAt"`
Format string `json:"format"`
File struct {
Size int `json:"size"`
} `json:"file"`
}
// One /bulk response: results in the order the items were sent.
type bulkResponse struct {
Results []struct {
Index int `json:"index"`
Format string `json:"format"`
URL string `json:"url"`
Error string `json:"error"`
} `json:"results"`
Summary map[string]int `json:"summary"`
}
func envOr(key, fallback string) string {
if v := os.Getenv(key); v != "" {
return v
}
return fallback
}
func apiKey() string { return os.Getenv("IMEJIS_API_KEY") }
func designID() string { return os.Getenv("IMEJIS_DESIGN_ID") }
func baseURL() string { return envOr("IMEJIS_RENDER_URL", "https://render.imejis.io") }
// The size to render on a multi-size design; "master"/absent is the base size.
func variationID() string { return envOr("IMEJIS_VARIATION_ID", "story") }
// render POSTs `body` to `path` with the render key and returns the response.
func render(path string, params url.Values, body any) *http.Response {
payload, err := json.Marshal(body)
if err != nil {
panic(err)
}
endpoint := baseURL() + path
if len(params) > 0 {
endpoint += "?" + params.Encode()
}
req, err := http.NewRequest("POST", endpoint, bytes.NewBuffer(payload))
if err != nil {
panic(err)
}
req.Header.Set("dma-api-key", apiKey())
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
return res
}
// readAll drains a response body (the rendered image, or a JSON envelope).
func readAll(res *http.Response) []byte {
defer res.Body.Close()
out, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
return out
}
// save writes the rendered bytes to disk.
func save(name string, data []byte) {
if err := os.WriteFile(name, data, 0o644); err != nil {
panic(err)
}
}
// decode parses a JSON response envelope into `target`.
func decode(data []byte, target any) {
if err := json.Unmarshal(data, target); err != nil {
panic(err)
}
}
func main() {
// The same render as a plain GET URL — drop it into an <img> tag, an HTML
// email, or a Slack message. Field overrides ride the query string.
getURL := baseURL() + "/v1/" + designID() + "?" + url.Values{
"dma-api-key": {apiKey()},
"format": {"png"},
"headline.text": {"Hello from a URL"},
"subtitle.text": {"No request body needed"},
}.Encode()
fmt.Println("get:", getURL)
viaURL, err := http.Get(getURL)
if err != nil {
panic(err)
}
urlBytes := readAll(viaURL)
save("output-get.png", urlBytes)
fmt.Println("get:", viaURL.StatusCode, len(urlBytes), "bytes")
}Hosted delivery get a public image url backHosted delivery: get a public image URL back
?delivery=hosted stores the render and returns a public URL instead of raw bytes, which is what an email, a webhook payload, or a dashboard needs: a link rather than a file.
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"os"
)
// A stored render (delivery=hosted or delivery=signed).
type stored struct {
URL string `json:"url"`
ExpiresAt string `json:"expiresAt"`
Format string `json:"format"`
File struct {
Size int `json:"size"`
} `json:"file"`
}
// One /bulk response: results in the order the items were sent.
type bulkResponse struct {
Results []struct {
Index int `json:"index"`
Format string `json:"format"`
URL string `json:"url"`
Error string `json:"error"`
} `json:"results"`
Summary map[string]int `json:"summary"`
}
func envOr(key, fallback string) string {
if v := os.Getenv(key); v != "" {
return v
}
return fallback
}
func apiKey() string { return os.Getenv("IMEJIS_API_KEY") }
func designID() string { return os.Getenv("IMEJIS_DESIGN_ID") }
func baseURL() string { return envOr("IMEJIS_RENDER_URL", "https://render.imejis.io") }
// The size to render on a multi-size design; "master"/absent is the base size.
func variationID() string { return envOr("IMEJIS_VARIATION_ID", "story") }
// render POSTs `body` to `path` with the render key and returns the response.
func render(path string, params url.Values, body any) *http.Response {
payload, err := json.Marshal(body)
if err != nil {
panic(err)
}
endpoint := baseURL() + path
if len(params) > 0 {
endpoint += "?" + params.Encode()
}
req, err := http.NewRequest("POST", endpoint, bytes.NewBuffer(payload))
if err != nil {
panic(err)
}
req.Header.Set("dma-api-key", apiKey())
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
return res
}
// readAll drains a response body (the rendered image, or a JSON envelope).
func readAll(res *http.Response) []byte {
defer res.Body.Close()
out, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
return out
}
// save writes the rendered bytes to disk.
func save(name string, data []byte) {
if err := os.WriteFile(name, data, 0o644); err != nil {
panic(err)
}
}
// decode parses a JSON response envelope into `target`.
func decode(data []byte, target any) {
if err := json.Unmarshal(data, target); err != nil {
panic(err)
}
}
func main() {
// delivery=hosted stores the render and returns a PUBLIC URL instead of
// bytes — for an email, a webhook payload, or a dashboard that needs a link.
var hosted stored
decode(readAll(render("/v1/"+designID(), url.Values{
"delivery": {"hosted"},
"format": {"png"},
}, map[string]string{"headline.text": "Hosted delivery"})), &hosted)
fmt.Println("hosted:", hosted.URL, hosted.File.Size, "bytes")
}Signed delivery a private expiring image urlSigned delivery: a private, expiring image URL
?delivery=signed stores the render privately and returns a time-limited signed URL. ?expiresIn= is minutes.
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"os"
)
// A stored render (delivery=hosted or delivery=signed).
type stored struct {
URL string `json:"url"`
ExpiresAt string `json:"expiresAt"`
Format string `json:"format"`
File struct {
Size int `json:"size"`
} `json:"file"`
}
// One /bulk response: results in the order the items were sent.
type bulkResponse struct {
Results []struct {
Index int `json:"index"`
Format string `json:"format"`
URL string `json:"url"`
Error string `json:"error"`
} `json:"results"`
Summary map[string]int `json:"summary"`
}
func envOr(key, fallback string) string {
if v := os.Getenv(key); v != "" {
return v
}
return fallback
}
func apiKey() string { return os.Getenv("IMEJIS_API_KEY") }
func designID() string { return os.Getenv("IMEJIS_DESIGN_ID") }
func baseURL() string { return envOr("IMEJIS_RENDER_URL", "https://render.imejis.io") }
// The size to render on a multi-size design; "master"/absent is the base size.
func variationID() string { return envOr("IMEJIS_VARIATION_ID", "story") }
// render POSTs `body` to `path` with the render key and returns the response.
func render(path string, params url.Values, body any) *http.Response {
payload, err := json.Marshal(body)
if err != nil {
panic(err)
}
endpoint := baseURL() + path
if len(params) > 0 {
endpoint += "?" + params.Encode()
}
req, err := http.NewRequest("POST", endpoint, bytes.NewBuffer(payload))
if err != nil {
panic(err)
}
req.Header.Set("dma-api-key", apiKey())
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
return res
}
// readAll drains a response body (the rendered image, or a JSON envelope).
func readAll(res *http.Response) []byte {
defer res.Body.Close()
out, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
return out
}
// save writes the rendered bytes to disk.
func save(name string, data []byte) {
if err := os.WriteFile(name, data, 0o644); err != nil {
panic(err)
}
}
// decode parses a JSON response envelope into `target`.
func decode(data []byte, target any) {
if err := json.Unmarshal(data, target); err != nil {
panic(err)
}
}
func main() {
// delivery=signed stores it privately and returns a time-limited signed
// URL. expiresIn is minutes (default 60, max 7 days).
var signed stored
decode(readAll(render("/v1/"+designID(), url.Values{
"delivery": {"signed"},
"format": {"png"},
"expiresIn": {"30"},
}, map[string]string{"headline.text": "Signed delivery"})), &signed)
fmt.Println("signed:", signed.ExpiresAt, signed.URL[:80]+"...")
}Bulk image generation in one callBulk image generation in one call
POST /bulk to render many images in a single request: several sizes, several data variants, a mix of designs, or the ordered slides of a carousel. results preserves input order, so results[i] is items[i].
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"os"
)
// A stored render (delivery=hosted or delivery=signed).
type stored struct {
URL string `json:"url"`
ExpiresAt string `json:"expiresAt"`
Format string `json:"format"`
File struct {
Size int `json:"size"`
} `json:"file"`
}
// One /bulk response: results in the order the items were sent.
type bulkResponse struct {
Results []struct {
Index int `json:"index"`
Format string `json:"format"`
URL string `json:"url"`
Error string `json:"error"`
} `json:"results"`
Summary map[string]int `json:"summary"`
}
func envOr(key, fallback string) string {
if v := os.Getenv(key); v != "" {
return v
}
return fallback
}
func apiKey() string { return os.Getenv("IMEJIS_API_KEY") }
func designID() string { return os.Getenv("IMEJIS_DESIGN_ID") }
func baseURL() string { return envOr("IMEJIS_RENDER_URL", "https://render.imejis.io") }
// The size to render on a multi-size design; "master"/absent is the base size.
func variationID() string { return envOr("IMEJIS_VARIATION_ID", "story") }
// render POSTs `body` to `path` with the render key and returns the response.
func render(path string, params url.Values, body any) *http.Response {
payload, err := json.Marshal(body)
if err != nil {
panic(err)
}
endpoint := baseURL() + path
if len(params) > 0 {
endpoint += "?" + params.Encode()
}
req, err := http.NewRequest("POST", endpoint, bytes.NewBuffer(payload))
if err != nil {
panic(err)
}
req.Header.Set("dma-api-key", apiKey())
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
return res
}
// readAll drains a response body (the rendered image, or a JSON envelope).
func readAll(res *http.Response) []byte {
defer res.Body.Close()
out, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
return out
}
// save writes the rendered bytes to disk.
func save(name string, data []byte) {
if err := os.WriteFile(name, data, 0o644); err != nil {
panic(err)
}
}
// decode parses a JSON response envelope into `target`.
func decode(data []byte, target any) {
if err := json.Unmarshal(data, target); err != nil {
panic(err)
}
}
func main() {
// Many images in ONE call. results keeps input order, so results[i] is
// items[i] — for a carousel the array IS the slide order. Each item is one
// metered render, and a failed item does not abort the rest.
var bulk bulkResponse
decode(readAll(render("/bulk", nil, map[string]any{
"delivery": "hosted",
"format": "png",
"items": []map[string]any{
{"designId": designID(),
"overrides": map[string]string{"headline.text": "Slide 1"}},
{"designId": designID(), "variation": variationID(), "format": "jpeg",
"quality": 80, "overrides": map[string]string{"headline.text": "Slide 2"}},
{"designId": designID(), "format": "pdf",
"overrides": map[string]string{"headline.text": "Slide 3"}},
},
})), &bulk)
summary, _ := json.Marshal(bulk.Summary)
fmt.Println("bulk:", string(summary))
for _, item := range bulk.Results {
target := item.URL
if target == "" {
target = item.Error
}
fmt.Println(" ", item.Index, item.Format, target)
}
}Bulk from a list of rowsBulk from a list of rows
Send data instead of items and every row becomes one render, with no item list to build. That is the shape to reach for when the input is a spreadsheet, a database query, or a CSV.
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"os"
)
// A stored render (delivery=hosted or delivery=signed).
type stored struct {
URL string `json:"url"`
ExpiresAt string `json:"expiresAt"`
Format string `json:"format"`
File struct {
Size int `json:"size"`
} `json:"file"`
}
// One /bulk response: results in the order the items were sent.
type bulkResponse struct {
Results []struct {
Index int `json:"index"`
Format string `json:"format"`
URL string `json:"url"`
Error string `json:"error"`
} `json:"results"`
Summary map[string]int `json:"summary"`
}
func envOr(key, fallback string) string {
if v := os.Getenv(key); v != "" {
return v
}
return fallback
}
func apiKey() string { return os.Getenv("IMEJIS_API_KEY") }
func designID() string { return os.Getenv("IMEJIS_DESIGN_ID") }
func baseURL() string { return envOr("IMEJIS_RENDER_URL", "https://render.imejis.io") }
// The size to render on a multi-size design; "master"/absent is the base size.
func variationID() string { return envOr("IMEJIS_VARIATION_ID", "story") }
// render POSTs `body` to `path` with the render key and returns the response.
func render(path string, params url.Values, body any) *http.Response {
payload, err := json.Marshal(body)
if err != nil {
panic(err)
}
endpoint := baseURL() + path
if len(params) > 0 {
endpoint += "?" + params.Encode()
}
req, err := http.NewRequest("POST", endpoint, bytes.NewBuffer(payload))
if err != nil {
panic(err)
}
req.Header.Set("dma-api-key", apiKey())
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
return res
}
// readAll drains a response body (the rendered image, or a JSON envelope).
func readAll(res *http.Response) []byte {
defer res.Body.Close()
out, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
return out
}
// save writes the rendered bytes to disk.
func save(name string, data []byte) {
if err := os.WriteFile(name, data, 0o644); err != nil {
panic(err)
}
}
// decode parses a JSON response envelope into `target`.
func decode(data []byte, target any) {
if err := json.Unmarshal(data, target); err != nil {
panic(err)
}
}
func main() {
// The same design over a LIST OF ROWS — one render per row, no items[] to
// build. Use "variations": ["master","story"] instead to render every SIZE.
var rows bulkResponse
decode(readAll(render("/bulk", nil, map[string]any{
"designId": designID(),
"delivery": "signed",
"expiresIn": 15,
"format": "png",
"data": []map[string]string{
{"headline.text": "Ada Lovelace", "subtitle.text": "Mathematician"},
{"headline.text": "Alan Turing", "subtitle.text": "Computer scientist"},
{"headline.text": "Grace Hopper", "subtitle.text": "Rear admiral"},
},
})), &rows)
rowsSummary, _ := json.Marshal(rows.Summary)
fmt.Println("bulk-data:", string(rowsSummary))
}The response is the raw image (`image/jpeg` by default). Choose the format with `?format=png|jpeg|webp|pdf` (default jpeg) and set JPEG quality with `?quality=1-100`. Store the result and get a URL back with `?delivery=hosted` (or `?delivery=signed&expiresIn=60`), and render a specific size of a multi-size design with `?variation=<id>`.
| Parameter | Values | Default | What it does |
|---|---|---|---|
?format= | png · jpeg · webp · pdf | jpeg | Output image format. |
?quality= | 1–100 | none | Compression quality for lossy output; ignored for other formats. (JPEG only) |
?delivery= | stream · hosted · signed | stream | stream = raw image bytes (default); hosted = store + return a public URL; signed = store + return a time-limited URL. |
?expiresIn= | minutes | 60 | Signed-URL lifetime in minutes (default 60, max 10080 = 7 days). (delivery=signed only) |
?variation= | <size id> | master | Which multi-dimension SIZE to render. Omit or use "master" for the base size; an unknown id falls back to the master. (multi-size designs only) |
- PNG (
?format=png): Lossless, supports transparency. Largest file. - JPEG (
?format=jpeg): Smaller, lossy, no transparency. Quality adjustable. - WebP (
?format=webp): Smallest, supports transparency. Modern browsers. - PDF (
?format=pdf): Vector page, for print and documents.
See the delivery modes and generate images with the API guides.
There is no Go framework page yet, so the cURL page is the closest reference for the raw requests. Reuse one http.Client with a timeout rather than the package-level default, because a render can take seconds and the default client waits forever. Each call is one render, 100 free a month, then pricing.