polipage

package module
v0.9.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 16, 2026 License: MIT Imports: 18 Imported by: 0

README

Poli Page SDK for Go

Release Ci Codeql Coverage Go Lint Go.dev Report Deps Docs License

Official Go SDK for Poli Page — render polished PDFs from HTML templates via the Poli Page API.

→ Documentation: https://poli-page.github.io/sdk-go/

→ API reference (auto-generated from doc comments): pkg.go.dev/github.com/poli-page/sdk-go

Install

go get github.com/poli-page/sdk-go

Requires Go 1.25 or later. Zero runtime dependencies.

Quick start

Project mode — render a published template by slug
package main

import (
    "context"
    "log"
    "os"

    polipage "github.com/poli-page/sdk-go"
    "github.com/poli-page/sdk-go/option"
)

func main() {
    client := polipage.NewClient(option.WithAPIKey(os.Getenv("POLI_PAGE_API_KEY")))

    pdf, err := client.Render.PDF(context.Background(), polipage.ProjectModeInput{
        Project:  "getting-started",
        Template: "welcome",
        Version:  polipage.Opt("1.0.0"),
        Data:     map[string]any{"name": "World"},
    })
    if err != nil {
        log.Fatal(err)
    }
    _ = os.WriteFile("welcome.pdf", pdf, 0o644)
}

Every Poli Page org comes pre-provisioned with a getting-started/welcome template, so the snippet above runs as-is the moment you have an API key — no project setup needed. For your own templates, swap the slugs once you've pushed a version with the poli CLI:

pdf, err := client.Render.PDF(ctx, polipage.ProjectModeInput{
    Project:  "billing",
    Template: "invoice",
    Version:  polipage.Opt("1.0.0"),
    Data:     map[string]any{"invoiceNumber": "INV-001", "total": 1280},
})
Preview inline HTML

Render.Preview accepts raw HTML for live editing and visual inspection without producing a stored document. Use this for editor previews or layout tests.

res, err := client.Render.Preview(ctx, polipage.InlineModeInput{
    Template: "<h1>Hello {{ name }}</h1>",
    Data:     map[string]any{"name": "World"},
})
// res.HTML, res.TotalPages, res.Environment

Render.PDF, Render.PDFStream, and Render.Document require project mode — they accept ProjectModeInput directly so inline-mode calls are rejected at compile time. Render.Preview accepts the RenderInput sealed interface, satisfied by both modes.

Write a PDF to disk
err := polipage.RenderToFile(ctx, client, polipage.ProjectModeInput{
    Project:  "getting-started",
    Template: "welcome",
    Version:  polipage.Opt("1.0.0"),
    Data:     map[string]any{"name": "World"},
}, "./welcome.pdf")

RenderToFile streams response bytes directly to disk (bounded memory). Parent directories are created on demand; existing files are overwritten.

Try it locally — runnable demo

The repo ships a runnable demo that exercises every public method end-to-end against the real API:

go run ./cmd/demo
# or remote-only, no checkout:
go run github.com/poli-page/sdk-go/cmd/demo@latest

First run prompts for a pp_test_* key and saves it to .env. Subsequent runs are silent. The demo walks through Render.PDF → PDFStream → RenderToFile → Preview → Document → Documents.Get → Thumbnails → Preview → Delete → an intentional error path, writing artifacts to ./output/.

Stream — for large PDFs or piping to S3 / HTTP responses
body, err := client.Render.PDFStream(ctx, polipage.ProjectModeInput{
    Project: "billing", Template: "invoice",
    Version: polipage.Opt("1.0.0"),
    Data:    map[string]any{"invoiceNumber": "INV-001"},
})
if err != nil {
    return err
}
defer body.Close()

// Pipe straight to an HTTP response, an S3 upload, a file — anything that
// accepts io.Reader. Memory stays bounded regardless of document size.
_, err = io.Copy(w, body)

Working with stored documents

Every render produces a stored document, accessible via documentId for later download or thumbnails. Render.PDF and Render.PDFStream are conveniences that chain a presigned-URL fetch internally to return bytes; Render.Document returns just the descriptor (skip the auto-download when you'll fetch the bytes later).

// 1. Render and store
doc, err := client.Render.Document(ctx, polipage.ProjectModeInput{
    Project:  "billing",
    Template: "invoice",
    Version:  polipage.Opt("1.0.0"),
    Data:     map[string]any{"invoiceNumber": "INV-001"},
    Metadata: polipage.RenderMetadata{"customerId": "cust_123"}, // your own audit data
})
// doc.DocumentID, doc.PageCount, doc.SizeBytes, doc.PresignedPDFURL, doc.Metadata, ...

// 2. Save doc.DocumentID in your database
_ = db.Invoices.Update("INV-001", doc.DocumentID)

// 3. Later, fetch a fresh presigned URL + download
fresh, err := client.Documents.Get(ctx, doc.DocumentID)
pdf, err := fresh.DownloadPDF(ctx)

// 4. Generate thumbnails
thumbs, err := client.Documents.Thumbnails(ctx, doc.DocumentID, polipage.ThumbnailOptions{
    Width:  320,
    Format: polipage.ThumbnailFormatPNG,
})

// 5. When done, soft-delete
err = client.Documents.Delete(ctx, doc.DocumentID)

The presigned URL has a ~15-minute TTL. If DownloadPDF fails with Code: ErrCodeDownloadFailed (HTTP 403 from S3), call Documents.Get(ctx, id) to refresh and retry.

Authentication & environments

The mode is determined by the API key prefix:

  • pp_test_… → sandbox mode (not billed, generous rate limits)
  • pp_live_… → live mode (billed, production rate limits)
  • pp_sa_… → service-account keys; environment matches the SA's configuration (sandbox or live)

All prefixes hit the same endpoint (https://api.poli.page). The SDK passes the key through as a Bearer token and never inspects the prefix — pick whichever fits your deploy model.

Methods

Method Returns Description
client.Render.PDF(ctx, in, opts...) ([]byte, error) Render a PDF, return bytes
client.Render.PDFStream(ctx, in, opts...) (io.ReadCloser, error) Render and stream the response
client.Render.Preview(ctx, in, opts...) (*PreviewResult, error) Paginated HTML preview
client.Render.Document(ctx, in, opts...) (*DocumentDescriptor, error) Render and return descriptor (skip auto-download)
client.Documents.Get(ctx, id) (*DocumentDescriptor, error) Retrieve a stored document
client.Documents.Preview(ctx, id) (*DocumentPreviewResult, error) Stored document's paginated HTML
client.Documents.Thumbnails(ctx, id, options, ...) ([]Thumbnail, error) Page thumbnails (PNG/JPEG, base64)
client.Documents.Delete(ctx, id) error Soft-delete a stored document
(*DocumentDescriptor).DownloadPDF(ctx) ([]byte, error) Fetch bytes from the descriptor's presigned URL
polipage.RenderToFile(ctx, client, in, path) error Render and stream to disk

Configuration

All options live in the option subpackage and are passed to NewClient (variadic). Per-call options (currently only WithIdempotencyKey) are passed to individual methods as the final variadic argument.

Option Type Default Description
option.WithAPIKey(key) string (required) pp_test_* or pp_live_* API key
option.WithBaseURL(url) string https://api.poli.page API base URL
option.WithMaxRetries(n) int 2 Retry budget on top of the initial attempt
option.WithRetryDelay(d) time.Duration 500 * time.Millisecond Base exponential-backoff delay
option.WithTimeout(d) time.Duration 60 * time.Second Per-request fallback deadline (when ctx has none)
option.WithHTTPClient(c) *http.Client new client Inject custom transport / TLS / middleware
option.WithLogger(l) *slog.Logger discard One DEBUG/attempt, WARN/retry, ERROR/terminal
option.WithOnRetry(fn) func(polipage.RetryEvent) nil Fires before each retry sleep
option.WithOnError(fn) func(error) nil Fires on terminal failure
option.WithIdempotencyKey(key) string UUID4 Per-call — override the auto-generated key
option.WithRequestTimeout(d) time.Duration WithTimeout value Per-call — override per-request deadline (no-op if ctx has a deadline)
option.WithHeader(key, value) string, string — Construction + per-call — extra request header; per-call wins on duplicate keys

Error handling

The SDK returns a single error type, *polipage.Error, for every failure. Use errors.Is against the package-level sentinels for quick branching, or errors.As to inspect the full value:

import (
    "errors"
    "log"

    polipage "github.com/poli-page/sdk-go"
)

pdf, err := client.Render.PDF(ctx, in)
if err != nil {
    if errors.Is(err, polipage.ErrUnauthorized)  { return refreshCredentials() }
    if errors.Is(err, polipage.ErrRateLimit)     { return queueForLater() }
    if errors.Is(err, polipage.ErrNotFound)      { return show404() }

    var pErr *polipage.Error
    if errors.As(err, &pErr) {
        if pErr.IsValidationError() { log.Println("bad input:", pErr.Message) }
        if pErr.IsNetworkError()    { log.Println("network/timeout") }
        if pErr.IsRetryable()       { /* SDK already retried up to MaxRetries */ }
        log.Printf("code=%s status=%d requestId=%s\n", pErr.Code, pErr.StatusCode, pErr.RequestID)
    }
    return err
}

For lifecycle and billing failures, route the user to actionable messages rather than treating them as opaque errors:

var pErr *polipage.Error
if errors.As(err, &pErr) {
    switch pErr.Code {
    case polipage.ErrCodePaymentRequired:       return showBanner("Subscription has unpaid invoices.")
    case polipage.ErrCodeOrganizationCancelled: return showBanner("Subscription cancelled — service is read-only.")
    case polipage.ErrCodeOrganizationPurged:    return showBanner("Organization has been purged.")
    case polipage.ErrCodeDocumentNotFound:      return show404()
    case polipage.ErrCodeGone:                  return show410() // document was soft-deleted
    }
}

Cancellation

Pass a context.Context with a deadline or cancel to abort a render in flight:

ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

pdf, err := client.Render.PDF(ctx, in)

When the context is canceled, the SDK returns *polipage.Error with Code == ErrCodeAborted; when the deadline expires, Code == ErrCodeTimeout. Caller-aborted errors are never retried.

Observability

The SDK ships with log/slog integration as the primary observability mechanism:

logger := slog.New(slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{Level: slog.LevelDebug}))
client := polipage.NewClient(
    option.WithAPIKey(os.Getenv("POLI_PAGE_API_KEY")),
    option.WithLogger(logger),
)

One DEBUG line per HTTP attempt, one WARN per retry, one ERROR per terminal failure. Headers and bodies that could contain the API key are never logged.

For SDK-level events that don't fit a log line, register hooks:

client := polipage.NewClient(
    option.WithAPIKey(os.Getenv("POLI_PAGE_API_KEY")),
    option.WithOnRetry(func(e polipage.RetryEvent) {
        metrics.Counter("poli.retry").With("attempt", e.Attempt).Inc()
    }),
    option.WithOnError(func(err error) {
        sentry.CaptureException(err)
    }),
)

Hooks are synchronous, optional, and panic-safe — a hook that panics never breaks the request. For request/response inspection (full headers + body), inject a custom *http.Client via option.WithHTTPClient and add a middleware transport there — see the next section.

Middleware via http.RoundTripper

The SDK's hooks fire at SDK-level events (retry, terminal error). For full-fidelity HTTP middleware — tracing, request signing, response caching, fixture recording, request/response logging with bodies — wrap a http.RoundTripper and pass it via option.WithHTTPClient. This is the stdlib idiom; the SDK does nothing special to enable it.

type tracingTransport struct {
    base http.RoundTripper
}

func (t *tracingTransport) RoundTrip(req *http.Request) (*http.Response, error) {
    start := time.Now()
    resp, err := t.base.RoundTrip(req)
    log.Printf("%s %s → %d in %s", req.Method, req.URL.Path, resp.StatusCode, time.Since(start))
    return resp, err
}

client := polipage.NewClient(
    option.WithAPIKey(os.Getenv("POLI_PAGE_API_KEY")),
    option.WithHTTPClient(&http.Client{
        Transport: &tracingTransport{base: http.DefaultTransport},
    }),
)

Compose multiple layers by chaining RoundTrippers (each wraps the previous one's base). The SDK's retry loop runs outside this transport, so each RoundTrip corresponds to one attempt — log every retry by counting RoundTrip calls per request.

Per-call tracing IDs

For one-off per-request headers (a tracing ID, a tenant override, a feature flag), use option.WithHeader as a per-call option without rebuilding the client:

ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

pdf, err := client.Render.PDF(ctx, in,
    option.WithHeader("X-Trace-Id", traceID),
    option.WithRequestTimeout(5*time.Second), // overrides client default for this call only
)

Per-call header keys win over construction-time WithHeader entries for the same key; both override the SDK's own headers (Authorization, Content-Type, etc.) if you supply matching keys — caller's responsibility.

Retries & idempotency

The SDK retries on 5xx, 429, network errors, and timeouts. Backoff is exponential (RetryDelay × 2^N) with jitter in [0.5, 1.5), capped at the server's Retry-After header when provided (max 30s). Every POST sends an auto-generated Idempotency-Key (UUID v4); pass option.WithIdempotencyKey("…") as the last argument to override:

_, err := client.Render.PDF(ctx, in, option.WithIdempotencyKey("inv-INV-001"))

Type system

The SDK uses Go's type system to enforce the contract at compile time:

  • RenderInput is a sealed marker interface (unexported method) satisfied by ProjectModeInput and InlineModeInput only. External types cannot satisfy it.
  • Render.PDF, PDFStream, and Document accept ProjectModeInput directly — passing InlineModeInput is a compile-time error.
  • Nullable wire fields (ProjectID, Version, Orientation, Locale, …) are *string to distinguish JSON null from empty strings.
  • Opt[T any](v T) *T turns a literal into a *T for optional fields: Version: polipage.Opt("1.0.0").

Concurrency & thread-safety

*polipage.Client is safe for concurrent use. Create one client per process and reuse it across goroutines — the underlying *http.Client pools connections automatically. The SDK has no async/sync split; goroutines + context.Context cover both concurrency and cancellation.

var wg sync.WaitGroup
results := make([]*polipage.DocumentDescriptor, len(invoices))
errs    := make([]error, len(invoices))
for i, inv := range invoices {
    wg.Add(1)
    go func(i int, inv Invoice) {
        defer wg.Done()
        results[i], errs[i] = client.Render.Document(ctx, polipage.ProjectModeInput{
            Project:  "billing",
            Template: "invoice",
            Version:  polipage.Opt("1.0.0"),
            Data:     inv.Data(),
        })
    }(i, inv)
}
wg.Wait()

Runtime support

Server-side only. The SDK runs on:

  • Go 1.25+ — current and N-1 stable Go releases.

Browsers / WebAssembly are not supported. API keys (pp_test_*, pp_live_*) are secrets and must never be shipped to a browser. Call the SDK from your backend (HTTP server, CLI, worker, lambda) and proxy the result to the client.

Requirements

Go 1.25 or later. The SDK has zero runtime dependencies — only the Go standard library.

Documentation & support

License

MIT © Poli Page

Documentation

Overview

Package polipage is the official Go SDK for Poli Page.

Construct a client with NewClient, then call methods on the Render or Documents namespaces. The client is safe for concurrent use — share one instance per process so the underlying *http.Client pools connections automatically.

Index

Examples

Constants

View Source
const (
	// ErrCodeInvalidOptions marks constructor or per-call option validation
	// failures (empty API key, malformed metadata, etc.).
	ErrCodeInvalidOptions = "invalid_options"
	// ErrCodeNetworkError marks DNS / connection / TLS failures.
	ErrCodeNetworkError = "network_error"
	// ErrCodeTimeout marks a per-request deadline being exceeded.
	ErrCodeTimeout = "timeout"
	// ErrCodeAborted marks caller-initiated cancellation. Never retryable.
	ErrCodeAborted = "aborted"
	// ErrCodeUnknownError is the fallback code when an error-body JSON has
	// no recognised fields.
	ErrCodeUnknownError = "unknown_error"
	// ErrCodeDownloadFailed marks a failure fetching a presigned PDF URL.
	ErrCodeDownloadFailed = "DOWNLOAD_FAILED"
	// ErrCodeInternalError is the SDK-side fallback when the response body
	// is unparseable or missing. Distinct from ErrCodeAPIInternalError, which
	// has the same wire value but originates from the API.
	ErrCodeInternalError = "INTERNAL_ERROR"
	// ErrCodeIOFailed marks local filesystem failures from [RenderToFile]
	// (MkdirAll / Create / write errors). The underlying os error is wrapped
	// in Cause — use errors.Unwrap or errors.As(*os.PathError) to inspect.
	ErrCodeIOFailed = "io_failed"
)

SDK-internal error codes. These do not appear in API responses; the SDK sets them on errors raised before, around, or after the HTTP call.

View Source
const (
	ErrCodeMissingAPIKey              = "MISSING_API_KEY" //nolint:gosec // G101: error-code identifier, not a credential
	ErrCodeInvalidAPIKey              = "INVALID_API_KEY" //nolint:gosec // G101: error-code identifier, not a credential
	ErrCodePaymentRequired            = "PAYMENT_REQUIRED"
	ErrCodeForbidden                  = "FORBIDDEN"
	ErrCodeOrganizationCancelled      = "ORGANIZATION_CANCELLED"
	ErrCodeOrganizationPurged         = "ORGANIZATION_PURGED"
	ErrCodeNotFound                   = "NOT_FOUND"
	ErrCodeVersionNotFound            = "VERSION_NOT_FOUND"
	ErrCodeDocumentNotFound           = "DOCUMENT_NOT_FOUND"
	ErrCodeGone                       = "GONE"
	ErrCodeValidationError            = "VALIDATION_ERROR"
	ErrCodeMissingData                = "MISSING_DATA"
	ErrCodeMissingProjectOrTemplate   = "MISSING_PROJECT_OR_TEMPLATE"
	ErrCodeMissingTemplateSlug        = "MISSING_TEMPLATE_SLUG"
	ErrCodeProjectRequiredForDocument = "PROJECT_REQUIRED_FOR_DOCUMENT"
	ErrCodeInvalidVersionFormat       = "INVALID_VERSION_FORMAT"
	ErrCodeVersionRequired            = "VERSION_REQUIRED"
	ErrCodeInvalidVersionForKeyEnv    = "INVALID_VERSION_FOR_KEY_ENV"
	ErrCodeQuotaExceeded              = "QUOTA_EXCEEDED"
	ErrCodeOverageCapExceeded         = "OVERAGE_CAP_EXCEEDED"
	// ErrCodeAPIInternalError shares the wire value "INTERNAL_ERROR" with
	// ErrCodeInternalError; kept as a separate constant for call-site clarity.
	ErrCodeAPIInternalError = "INTERNAL_ERROR"
)

Known API error codes pass through verbatim from the deployed API. Callers may see codes not in this list — the SDK preserves whatever the API returns.

View Source
const (
	// DefaultBaseURL is the production Poli Page API base URL. Override via
	// option.WithBaseURL to target another environment.
	DefaultBaseURL = "https://api.poli.page"

	// DefaultMaxRetries is the default retry budget: 2 retries on top of the
	// initial attempt, so 3 attempts total before a retryable error surfaces.
	DefaultMaxRetries = 2

	// DefaultRetryDelay is the base exponential-backoff delay. The first
	// retry waits ~DefaultRetryDelay × jitter, the second ~2×, etc.
	DefaultRetryDelay = 500 * time.Millisecond

	// DefaultTimeout is the per-request fallback deadline applied when the
	// caller's context has no deadline of its own.
	DefaultTimeout = 60 * time.Second
)

User-facing default values for client construction. Internal SDK values (header names, jitter bounds, path templates) live in internal/constants instead, per sdk-go-plan.md §17.

Variables

View Source
var (
	ErrUnauthorized          = &Error{Code: ErrCodeMissingAPIKey}         // also matches INVALID_API_KEY
	ErrForbidden             = &Error{Code: ErrCodeForbidden}             //
	ErrNotFound              = &Error{Code: ErrCodeNotFound}              //
	ErrVersionNotFound       = &Error{Code: ErrCodeVersionNotFound}       //
	ErrDocumentNotFound      = &Error{Code: ErrCodeDocumentNotFound}      //
	ErrGone                  = &Error{Code: ErrCodeGone}                  //
	ErrValidation            = &Error{Code: ErrCodeValidationError}       //
	ErrRateLimit             = &Error{Code: ErrCodeQuotaExceeded}         // also matches OVERAGE_CAP_EXCEEDED
	ErrTimeout               = &Error{Code: ErrCodeTimeout}               //
	ErrAborted               = &Error{Code: ErrCodeAborted}               //
	ErrNetwork               = &Error{Code: ErrCodeNetworkError}          //
	ErrDownloadFailed        = &Error{Code: ErrCodeDownloadFailed}        //
	ErrIOFailed              = &Error{Code: ErrCodeIOFailed}              // local filesystem write failure from RenderToFile
	ErrPaymentRequired       = &Error{Code: ErrCodePaymentRequired}       // 402 — unpaid invoice / subscription lapsed
	ErrOrganizationCancelled = &Error{Code: ErrCodeOrganizationCancelled} // 403 — subscription cancelled, service is read-only
	ErrOrganizationPurged    = &Error{Code: ErrCodeOrganizationPurged}    // 410 — organization data has been purged
)

Sentinel errors. Use with errors.Is for ergonomic call-site checks:

if errors.Is(err, polipage.ErrNotFound) {
    return nil // treat 404 as absent without further inspection
}

Each sentinel is a zero-status *Error keyed by Code; (*Error).Is matches receivers whose Code equals the sentinel's, with two logical groups (auth, rate-limit) that compare equal across related codes.

Functions

func Opt

func Opt[T any](v T) *T

Opt returns a pointer to v. Use it to set optional pointer-typed fields with literal values:

polipage.ProjectModeInput{Version: polipage.Opt("1.0.0")}

Named for the intent (optional fields) rather than the mechanic (pointers) — Go has no inline pointer-to-literal syntax.

Example

ExampleOpt shows the common use of the Opt helper: turning a literal value into a *T for optional pointer-typed fields like polipage.ProjectModeInput.Version.

package main

import (
	"fmt"

	polipage "github.com/poli-page/sdk-go"
)

func main() {
	in := polipage.ProjectModeInput{
		Project:  "billing",
		Template: "invoice",
		Version:  polipage.Opt("1.0.0"),
		Data:     map[string]any{},
	}
	fmt.Println(*in.Version)
}
Output:
1.0.0

func RenderToFile

func RenderToFile(ctx context.Context, c *Client, in ProjectModeInput, path string) error

RenderToFile renders a PDF and streams the bytes straight to disk. Parent directories are created if missing; an existing file at path is overwritten. Memory-bounded — streaming via io.Copy regardless of PDF size.

Errors from the render call propagate as-is (typed *Error). I/O errors surface as *Error with Code == ErrCodeInvalidOptions and the underlying os error wrapped in Cause — use errors.Unwrap to inspect.

Method order matches the spec: callers should reuse a single *Client across calls. RenderToFile is a free function because it is a thin convenience over Render.PDFStream; keeping it off *Client matches the platform spec §2.

Example

ExampleRenderToFile streams a PDF directly to disk. Parent directories are created if missing; existing files are overwritten. Memory stays bounded regardless of document size.

package main

import (
	"context"
	"log"
	"os"

	polipage "github.com/poli-page/sdk-go"
	"github.com/poli-page/sdk-go/option"
)

func main() {
	client := polipage.NewClient(option.WithAPIKey(os.Getenv("POLI_PAGE_API_KEY")))
	err := polipage.RenderToFile(
		context.Background(),
		client,
		polipage.ProjectModeInput{
			Project: "billing", Template: "invoice",
			Version: polipage.Opt("1.0.0"),
			Data:    map[string]any{"invoiceNumber": "INV-001"},
		},
		"out/invoice.pdf",
	)
	if err != nil {
		log.Fatal(err)
	}
}

Types

type Client

type Client struct {

	// Render is the render namespace. See [Render] for available methods.
	Render *Render

	// Documents is the stored-documents namespace. See [Documents] for
	// available methods.
	Documents *Documents
	// contains filtered or unexported fields
}

Client is the Poli Page SDK entry point. Construct one via NewClient and reuse it for the lifetime of the process.

func NewClient

func NewClient(opts ...option.RequestOption) *Client

NewClient constructs a Poli Page SDK client. Options are applied in order; later options override earlier ones for the same field.

Validation is deferred: NewClient never returns an error. If a required option is missing (e.g. option.WithAPIKey), the first method call returns an *Error with Code == ErrCodeInvalidOptions.

client := polipage.NewClient(
    option.WithAPIKey(os.Getenv("POLI_PAGE_API_KEY")),
)
Example

ExampleNewClient demonstrates the canonical construction of a Client. The API key is the only required option; sensible defaults (3 attempts total, 500ms base retry delay, 60s per-request timeout) apply to everything else.

package main

import (
	"os"

	polipage "github.com/poli-page/sdk-go"
	"github.com/poli-page/sdk-go/option"
)

func main() {
	client := polipage.NewClient(
		option.WithAPIKey(os.Getenv("POLI_PAGE_API_KEY")),
		option.WithMaxRetries(3),
	)
	// Share one client across the process — *http.Client pools
	// connections automatically.
	_ = client
}
Example (WithLogger)

ExampleNewClient_withLogger wires a structured slog logger. The SDK emits one DEBUG line per HTTP attempt, one WARN per retry, and one ERROR per terminal failure. Headers and bodies that could contain the API key are not logged.

package main

import (
	"log/slog"
	"os"

	polipage "github.com/poli-page/sdk-go"
	"github.com/poli-page/sdk-go/option"
)

func main() {
	logger := slog.New(slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{Level: slog.LevelDebug}))
	client := polipage.NewClient(
		option.WithAPIKey(os.Getenv("POLI_PAGE_API_KEY")),
		option.WithLogger(logger),
	)
	_ = client
}
Example (WithTimeout)

ExampleNewClient_withTimeout shows the recommended cancellation / deadline pattern: a per-call context.WithTimeout. The Client's own WithTimeout is a fallback applied only when the caller's ctx has no deadline.

package main

import (
	"context"
	"os"
	"time"

	polipage "github.com/poli-page/sdk-go"
	"github.com/poli-page/sdk-go/option"
)

func main() {
	client := polipage.NewClient(option.WithAPIKey(os.Getenv("POLI_PAGE_API_KEY")))

	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	_, _ = client.Render.PDF(ctx, polipage.ProjectModeInput{
		Project: "billing", Template: "invoice",
		Version: polipage.Opt("1.0.0"),
		Data:    map[string]any{},
	})
}

type DocumentDescriptor

type DocumentDescriptor struct {
	DocumentID     string `json:"documentId"`
	OrganizationID string `json:"organizationId"`

	ProjectID    *string `json:"projectId"`
	ProjectSlug  *string `json:"projectSlug"`
	TemplateID   *string `json:"templateId"`
	TemplateSlug *string `json:"templateSlug"`
	Version      *string `json:"version"`
	APIKeyID     *string `json:"apiKeyId"`

	Environment Environment `json:"environment"`
	Format      PageFormat  `json:"format"`

	Orientation *string `json:"orientation"`
	Locale      *string `json:"locale"`

	PageCount int   `json:"pageCount"`
	SizeBytes int64 `json:"sizeBytes"`

	CreatedAt string `json:"createdAt"`
	ExpiresAt string `json:"expiresAt"`

	// Metadata is the caller-supplied metadata echoed by the server. Always
	// non-nil after a successful decode — a server null is normalised to an
	// empty map so callers can range without a nil check.
	Metadata RenderMetadata `json:"metadata"`

	// PresignedPDFURL has a ~15-minute TTL. Re-fetch via Documents.Get when
	// expired.
	PresignedPDFURL string `json:"presignedPdfUrl"`
	// contains filtered or unexported fields
}

DocumentDescriptor is a stored document returned by Render.Document and (in a future phase) Documents.Get. Top-level fields are system-controlled; Metadata echoes caller-supplied data.

Nullable wire fields (ProjectID, ProjectSlug, TemplateID, TemplateSlug, Version, APIKeyID, Orientation, Locale) are *string so the SDK can distinguish JSON null from an empty string.

func (*DocumentDescriptor) DownloadPDF

func (d *DocumentDescriptor) DownloadPDF(ctx context.Context, opts ...option.DownloadOption) ([]byte, error)

DownloadPDF fetches the PDF bytes from PresignedPDFURL. The URL has a ~15-minute TTL — when it expires, call Documents.Get(id) to refresh and retry. Returns *Error with Code == ErrCodeDownloadFailed on non-2xx or network failure.

The request is unauthenticated and is not subject to the SDK's retry policy: presigned-URL fetches go directly to S3 (or equivalent).

Example

ExampleDocumentDescriptor_DownloadPDF fetches the bytes from a descriptor's PresignedPDFURL. Useful when you persisted the descriptor earlier and want to defer the byte fetch until needed.

package main

import (
	"context"
	"log"
	"os"

	polipage "github.com/poli-page/sdk-go"
	"github.com/poli-page/sdk-go/option"
)

func main() {
	client := polipage.NewClient(option.WithAPIKey(os.Getenv("POLI_PAGE_API_KEY")))
	doc, err := client.Documents.Get(context.Background(), "doc_abc123")
	if err != nil {
		log.Fatal(err)
	}
	pdf, err := doc.DownloadPDF(context.Background())
	if err != nil {
		log.Fatal(err)
	}
	_ = os.WriteFile("invoice.pdf", pdf, 0o644)
}

type DocumentPreviewResult

type DocumentPreviewResult struct {
	HTML      string
	PageCount int
}

DocumentPreviewResult is the result of Documents.Preview — the paginated HTML for an already-stored document and the page count the engine emitted at render time.

Note: the field is PageCount (singular) here, distinct from PreviewResult.TotalPages returned by Render.Preview. The deployed API uses different field shapes for the two endpoints.

type Documents

type Documents struct {
	// contains filtered or unexported fields
}

Documents is the stored-documents namespace exposed as client.Documents. It hosts the four lifecycle methods defined in spec §6.

func (*Documents) Delete

func (d *Documents) Delete(ctx context.Context, id string, opts ...option.RequestOption) error

Delete soft-deletes a stored document. The PDF is purged from storage; metadata is retained for audit. Already-deleted documents surface as ErrGone (HTTP 410) — use errors.Is to branch on it.

Spec §6.4.

Example

ExampleDocuments_Delete soft-deletes a stored document. Subsequent reads of the same documentId surface as polipage.ErrGone.

package main

import (
	"context"
	"log"
	"os"

	polipage "github.com/poli-page/sdk-go"
	"github.com/poli-page/sdk-go/option"
)

func main() {
	client := polipage.NewClient(option.WithAPIKey(os.Getenv("POLI_PAGE_API_KEY")))
	if err := client.Documents.Delete(context.Background(), "doc_abc123"); err != nil {
		log.Fatal(err)
	}
}

func (*Documents) Get

Get retrieves a stored document's descriptor with a fresh presigned URL. The returned descriptor's DocumentDescriptor.DownloadPDF uses the parent client for transport; calling it after the URL's ~15-minute TTL returns *Error{Code: ErrCodeDownloadFailed} — re-fetch via Get.

Spec §6.1.

Example

ExampleDocuments_Get retrieves a stored document with a fresh presigned URL. The PDF download URL has a ~15-minute TTL — call Get again to reissue it once expired.

package main

import (
	"context"
	"fmt"
	"log"
	"os"

	polipage "github.com/poli-page/sdk-go"
	"github.com/poli-page/sdk-go/option"
)

func main() {
	client := polipage.NewClient(option.WithAPIKey(os.Getenv("POLI_PAGE_API_KEY")))
	doc, err := client.Documents.Get(context.Background(), "doc_abc123")
	if err != nil {
		log.Fatal(err)
	}
	pdf, err := doc.DownloadPDF(context.Background())
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%d bytes\n", len(pdf))
}

func (*Documents) Preview

Preview retrieves a stored document's paginated HTML. The engine does no work — this is a cheap read.

The deployed API returns the HTML as text/html (not a JSON envelope) and the page count via the X-Document-Page-Count response header. Missing or unparseable headers are tolerated: PageCount defaults to 0.

Spec §6.2.

Example

ExampleDocuments_Preview retrieves the stored HTML for a document. The engine performs no work on this call — it's a cheap read suitable for preview UIs and snapshot tests in CI.

package main

import (
	"context"
	"fmt"
	"log"
	"os"

	polipage "github.com/poli-page/sdk-go"
	"github.com/poli-page/sdk-go/option"
)

func main() {
	client := polipage.NewClient(option.WithAPIKey(os.Getenv("POLI_PAGE_API_KEY")))
	res, err := client.Documents.Preview(context.Background(), "doc_abc123")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%d page(s), %d chars HTML\n", res.PageCount, len(res.HTML))
}

func (*Documents) Thumbnails

func (d *Documents) Thumbnails(ctx context.Context, id string, options ThumbnailOptions, opts ...option.RequestOption) ([]Thumbnail, error)

Thumbnails generates page thumbnails for a stored document. Width is required. Pass polipage.ThumbnailFormatJPEG with a Quality value for JPEG output; otherwise PNG is returned.

The deployed API expects the options wrapped under a top-level "thumbnails" key on the wire and returns the array under the same key — both are handled here so callers see a plain slice.

Spec §6.3.

Example

ExampleDocuments_Thumbnails generates page thumbnails. Pass polipage.ThumbnailFormatJPEG with a Quality value for JPEG output; otherwise PNG is returned. Tier-gated on the API — Free tier returns THUMBNAILS_NOT_AVAILABLE.

package main

import (
	"context"
	"fmt"
	"log"
	"os"

	polipage "github.com/poli-page/sdk-go"
	"github.com/poli-page/sdk-go/option"
)

func main() {
	client := polipage.NewClient(option.WithAPIKey(os.Getenv("POLI_PAGE_API_KEY")))
	thumbs, err := client.Documents.Thumbnails(
		context.Background(),
		"doc_abc123",
		polipage.ThumbnailOptions{
			Width:  840,
			Format: polipage.ThumbnailFormatPNG,
			Pages:  []int{1, 2, 3},
		},
	)
	if err != nil {
		log.Fatal(err)
	}
	for _, t := range thumbs {
		fmt.Printf("page %d: %dx%d %s\n", t.Page, t.Width, t.Height, t.ContentType)
	}
}

type Environment

type Environment string

Environment is the API environment a stored document belongs to.

const (
	EnvironmentSandbox Environment = "sandbox"
	EnvironmentLive    Environment = "live"
)

Document environments.

type Error

type Error struct {
	// Code is the machine-readable error code. For HTTP errors this is the
	// API's code field (verbatim); for SDK-internal errors it is one of
	// ErrCode* (invalid_options, network_error, timeout, aborted, etc.).
	Code string
	// StatusCode is the HTTP response status. Zero for SDK-internal errors
	// (network failure, timeout, abort, constructor validation).
	StatusCode int
	// Message is the human-readable error message.
	Message string
	// RequestID is the x-request-id header value when present; empty otherwise.
	RequestID string
	// Cause is the underlying error this *Error wraps. nil when the error
	// originated in the SDK itself with no upstream cause.
	Cause error
}

Error is the single error type raised by the SDK: API errors, network failures, timeouts, caller cancellation, and constructor validation failures all surface as *Error.

Callers can use either errors.Is against the package-level sentinels (ErrNotFound, ErrUnauthorized, etc.) for quick branching or errors.As to inspect Code, StatusCode, RequestID, and the wrapped Cause.

Example (TypedInspection)

ExampleError_typedInspection demonstrates the two idiomatic ways to branch on errors returned by the SDK: errors.Is against the package-level sentinels for quick checks, and errors.As to inspect the full *Error value (Code, StatusCode, RequestID, Cause).

package main

import (
	"context"
	"errors"
	"fmt"

	polipage "github.com/poli-page/sdk-go"
	"github.com/poli-page/sdk-go/option"
)

func main() {
	client := polipage.NewClient(option.WithAPIKey("pp_test_bad_key"))
	_, err := client.Render.PDF(context.Background(), polipage.ProjectModeInput{
		Project: "x", Template: "y", Data: map[string]any{},
	})
	if errors.Is(err, polipage.ErrUnauthorized) {
		// refresh credentials, surface to the user, ...
	}
	var pErr *polipage.Error
	if errors.As(err, &pErr) {
		fmt.Printf("code=%s status=%d requestID=%s\n", pErr.Code, pErr.StatusCode, pErr.RequestID)
	}
}

func (*Error) Error

func (e *Error) Error() string

Error implements the error interface. The format is stable but not parseable — callers wanting structured access should use errors.As to extract *Error.

func (*Error) Is

func (e *Error) Is(target error) bool

Is supports errors.Is by matching the receiver against package-level sentinel errors via their Code field. A small number of logical groups (auth: MISSING_API_KEY / INVALID_API_KEY; rate-limit: QUOTA_EXCEEDED / OVERAGE_CAP_EXCEEDED) compare equal so the corresponding sentinel matches either underlying code.

func (*Error) IsAuthError

func (e *Error) IsAuthError() bool

IsAuthError reports whether the response was 401 or 403 — invalid, missing, or unauthorized API key.

func (*Error) IsNetworkError

func (e *Error) IsNetworkError() bool

IsNetworkError reports whether the error is a transport-level failure (DNS, connection refused, TLS) or a per-request timeout. Caller-aborted requests (ErrCodeAborted) and constructor-validation failures (ErrCodeInvalidOptions) do not count.

func (*Error) IsRateLimitError

func (e *Error) IsRateLimitError() bool

IsRateLimitError reports whether the response was 429 — too many requests.

func (*Error) IsRetryable

func (e *Error) IsRetryable() bool

IsRetryable reports whether the SDK considers this error retryable (5xx, 429, network failure, timeout). Caller-aborted requests are never retryable. The SDK already retries internally up to the configured limit; this predicate is useful when an outer queue or scheduler decides whether to re-enqueue the job.

func (*Error) IsValidationError

func (e *Error) IsValidationError() bool

IsValidationError reports whether the response was 400 — request payload failed validation.

func (*Error) ToPayload

func (e *Error) ToPayload() Payload

ToPayload returns the canonical wire payload for framework integrations. The Error.StatusCode field stays 0 for transport failures — only the payload surfaces 503/504, so callers reading StatusCode are not affected.

func (*Error) Unwrap

func (e *Error) Unwrap() error

Unwrap exposes the wrapped Cause to errors.Is and errors.As.

type InlineModeInput

type InlineModeInput struct {
	Data     map[string]any `json:"data"`
	Template string         `json:"template"` // raw HTML

	Format      PageFormat     `json:"format,omitempty"`
	Orientation Orientation    `json:"orientation,omitempty"`
	Locale      string         `json:"locale,omitempty"`
	Metadata    RenderMetadata `json:"metadata,omitempty"`
}

InlineModeInput renders raw HTML with no project resolution. Use this with Render.Preview to validate templates before saving them.

type Orientation

type Orientation string

Orientation is the page orientation: portrait or landscape.

const (
	OrientationPortrait  Orientation = "portrait"
	OrientationLandscape Orientation = "landscape"
)

Canonical orientations.

type PageFormat

type PageFormat string

PageFormat is a canonical Poli Page page format. Values match the strings accepted by the deployed API and shared across every SDK.

const (
	PageFormatA3        PageFormat = "A3"
	PageFormatA4        PageFormat = "A4"
	PageFormatA5        PageFormat = "A5"
	PageFormatA6        PageFormat = "A6"
	PageFormatB4        PageFormat = "B4"
	PageFormatB5        PageFormat = "B5"
	PageFormatLetter    PageFormat = "Letter"
	PageFormatLegal     PageFormat = "Legal"
	PageFormatTabloid   PageFormat = "Tabloid"
	PageFormatExecutive PageFormat = "Executive"
	PageFormatStatement PageFormat = "Statement"
	PageFormatFolio     PageFormat = "Folio"
)

Canonical page formats. See the platform spec for the authoritative list.

type Payload

type Payload struct {
	Code      string `json:"code"`
	Message   string `json:"message"`
	Status    int    `json:"status,omitempty"`
	RequestID string `json:"requestId,omitempty"`
}

Payload is the canonical wire shape for framework integrations: {code, message, status, requestId}. Status is the API HTTP status for status-bearing failures, 503 for network failures, 504 for timeouts, omitted otherwise.

type PreviewResult

type PreviewResult struct {
	HTML        string      `json:"html"`
	TotalPages  int         `json:"totalPages"`
	Environment Environment `json:"environment"`
}

PreviewResult is the result of Render.Preview — paginated HTML, the total page count the engine produced, and the environment that served the request.

type ProjectModeInput

type ProjectModeInput struct {
	// Required.
	Project  string         `json:"project"`
	Template string         `json:"template"`
	Data     map[string]any `json:"data"`

	// Optional — omitted from the wire when unset.
	Version     *string        `json:"version,omitempty"`
	Format      PageFormat     `json:"format,omitempty"`
	Orientation Orientation    `json:"orientation,omitempty"`
	Locale      string         `json:"locale,omitempty"`
	Metadata    RenderMetadata `json:"metadata,omitempty"`
}

ProjectModeInput renders against a stored project + template by slug. Use Opt to set Version with a literal: Version: polipage.Opt("1.0.0").

type Render

type Render struct {
	// contains filtered or unexported fields
}

Render is the render namespace exposed as client.Render. Phase 3 ships Preview + PDF + PDFStream + Document, the full spec §5.1–§5.3 surface.

func (*Render) Document

Document renders a PDF, stores it server-side, and returns the descriptor. The PDF bytes are NOT fetched — call (*DocumentDescriptor).DownloadPDF when you need them, or use Render.PDF / Render.PDFStream for the one-call shortcut.

Accepts ProjectModeInput only. Inline mode (raw HTML) is rejected at compile time by the signature and again at run time defensively.

Example

ExampleRender_Document stores the document server-side and returns its descriptor without auto-fetching the PDF bytes. Use when you want to persist the documentId for later access (preview, thumbnails, re-download) without paying for the bytes up front.

package main

import (
	"context"
	"fmt"
	"log"
	"os"

	polipage "github.com/poli-page/sdk-go"
	"github.com/poli-page/sdk-go/option"
)

func main() {
	client := polipage.NewClient(option.WithAPIKey(os.Getenv("POLI_PAGE_API_KEY")))
	doc, err := client.Render.Document(context.Background(), polipage.ProjectModeInput{
		Project: "billing", Template: "invoice",
		Version: polipage.Opt("1.0.0"),
		Data:    map[string]any{"invoiceNumber": "INV-001"},
		// Metadata is echoed back on Documents.Get — primitives only.
		Metadata: polipage.RenderMetadata{"customerId": "cust_123"},
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("documentId=%s pages=%d\n", doc.DocumentID, doc.PageCount)
}

func (*Render) PDF

func (r *Render) PDF(ctx context.Context, in ProjectModeInput, opts ...option.RequestOption) ([]byte, error)

PDF renders a PDF and returns the raw bytes. Two HTTP calls under the hood: POST /v1/render to produce a stored document, then GET PresignedPDFURL to fetch the bytes.

Example

ExampleRender_PDF renders a project-mode document into a []byte. Two HTTP calls under the hood; one from the caller's point of view.

package main

import (
	"context"
	"fmt"
	"log"
	"os"

	polipage "github.com/poli-page/sdk-go"
	"github.com/poli-page/sdk-go/option"
)

func main() {
	client := polipage.NewClient(option.WithAPIKey(os.Getenv("POLI_PAGE_API_KEY")))
	pdf, err := client.Render.PDF(context.Background(), polipage.ProjectModeInput{
		Project:  "billing",
		Template: "invoice",
		Version:  polipage.Opt("1.0.0"),
		Data:     map[string]any{"invoiceNumber": "INV-001"},
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("PDF size: %d bytes\n", len(pdf))
}
Example (WithIdempotencyKey)

ExampleRender_PDF_withIdempotencyKey supplies a natural identifier as the Idempotency-Key so retried requests against the same logical invoice never produce duplicate documents server-side.

package main

import (
	"context"
	"os"

	polipage "github.com/poli-page/sdk-go"
	"github.com/poli-page/sdk-go/option"
)

func main() {
	client := polipage.NewClient(option.WithAPIKey(os.Getenv("POLI_PAGE_API_KEY")))
	_, _ = client.Render.PDF(
		context.Background(),
		polipage.ProjectModeInput{
			Project: "billing", Template: "invoice",
			Version: polipage.Opt("1.0.0"),
			Data:    map[string]any{"invoiceNumber": "INV-001"},
		},
		option.WithIdempotencyKey("inv-INV-001"),
	)
}

func (*Render) PDFStream

func (r *Render) PDFStream(ctx context.Context, in ProjectModeInput, opts ...option.RequestOption) (io.ReadCloser, error)

PDFStream is like Render.PDF but returns the PDF as an io.ReadCloser so the caller can stream it directly to an HTTP response, an S3 upload, or a file without buffering.

The caller MUST close the returned ReadCloser when done, even on early return paths.

Example

ExampleRender_PDFStream streams PDF bytes directly to a destination without buffering — memory stays bounded regardless of document size. The caller MUST close the returned ReadCloser.

package main

import (
	"context"
	"io"
	"log"
	"os"

	polipage "github.com/poli-page/sdk-go"
	"github.com/poli-page/sdk-go/option"
)

func main() {
	client := polipage.NewClient(option.WithAPIKey(os.Getenv("POLI_PAGE_API_KEY")))
	body, err := client.Render.PDFStream(context.Background(), polipage.ProjectModeInput{
		Project: "billing", Template: "invoice",
		Version: polipage.Opt("1.0.0"),
		Data:    map[string]any{"invoiceNumber": "INV-001"},
	})
	if err != nil {
		log.Fatal(err)
	}
	defer func() { _ = body.Close() }()

	out, _ := os.Create("invoice.pdf")
	defer func() { _ = out.Close() }()
	_, _ = io.Copy(out, body)
}

func (*Render) Preview

func (r *Render) Preview(ctx context.Context, in RenderInput, opts ...option.RequestOption) (*PreviewResult, error)

Preview generates paginated HTML from the input. Accepts both ProjectModeInput and InlineModeInput — that is the only render method that allows inline-mode HTML.

Variadic options apply per-call. The most useful one is option.WithIdempotencyKey when the caller has a natural identifier (e.g. an invoice number) and wants to override the auto-generated UUID4.

Example

ExampleRender_Preview generates paginated HTML. Unlike PDF/PDFStream/ Document, Preview accepts both polipage.ProjectModeInput and polipage.InlineModeInput — useful for validating raw templates before saving them.

package main

import (
	"context"
	"fmt"
	"log"
	"os"

	polipage "github.com/poli-page/sdk-go"
	"github.com/poli-page/sdk-go/option"
)

func main() {
	client := polipage.NewClient(option.WithAPIKey(os.Getenv("POLI_PAGE_API_KEY")))
	res, err := client.Render.Preview(context.Background(), polipage.InlineModeInput{
		Template: "<html><body><h1>{{ name }}</h1></body></html>",
		Data:     map[string]any{"name": "Mickael"},
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%d page(s), %d chars HTML\n", res.TotalPages, len(res.HTML))
}

type RenderInput

type RenderInput interface {
	// contains filtered or unexported methods
}

RenderInput is the marker interface satisfied by ProjectModeInput and InlineModeInput only. External packages cannot satisfy it (the marker method is unexported) — that is how Render.PDF / PDFStream / Document enforce project-mode-only at compile time.

type RenderMetadata

type RenderMetadata = map[string]any

RenderMetadata is free-form caller metadata forwarded to the API and echoed on responses that support it. Values must be primitives (string, number, bool); nested maps and slices are rejected at serialise time with *Error{Code: ErrCodeInvalidOptions}.

type RequestEvent

type RequestEvent = clientconfig.RequestEvent

RequestEvent is delivered to the OnRequest hook before each HTTP attempt. Aliased to clientconfig.RequestEvent so option.WithOnRequest and the re-export here both spell the type identically.

type ResponseEvent

type ResponseEvent = clientconfig.ResponseEvent

ResponseEvent is delivered to the OnResponse hook after each successful 2xx response. Aliased to clientconfig.ResponseEvent.

type RetryEvent

type RetryEvent = clientconfig.RetryEvent

RetryEvent is delivered to the OnRetry hook before each retry sleep. Aliased to clientconfig.RetryEvent so option.WithOnRetry and the re-export here can both spell the type identically.

type Thumbnail

type Thumbnail struct {
	Page        int    `json:"page"`
	Width       int    `json:"width"`
	Height      int    `json:"height"`
	ContentType string `json:"contentType"`
	Data        string `json:"data"`
}

Thumbnail is a single page thumbnail returned by Documents.Thumbnails. Data is base64-encoded image bytes; the caller decodes via encoding/base64.StdEncoding.DecodeString as needed.

type ThumbnailFormat

type ThumbnailFormat string

ThumbnailFormat is the image format for a generated thumbnail. PNG is the default; JPEG accepts an additional Quality option.

const (
	ThumbnailFormatPNG  ThumbnailFormat = "png"
	ThumbnailFormatJPEG ThumbnailFormat = "jpeg"
)

Canonical thumbnail formats.

type ThumbnailOptions

type ThumbnailOptions struct {
	// Width is the thumbnail width in pixels. Required.
	Width int `json:"width"`
	// Format selects PNG (default) or JPEG output.
	Format ThumbnailFormat `json:"format,omitempty"`
	// Quality is the JPEG quality 1-100. Only valid when Format is JPEG.
	Quality int `json:"quality,omitempty"`
	// Pages selects specific 1-based page numbers. Empty means all pages.
	Pages []int `json:"pages,omitempty"`
}

ThumbnailOptions configures a thumbnail-generation request. Width is required; other fields default per spec §6.3.

Directories

Path Synopsis
cmd
demo command
Demo of the official Poli Page SDK for Go.
Demo of the official Poli Page SDK for Go.
examples
documents-delete command
Demonstrates: client.Documents.Delete(ctx, id) — soft-delete a stored document.
Demonstrates: client.Documents.Delete(ctx, id) — soft-delete a stored document.
documents-get command
Demonstrates: client.Documents.Get(ctx, id) — fetch a stored document.
Demonstrates: client.Documents.Get(ctx, id) — fetch a stored document.
documents-preview command
Demonstrates: client.Documents.Preview(ctx, id) — get a stored document's HTML preview.
Demonstrates: client.Documents.Preview(ctx, id) — get a stored document's HTML preview.
documents-thumbnails command
Demonstrates: client.Documents.Thumbnails(ctx, id, options) — page thumbnails for a stored document.
Demonstrates: client.Documents.Thumbnails(ctx, id, options) — page thumbnails for a stored document.
poli-page-constructor command
Demonstrates: polipage.NewClient(options) — the only entry point.
Demonstrates: polipage.NewClient(options) — the only entry point.
render-document command
Demonstrates: client.Render.Document(ctx, in) — render and store a PDF server-side.
Demonstrates: client.Render.Document(ctx, in) — render and store a PDF server-side.
render-pdf command
Demonstrates: client.Render.PDF(ctx, in) — project mode only.
Demonstrates: client.Render.PDF(ctx, in) — project mode only.
render-pdf-stream command
Demonstrates: client.Render.PDFStream(ctx, in) — project mode only.
Demonstrates: client.Render.PDFStream(ctx, in) — project mode only.
render-preview command
Demonstrates: client.Render.Preview(ctx, in) — accepts project mode OR inline mode.
Demonstrates: client.Render.Preview(ctx, in) — accepts project mode OR inline mode.
render-to-file command
Demonstrates: polipage.RenderToFile(ctx, client, in, path) — streams a PDF to disk.
Demonstrates: polipage.RenderToFile(ctx, client, in, path) — streams a PDF to disk.
internal
clientconfig
Package clientconfig holds the mutable Config used by the polipage client and the option subpackage.
Package clientconfig holds the mutable Config used by the polipage client and the option subpackage.
constants
Package constants holds the SDK-internal string values shared between the transport layer and the namespace implementations: API path templates, canonical HTTP header names, and any other magic strings that would otherwise be re-typed at multiple call sites.
Package constants holds the SDK-internal string values shared between the transport layer and the namespace implementations: API path templates, canonical HTTP header names, and any other magic strings that would otherwise be re-typed at multiple call sites.
http
Package http contains the pure transport-layer helpers used by the top-level polipage client.
Package http contains the pure transport-layer helpers used by the top-level polipage client.
uuid
Package uuid generates RFC 4122 §4.4 version-4 UUIDs from crypto/rand.
Package uuid generates RFC 4122 §4.4 version-4 UUIDs from crypto/rand.
version
Package version exposes the SDK build version, embedded into the User-Agent header by the transport layer.
Package version exposes the SDK build version, embedded into the User-Agent header by the transport layer.
Package option holds the functional options for constructing a polipage.Client and overriding behavior on individual method calls.
Package option holds the functional options for constructing a polipage.Client and overriding behavior on individual method calls.
scripts
extract-api command
Command extract-api walks the public Poli Page Go SDK surface with go/packages + go/doc and emits the docs/src/content/docs/reference/ tree consumed by the Starlight site.
Command extract-api walks the public Poli Page Go SDK surface with go/packages + go/doc and emits the docs/src/content/docs/reference/ tree consumed by the Starlight site.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL