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 ¶
- Constants
- Variables
- func RenderToFile(ctx context.Context, c *Client, in RenderInput, path string) error
- type Client
- type DocumentDescriptor
- type DocumentPreviewResult
- type Documents
- func (d *Documents) Delete(ctx context.Context, id string, opts ...option.RequestOption) error
- func (d *Documents) Get(ctx context.Context, id string, opts ...option.RequestOption) (*DocumentDescriptor, error)
- func (d *Documents) Preview(ctx context.Context, id string, opts ...option.RequestOption) (*DocumentPreviewResult, error)
- func (d *Documents) Thumbnails(ctx context.Context, id string, options ThumbnailOptions, ...) ([]Thumbnail, error)
- type Error
- func (e *Error) Error() string
- func (e *Error) Is(target error) bool
- func (e *Error) IsAuthError() bool
- func (e *Error) IsNetworkError() bool
- func (e *Error) IsRateLimitError() bool
- func (e *Error) IsRetryable() bool
- func (e *Error) IsValidationError() bool
- func (e *Error) ToPayload() Payload
- func (e *Error) Unwrap() error
- type Orientation
- type PageFormat
- type Payload
- type Render
- func (r *Render) Document(ctx context.Context, in RenderInput, opts ...option.RequestOption) (*DocumentDescriptor, error)
- func (r *Render) PDF(ctx context.Context, in RenderInput, opts ...option.RequestOption) ([]byte, error)
- func (r *Render) PDFStream(ctx context.Context, in RenderInput, opts ...option.RequestOption) (io.ReadCloser, error)
- type RenderInput
- type RenderMetadata
- type RequestEvent
- type ResponseEvent
- type RetryEvent
- type Thumbnail
- type ThumbnailFormat
- type ThumbnailOptions
Examples ¶
Constants ¶
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 (a canceled // context.Context). 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.
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 ErrCodeForbidden = "FORBIDDEN" ErrCodeOrganizationCancelled = "ORGANIZATION_CANCELLED" ErrCodeOrganizationPurged = "ORGANIZATION_PURGED" ErrCodeOrganizationPaymentGrace = "ORGANIZATION_PAYMENT_GRACE" ErrCodeOrganizationMigrating = "ORGANIZATION_MIGRATING" ErrCodeEnvironmentMismatch = "ENVIRONMENT_MISMATCH" ErrCodeEnvironmentProtected = "ENVIRONMENT_PROTECTED" ErrCodeNotFound = "NOT_FOUND" ErrCodeProjectNotFound = "PROJECT_NOT_FOUND" ErrCodeProjectNotInEnvironment = "PROJECT_NOT_IN_ENVIRONMENT" ErrCodeTemplateNotFound = "TEMPLATE_NOT_FOUND" ErrCodeDocumentNotFound = "DOCUMENT_NOT_FOUND" ErrCodeDocumentGone = "DOCUMENT_GONE" ErrCodeValidationError = "VALIDATION_ERROR" ErrCodeMissingData = "MISSING_DATA" ErrCodeMissingTemplateSlug = "MISSING_TEMPLATE_SLUG" ErrCodeProjectRequiredForDocument = "PROJECT_REQUIRED_FOR_DOCUMENT" ErrCodeTemplateError = "TEMPLATE_ERROR" ErrCodeTemplateUnsafe = "TEMPLATE_UNSAFE" ErrCodeEmptyDocument = "EMPTY_DOCUMENT" ErrCodeRenderBodyTooLarge = "RENDER_BODY_TOO_LARGE" ErrCodeDocumentTooLarge = "DOCUMENT_TOO_LARGE" ErrCodeThumbnailsNotAvailable = "THUMBNAILS_NOT_AVAILABLE" ErrCodeQuotaExceeded = "QUOTA_EXCEEDED" ErrCodeOverageCapExceeded = "OVERAGE_CAP_EXCEEDED" ErrCodeRateLimitExceeded = "RATE_LIMIT_EXCEEDED" // ErrCodePublishInProgress is a 503 answered while a publish locks the // project in the key's environment. Retried like any 5xx, honouring // Retry-After. ErrCodePublishInProgress = "PUBLISH_IN_PROGRESS" ErrCodeStorageAccessDenied = "STORAGE_ACCESS_DENIED" ErrCodeRenderTimeout = "RENDER_TIMEOUT" // 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.
const ( // DefaultBaseURL is the production Poli Page API base URL. Override via // option.WithBaseURL to target another API host. 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 ¶
var ( ErrForbidden = &Error{Code: ErrCodeForbidden} // ErrNotFound = &Error{Code: ErrCodeNotFound} // ErrDocumentNotFound = &Error{Code: ErrCodeDocumentNotFound} // ErrDocumentGone = &Error{Code: ErrCodeDocumentGone} // 410 — document deleted or expired 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 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 RenderToFile ¶
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.RenderInput{
Project: "billing", Template: "invoice",
Data: map[string]any{"invoiceNumber": "INV-001"},
},
"out/invoice.pdf",
)
if err != nil {
log.Fatal(err)
}
}
Output:
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
}
Output:
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
}
Output:
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.RenderInput{
Project: "billing", Template: "invoice",
Data: map[string]any{},
})
}
Output:
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"`
APIKeyID *string `json:"apiKeyId"`
// Environment is the name of the environment the document was rendered
// in ("sandbox", "live", or any other environment of the organization),
// returned as the API sent it.
Environment string `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 Documents.Get. Top-level fields are system-controlled; Metadata echoes caller-supplied data.
Nullable wire fields (ProjectID, ProjectSlug, TemplateID, TemplateSlug, 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.
A non-2xx answer returns *Error with Code == ErrCodeDownloadFailed and the storage status; a network failure, before the answer or while the body is read, returns ErrCodeDownloadFailed without a status. Canceling ctx returns ErrCodeAborted. The underlying error is wrapped in Cause.
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)
}
Output:
type DocumentPreviewResult ¶
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.
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 ¶
Delete soft-deletes a stored document. The PDF is purged from storage; metadata is retained for audit. Deleting an already-deleted document also succeeds: the API answers 204 either way.
Spec §6.4.
Example ¶
ExampleDocuments_Delete soft-deletes a stored document. Deleting it again also succeeds; subsequent reads of the same documentId surface as polipage.ErrDocumentGone.
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)
}
}
Output:
func (*Documents) Get ¶
func (d *Documents) Get(ctx context.Context, id string, opts ...option.RequestOption) (*DocumentDescriptor, error)
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))
}
Output:
func (*Documents) Preview ¶
func (d *Documents) Preview(ctx context.Context, id string, opts ...option.RequestOption) (*DocumentPreviewResult, error)
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))
}
Output:
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. Every option is optional: pass a zero ThumbnailOptions for the API defaults (400 px wide JPEG, every page).
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. With no option set the body is {}.
Spec §6.3.
Example ¶
ExampleDocuments_Thumbnails generates page thumbnails. Every option is optional: a zero polipage.ThumbnailOptions gets the API defaults (400 px wide JPEG, every page). 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.ThumbnailFormatWebP,
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)
}
}
Output:
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_sandbox_bad_key"))
_, err := client.Render.PDF(context.Background(), polipage.RenderInput{
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)
}
}
Output:
func (*Error) Error ¶
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 ¶
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 ¶
IsAuthError reports whether the response was 401 or 403 — invalid, missing, or unauthorized API key.
func (*Error) IsNetworkError ¶
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 ¶
IsRateLimitError reports whether the response was 429 — too many requests.
func (*Error) IsRetryable ¶
IsRetryable reports whether the SDK considers this error retryable: a network failure, a timeout, a 5xx or a 429, except QUOTA_EXCEEDED, OVERAGE_CAP_EXCEEDED and STORAGE_ACCESS_DENIED, which last until the monthly reset or until the bucket access is restored. A DOWNLOAD_FAILED is never retryable, whatever the storage status. 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 ¶
IsValidationError reports whether the response was 400 — request payload failed validation.
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"`
RequestID string `json:"requestId"`
}
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, and 0 otherwise. In JSON, a zero Status and an empty RequestID are null.
Do not embed Payload in another struct: its MarshalJSON is promoted, so the embedding struct marshals as the Payload alone and its own fields drop out of the JSON. Use a named field instead.
func (Payload) MarshalJSON ¶ added in v0.11.0
MarshalJSON writes Status and RequestID as null when they are unknown (zero and empty), as the SDK specification's toPayload() does.
type Render ¶
type Render struct {
// contains filtered or unexported fields
}
Render is the render namespace exposed as client.Render: PDF, PDFStream and Document, the spec §5 surface.
func (*Render) Document ¶
func (r *Render) Document(ctx context.Context, in RenderInput, opts ...option.RequestOption) (*DocumentDescriptor, error)
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.
The API renders the project's copy published in the API key's environment. 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_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.RenderInput{
Project: "billing", Template: "invoice",
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)
}
Output:
func (*Render) PDF ¶
func (r *Render) PDF(ctx context.Context, in RenderInput, 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 template of a project into a []byte, using the project's copy published in the API key's environment. 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.RenderInput{
Project: "billing",
Template: "invoice",
Data: map[string]any{"invoiceNumber": "INV-001"},
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("PDF size: %d bytes\n", len(pdf))
}
Output:
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.RenderInput{
Project: "billing", Template: "invoice",
Data: map[string]any{"invoiceNumber": "INV-001"},
},
option.WithIdempotencyKey("inv-INV-001"),
)
}
Output:
func (*Render) PDFStream ¶
func (r *Render) PDFStream(ctx context.Context, in RenderInput, 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.RenderInput{
Project: "billing", Template: "invoice",
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)
}
Output:
type RenderInput ¶
type RenderInput struct {
// Required.
Project string `json:"project"`
Template string `json:"template"`
Data map[string]any `json:"data"`
// Optional — omitted from the wire when unset.
Format PageFormat `json:"format,omitempty"`
Orientation Orientation `json:"orientation,omitempty"`
Locale string `json:"locale,omitempty"`
Metadata RenderMetadata `json:"metadata,omitempty"`
}
RenderInput is the input of every render method: a template of a project, rendered with the project's copy published in the API key's environment. Only these seven fields are sent; unset optional fields are omitted from the wire.
type RenderMetadata ¶
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 once per 2xx attempt, after its body has been read in full; never for a 2xx whose body read fails. DurationMs runs from just before the request is sent until the body is read. 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. The API default is JPEG, which also accepts a Quality option.
const ( ThumbnailFormatJPEG ThumbnailFormat = "jpeg" ThumbnailFormatWebP ThumbnailFormat = "webp" ThumbnailFormatPNG ThumbnailFormat = "png" )
Canonical thumbnail formats.
type ThumbnailOptions ¶
type ThumbnailOptions struct {
// Width is the thumbnail width in pixels, 50-2000. API default: 400.
Width int `json:"width,omitempty"`
// Format selects jpeg, webp or png. API default: jpeg.
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. Every field is optional: a zero value is not sent and the API applies its default. The SDK does not check bounds; the API answers 400 VALIDATION_ERROR.
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) — renders the project's copy published in the key's environment.
|
Demonstrates: client.Render.PDF(ctx, in) — renders the project's copy published in the key's environment. |
|
render-pdf-stream
command
Demonstrates: client.Render.PDFStream(ctx, in) — renders the project's copy published in the key's environment.
|
Demonstrates: client.Render.PDFStream(ctx, in) — renders the project's copy published in the key's environment. |
|
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. |