api2convert

package module
v10.4.0 Latest Latest
Warning

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

Go to latest
Published: Aug 12, 2026 License: MIT Imports: 25 Imported by: 0

README

API2Convert Go SDK

CI Go Reference Release License

The official Go SDK for the API2Convert file-conversion API — convert, compress and transform files with one call. It is one of the official ports (PHP, Python, Java, Node.js, Go) that all implement the same SDK contract.

  • Zero third-party runtime dependencies (standard library only).
  • context.Context-first, functional options, typed errors (errors.As).
  • Automatic retries with jittered backoff; job polling with a floored interval and capped timeout.
  • Streaming multipart upload and streaming download.
  • Secret-safe by design: the account key, per-job token and download password never follow a redirect and never appear in a URL or an error message (see SECURITY.md).

Install

go get github.com/QaamGo/api2convert-go/v10

Requires Go 1.22+.

Quick start

package main

import (
	"context"
	"log"

	api2convert "github.com/QaamGo/api2convert-go/v10"
)

func main() {
	// The API key falls back to the API2CONVERT_API_KEY env var when "".
	client, err := api2convert.New("YOUR_API_KEY")
	if err != nil {
		log.Fatal(err)
	}

	res, err := client.Convert(context.Background(), "photo.png", "jpg")
	if err != nil {
		log.Fatal(err)
	}
	if _, err := res.Save(context.Background(), "photo.jpg"); err != nil {
		log.Fatal(err)
	}
}

Convert accepts a local path (string), a public URL (^https?://), in-memory bytes ([]byte), or an io.Reader.

More examples

Given a client and a ctx context.Context, each variation is a single call. (Error handling is elided here — check it as in the quick start above.)

// From a URL (fetched server-side).
res, err := client.Convert(ctx, "https://example.com/photo.png", "jpg")

// With conversion options (discover them via client.Options); saving into a
// directory keeps the API's filename.
res, err = client.Convert(ctx, "photo.png", "jpg",
	api2convert.WithConversionOptions(map[string]any{"quality": 85, "width": 1280, "height": 720}))
res.Save(ctx, "out/")

// Password-protected output — remembered and applied automatically on download.
res, err = client.Convert(ctx, "statement.docx", "pdf",
	api2convert.WithDownloadPassword("hunter2"))

// Async with a webhook callback (returns once the job is started).
job, err := client.ConvertAsync(ctx, "movie.mov", "mp4",
	api2convert.WithCallback("https://your-app.example.com/webhooks/api2convert"))

Typed errors

Every failure the SDK returns satisfies api2convert.Api2ConvertError. Match specific failures with errors.As:

res, err := client.Convert(ctx, "in.psd", "png")
switch {
case err == nil:
	// ok
default:
	var rl *api2convert.RateLimitError
	var ve *api2convert.ValidationError
	var cf *api2convert.ConversionFailedError
	switch {
	case errors.As(err, &rl):
		if rl.RetryAfter != nil {
			log.Printf("rate limited; retry after %ds", *rl.RetryAfter)
		} else {
			log.Print("rate limited; retry after (unspecified)")
		}
	case errors.As(err, &ve):
		log.Printf("invalid request: %v", ve)
	case errors.As(err, &cf):
		log.Printf("job %s failed: %v", cf.Job.ID, cf.Errors())
	default:
		log.Printf("error: %v", err)
	}
}

Any HTTP error (status ≥ 400) also satisfies api2convert.HTTPError (Status(), RequestID(), Body()).

Webhooks

Verify a signed callback (HMAC-SHA256 over the raw body, delivered in the X-Oc-Signature header):

event, err := api2convert.Webhooks().ConstructEvent(rawBody, signatureHeader, "YOUR_WEBHOOK_SECRET")
if err != nil {
	// invalid signature — reject the request and stop (do not use event)
	return
}
job := event.Job

api2convert.Webhooks() needs no configured client. Pass an empty secret to skip verification, or use Parse for accounts without signed webhooks enabled.

Cloud storage

Read an input straight from your own cloud storage, and/or deliver the output into a bucket (S3, Azure, FTP, Google Cloud — shipped in 10.3.0). Credentials ride in the request body only: they are masked to [REDACTED] in String() and never appear in an error or a log line.

// Input from S3 — a per-provider constructor carries the exact keys the API
// expects (flat, lowercase). The result downloads locally as usual.
res, err := client.Convert(ctx,
	api2convert.CloudInputAmazonS3("my-bucket", "in/photo.png", "AKIA…", "…"), "jpg")
res.Save(ctx, "photo.jpg")

// Output to S3 — attach a generic OutputTarget. When any target is set the
// conversion delivers straight to your storage and produces no local output, so
// Convert returns the completed job without downloading.
res, err = client.Convert(ctx, "photo.png", "jpg",
	api2convert.WithOutputTarget(api2convert.OutputTargetOf(
		api2convert.CloudProviderAmazonS3,
		map[string]any{"bucket": "my-bucket", "file": "out/photo.jpg"},
		map[string]any{"accesskeyid": "AKIA…", "secretaccesskey": "…"},
	)))
delivered := res.Job.Conversion[0].OutputTargets[0].Status // waiting|uploading|completed|failed
_ = delivered

Azure, FTP and Google Cloud have matching input constructors (CloudInputAzure, CloudInputFTP, CloudInputGoogleCloud); output always uses the generic OutputTargetOf. Pass several targets at once with WithOutputTargets.

Full lifecycle control

Convert is built on the resources, which you can use directly for compound jobs, presets, custom polling or job chaining:

job, _ := client.Jobs().Create(ctx, map[string]any{
	"conversion": []any{map[string]any{"target": "pdf"}},
	"process":    false,
})
_, _ = client.Jobs().Upload(ctx, *job, "invoice.docx")
_, _ = client.Jobs().Start(ctx, job.ID)
done, _ := client.Jobs().Wait(ctx, job.ID, 0, true) // 0 = default poll timeout
outputs := done.Output
_ = outputs

Also available: client.Conversions(), client.Presets(), client.Stats(), client.Contracts(), and client.Options(ctx, target, category...) to discover a target's options.

Configuration

client, _ := api2convert.New("KEY",
	api2convert.WithBaseURL("https://api.api2convert.com/v2"),
	api2convert.WithTimeout(30*time.Second),
	api2convert.WithMaxRetries(2),
	api2convert.WithPollInterval(1*time.Second),
	api2convert.WithPollMaxInterval(5*time.Second),
	api2convert.WithPollTimeout(300*time.Second),
	api2convert.WithMaxDownloadBytes(0), // 0 = unlimited (Go-only hardening)
)

Testing

make test           # offline unit tests + the hermetic security suite (no key)
make test-security  # the independent security suite, run in isolation
make test-live      # live conformance — requires API2CONVERT_API_KEY
make check          # fmt + vet + test + test-security
Running live tests

The live suite hits the real API and consumes quota. It is gated by the live build tag and skips unless API2CONVERT_API_KEY is set. Never commit a key — supply it at run time:

API2CONVERT_API_KEY=<your key> make test-live
# optionally target another environment:
API2CONVERT_API_KEY=<key> API2CONVERT_BASE_URL=https://api.api2convert.com/v2 make test-live

The live conformance suite doubles as an executable, end-to-end tour of the SDK: one test per documented guide, plus two negative tests (an unknown target is a typed validation/conversion error; a bad key is a typed auth error that never leaks the credential). It runs automatically against the real API on every release tag (see .github/workflows/live-conformance.yml), so a published version is always verified end to end.

Each test mirrors a runnable single-purpose program in examples/. Every example reads the key from API2CONVERT_API_KEY (and honors API2CONVERT_BASE_URL); run one with go run ./examples/<name>:

Example Guide What it does
quickstart Quickstart Convert a remote JPG → PNG, re-fetch the job, download
convert-files Convert Files Browse the conversions catalog (all + filtered), then convert
uploading-files Uploading Files One-call upload + convert of a local file
job-lifecycle Job Lifecycle Manual create → add input → start → wait → outputs
add-watermark Add a Watermark Stamp a PDF with an image overlay (two inputs)
create-thumbnails Create Thumbnails Render a PDF page to a PNG thumbnail
compress-files Compress Files Shrink a JPG with the compress operation
create-archives Create Archives Bundle two remote files into a ZIP
create-hashes Create Hashes Compute a SHA-256 digest of a file
extract-assets Extract Assets Pull embedded assets out of a document
file-analysis File Analysis Extract file metadata as JSON
compare-files Compare Files Diff two images with the compare-image operation
capture-website Capture a Website Screenshot a URL with the screenshot engine
audio-operations Audio Operations Transcode WAV → AAC with explicit options
image-operations Image Operations Resize a JPG with the resize-image operation
webhooks Webhooks Async convert with a callback + verify the signed callback
presets Presets List saved conversion presets
statistics Statistics Fetch monthly usage figures
rate-limits Rate Limits Inspect the account's contracts (quota/limits)
authentication Authentication Prove the key works via an authenticated jobs list

License

MIT © Qaamgo Media GmbH

Documentation

Overview

Package api2convert is the official Go SDK for the API2Convert file-conversion API — convert, compress and transform files with one call.

Quick start:

client, err := api2convert.New("YOUR_API_KEY")
if err != nil {
	log.Fatal(err)
}
res, err := client.Convert(ctx, "invoice.docx", "pdf")
if err != nil {
	log.Fatal(err)
}
if _, err := res.Save(ctx, "invoice.pdf"); err != nil {
	log.Fatal(err)
}

The API key falls back to the API2CONVERT_API_KEY environment variable when the empty string is passed. Convert hides the multi-step job lifecycle (create -> upload -> start -> poll -> download); for full control use client.Jobs() and the other resources.

Index

Constants

View Source
const (
	// DefaultBaseURL is the default API base URL (includes the /v2 path segment).
	DefaultBaseURL = "https://api.api2convert.com/v2"
	// MinPollInterval is the hard floor for the job-poll interval; prevents a
	// busy-spin self-DDOS.
	MinPollInterval = 500 * time.Millisecond
	// MaxPollTimeout is the hard ceiling for the total job-poll timeout (4 hours);
	// bounds an unbounded poll.
	MaxPollTimeout = 14400 * time.Second
)

Public configuration constants.

View Source
const Version = "10.4.0"

Version is the SDK version, kept in lockstep with the PHP/Python/Java/Node.js SDKs.

Variables

This section is empty.

Functions

func IsTerminalCode

func IsTerminalCode(code string) bool

IsTerminalCode reports whether a raw status code is terminal (completed, failed or canceled). Unknown codes are treated as non-terminal.

Types

type APIError

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

APIError is an HTTP error response (status >= 400) with no more specific type — a 4xx the SDK does not map to a dedicated class.

func (*APIError) Body

func (e *APIError) Body() map[string]any

func (*APIError) RequestID

func (e *APIError) RequestID() string

func (*APIError) Status

func (e *APIError) Status() int

type Api2ConvertError

type Api2ConvertError interface {
	error
	// contains filtered or unexported methods
}

Api2ConvertError is satisfied by every error the SDK returns. Use it as the broadest catch.

type AuthenticationError

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

AuthenticationError means the API key is missing, invalid or not permitted (HTTP 401 / 403).

func (*AuthenticationError) Body

func (e *AuthenticationError) Body() map[string]any

func (*AuthenticationError) RequestID

func (e *AuthenticationError) RequestID() string

func (*AuthenticationError) Status

func (e *AuthenticationError) Status() int

type Client

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

Client is the API2Convert client. Construct it with New. A Client is safe for concurrent use by multiple goroutines: its configuration is set once in New and never mutated, and the default HTTP sender and jitter source are themselves goroutine-safe. (If you inject a Rand via WithRand, it must also be safe for concurrent use.)

func New

func New(apiKey string, opts ...Option) (*Client, error)

New builds a client. apiKey falls back to the API2CONVERT_API_KEY environment variable when empty; New returns a *ConfigError if neither yields a key.

func (*Client) Contracts

func (c *Client) Contracts() *ContractsResource

Contracts returns the contracts resource.

func (*Client) Conversions

func (c *Client) Conversions() *ConversionsResource

Conversions returns the conversions catalog resource.

func (*Client) Convert

func (c *Client) Convert(ctx context.Context, input any, to string, opts ...ConvertOption) (*ConversionResult, error)

Convert converts a file and waits for the result.

input is a local file path, a public URL (^https?://), in-memory []byte, or an io.Reader. Name the target format in to, then Save the returned result. Extra controls (conversion options, category, download password, output index, poll timeout) are supplied via ConvertOption values (the With* functions).

func (*Client) ConvertAsync

func (c *Client) ConvertAsync(ctx context.Context, input any, to string, opts ...ConvertOption) (*Job, error)

ConvertAsync starts a conversion without waiting. Pass WithCallback to be notified (sets notify_status), or poll later with client.Jobs().Get / client.Jobs().Wait.

func (*Client) Download

func (c *Client) Download(output OutputFile, downloadPassword ...string) *FileDownload

Download returns a FileDownload for an output file. A downloadPassword is remembered and sent automatically on download (overridable per call). No I/O happens until Save / Contents is called.

func (*Client) Jobs

func (c *Client) Jobs() *JobsResource

Jobs returns the jobs resource (full lifecycle control).

func (*Client) Options

func (c *Client) Options(ctx context.Context, target string, category ...string) (map[string]any, error)

Options discovers the valid options (type / enum / default / range) for a target. An optional category disambiguates an ambiguous target.

func (*Client) Presets

func (c *Client) Presets() *PresetsResource

Presets returns the presets resource.

func (*Client) Stats

func (c *Client) Stats() *StatsResource

Stats returns the usage-statistics resource.

type CloudInput added in v10.3.0

type CloudInput struct {
	// Source is the provider string (a CloudProvider value, kept as a raw string).
	Source string
	// Parameters are non-secret locator keys (bucket, file, host, …).
	Parameters map[string]any
	// Credentials are secret keys (access keys, passwords, tokens).
	Credentials map[string]any
}

CloudInput is a cloud-storage input descriptor: { type:"cloud", source:<provider>, parameters, credentials }.

Hand it to Client.Convert / Client.ConvertAsync as the input, or to Client.Jobs().AddInput(ctx, jobID, in.Descriptor()); either way it emits the wire descriptor via Descriptor(). Like a remote URL, a cloud input is a started job (process:true), not a staged upload.

The per-provider constructors carry each provider's required keys verbatim — flat and lowercase, exactly as the API expects (accesskeyid, not access_key_id). Those required keys are constructor arguments (structural correctness), not a runtime gate: the builder never rejects a descriptor the permissive, asynchronously-validating server would accept. Optional and forward-compat keys go through the generic CloudInputOf escape hatch.

Google Drive input uses the gdrive_picker input type (the generic AddInput raw-map path this wave); gdrive/youtube are output-only.

credentials ride in the plaintext body, so String() masks the whole credentials object to [REDACTED] and any sensitive parameters leaf.

func CloudInputAmazonS3 added in v10.3.0

func CloudInputAmazonS3(bucket, file, accesskeyid, secretaccesskey string) CloudInput

CloudInputAmazonS3 imports from Amazon S3.

func CloudInputAzure added in v10.3.0

func CloudInputAzure(container, file, accountname, accountkey string) CloudInput

CloudInputAzure imports from Azure Blob Storage.

func CloudInputFTP added in v10.3.0

func CloudInputFTP(host, file, username, password string) CloudInput

CloudInputFTP imports from an FTP server.

func CloudInputGoogleCloud added in v10.3.0

func CloudInputGoogleCloud(projectid, bucket, file, keyfile string) CloudInput

CloudInputGoogleCloud imports from Google Cloud Storage.

func CloudInputOf added in v10.3.0

func CloudInputOf(source CloudProvider, parameters, credentials map[string]any) CloudInput

CloudInputOf is the generic escape hatch: any provider (a typed CloudProvider or a forward-compat CloudProvider("...") value) with free-form maps.

func (CloudInput) Descriptor added in v10.3.0

func (c CloudInput) Descriptor() map[string]any

Descriptor is the wire descriptor sent to POST /jobs (inline input) or POST /jobs/{id}/input. Nil maps normalize to empty objects so the payload keys are always present.

func (CloudInput) String added in v10.3.0

func (c CloudInput) String() string

String is a human-readable form with credentials masked — safe to log. The whole credentials object renders as [REDACTED]; sensitive parameters leaves are masked too.

type CloudProvider added in v10.3.0

type CloudProvider string

CloudProvider is the vocabulary of cloud storage providers the API can import inputs from and deliver outputs to — the value of a cloud descriptor's "source" (input) or "type" (output) field.

It is build-side vocabulary only: it types the CloudInput builder and OutputTarget serialization. Read models keep source/type/status as raw strings, so an unknown provider string returned by the server round-trips untyped and never fails to hydrate. Pass a CloudProvider("...") conversion for a forward-compat provider the constants do not yet name.

Import support (a CloudInput constructor) exists for CloudProviderAmazonS3, CloudProviderAzure, CloudProviderFtp and CloudProviderGoogleCloud. CloudProviderGdrive and CloudProviderYoutube are output-only (they validate as an output type but have no downloader); Google Drive input uses the separate gdrive_picker input type via the raw AddInput path.

const (
	CloudProviderAmazonS3    CloudProvider = "amazons3"
	CloudProviderAzure       CloudProvider = "azure"
	CloudProviderFtp         CloudProvider = "ftp"
	CloudProviderGdrive      CloudProvider = "gdrive"
	CloudProviderGoogleCloud CloudProvider = "googlecloud"
	CloudProviderYoutube     CloudProvider = "youtube"
)

type ConfigError

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

ConfigError signals a client that was constructed with invalid configuration (for example, no API key). It is returned by New.

func (*ConfigError) Error

func (e *ConfigError) Error() string

func (*ConfigError) Unwrap

func (e *ConfigError) Unwrap() error

type ContractsResource

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

ContractsResource returns information about the account's active contracts (free-form response).

func (*ContractsResource) Get

func (r *ContractsResource) Get(ctx context.Context) (any, error)

Get returns the account's contract information.

type Conversion

type Conversion struct {
	Target        string
	ID            string
	Category      string
	Options       map[string]any
	Metadata      map[string]any
	OutputTargets []OutputTarget
}

Conversion is a single conversion within a job: the target format plus options.

OutputTargets holds any cloud delivery targets attached to this conversion's output (empty for an ordinary downloadable conversion).

func ConversionFromMap

func ConversionFromMap(data map[string]any) Conversion

ConversionFromMap hydrates a Conversion from a decoded JSON object.

type ConversionFailedError

type ConversionFailedError struct {
	Job Job
	// contains filtered or unexported fields
}

ConversionFailedError means a job reached the failed (or canceled) status. The originating Job is attached so you can inspect its Errors and Warnings.

func (*ConversionFailedError) Error

func (e *ConversionFailedError) Error() string

func (*ConversionFailedError) Errors

func (e *ConversionFailedError) Errors() []JobMessage

Errors returns the failed job's errors (may be empty if the API gave no detail).

func (*ConversionFailedError) Unwrap

func (e *ConversionFailedError) Unwrap() error

type ConversionResult

type ConversionResult struct {
	// Job is the completed job.
	Job Job
	// contains filtered or unexported fields
}

ConversionResult is the result of a completed conversion. The common case is one output: result.Save(ctx, "out.pdf"). Jobs that produce several files expose them via Outputs and Download.

func (*ConversionResult) Contents

func (r *ConversionResult) Contents(ctx context.Context, downloadPassword ...string) ([]byte, error)

Contents downloads the selected output and returns its contents.

func (*ConversionResult) Download

func (r *ConversionResult) Download(output ...OutputFile) (*FileDownload, error)

Download returns a FileDownload for a specific output (defaults to the selected one).

func (*ConversionResult) Output

func (r *ConversionResult) Output() (OutputFile, error)

Output returns the selected output file (the first one by default). An index not present — including a negative one — is an error rather than wrapping around.

func (*ConversionResult) Outputs

func (r *ConversionResult) Outputs() []OutputFile

Outputs returns all output files produced by the job.

func (*ConversionResult) Save

func (r *ConversionResult) Save(ctx context.Context, pathOrDir string, downloadPassword ...string) (string, error)

Save downloads the selected output to disk. Returns the path written to.

func (*ConversionResult) URL

func (r *ConversionResult) URL() (string, error)

URL returns the download URL of the selected output (self-contained, no auth).

type ConversionTimeoutError

type ConversionTimeoutError struct {
	Job Job
	// contains filtered or unexported fields
}

ConversionTimeoutError means a job did not reach a terminal status within the configured poll timeout. The job is still running server-side — re-fetch it later with client.Jobs().Get(ctx, job.ID).

func (*ConversionTimeoutError) Error

func (e *ConversionTimeoutError) Error() string

func (*ConversionTimeoutError) Unwrap

func (e *ConversionTimeoutError) Unwrap() error

type ConversionsResource

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

ConversionsResource is the conversions catalog (GET /conversions) — the source of truth for which targets exist and which options each accepts.

func (*ConversionsResource) List

func (r *ConversionsResource) List(ctx context.Context, category, target string, page int) ([]map[string]any, error)

List lists supported conversions, optionally filtered by category/target. Each entry is a map: {id, category, target, options}. An empty category/target is omitted; page <= 0 defaults to 1.

func (*ConversionsResource) Options

func (r *ConversionsResource) Options(ctx context.Context, target string, category ...string) (map[string]any, error)

Options returns the option schema (type / enum / default / range) for a single target. An optional category disambiguates an ambiguous target.

type ConvertOption

type ConvertOption func(*convertParams)

ConvertOption is an extra control for Convert / ConvertAsync. These named controls are kept strictly separate from the open-ended conversion options map (see WithConversionOptions), so open-ended API option keys can never collide with SDK control keys.

func WithCallback

func WithCallback(u string) ConvertOption

WithCallback sets a webhook URL to notify on status change (sets notify_status: true). Applies to ConvertAsync only.

func WithCategory

func WithCategory(c string) ConvertOption

WithCategory disambiguates an ambiguous target format.

func WithConversionOptions

func WithConversionOptions(o map[string]any) ConvertOption

WithConversionOptions sets the target-specific conversion options, passed 1:1 to the API's conversion "options". Discover valid options via Client.Options.

func WithConvertTimeout

func WithConvertTimeout(d time.Duration) ConvertOption

WithConvertTimeout overrides the poll timeout for this conversion. Applies to Convert only (which waits); ConvertAsync does not poll and ignores it.

func WithDownloadPassword

func WithDownloadPassword(pw string) ConvertOption

WithDownloadPassword protects every output; it is remembered on the returned result and sent automatically on download.

func WithFilename

func WithFilename(f string) ConvertOption

WithFilename sets the advertised filename for an uploaded local file / stream.

func WithOutputIndex

func WithOutputIndex(i int) ConvertOption

WithOutputIndex selects which output file the result selects (default 0). Applies to Convert only; ConvertAsync returns the Job (no result to select from) and ignores it.

func WithOutputTarget added in v10.3.0

func WithOutputTarget(target OutputTarget) ConvertOption

WithOutputTarget attaches a cloud delivery target to the conversion's output_target (never merged into the conversion options map). Repeatable — each call appends. When any output target is set the conversion delivers to your storage and produces no local output, so Convert returns the completed job without downloading.

func WithOutputTargets added in v10.3.0

func WithOutputTargets(targets ...OutputTarget) ConvertOption

WithOutputTargets attaches several cloud delivery targets at once (see WithOutputTarget). Appends to any already set.

type FileDownload

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

FileDownload is a downloadable output file. Returned by Client.Download. A download password supplied at construction is remembered and sent automatically on download.

func (*FileDownload) Contents

func (d *FileDownload) Contents(ctx context.Context, downloadPassword ...string) ([]byte, error)

Contents downloads the file and returns its contents (loads into memory).

func (*FileDownload) Save

func (d *FileDownload) Save(ctx context.Context, pathOrDir string, downloadPassword ...string) (string, error)

Save streams the file to disk. pathOrDir is a file path, or a directory (the API filename is used, sanitized to a bare basename). A password set at conversion time is applied automatically; pass one here only to override it. Returns the path written to.

func (*FileDownload) URL

func (d *FileDownload) URL() string

URL returns the self-contained download URL (no auth required).

type HTTPError

type HTTPError interface {
	Api2ConvertError
	Status() int
	RequestID() string
	Body() map[string]any
}

HTTPError is satisfied by every error that originated from an HTTP error response (status >= 400). It exposes the status code, request id and decoded body.

type HttpSender

type HttpSender interface {
	Send(ctx context.Context, req *Request) (*Response, error)
}

HttpSender is the pluggable transport. The default is netHTTPSender; tests inject a fake. Send must respect ctx for cancellation.

type InputFile

type InputFile struct {
	ID          string
	Type        string
	Source      string
	Status      string
	Filename    string
	Size        *int64
	ContentType string
	Options     map[string]any
	Parameters  map[string]any
}

InputFile is an input file attached to a job.

Parameters surfaces a cloud input's non-secret locator keys (bucket, file, host, …); it is empty for ordinary uploaded/remote inputs. Source and Status stay raw strings (an unknown cloud provider round-trips untyped). Cloud credentials are never surfaced (the API returns them empty).

func InputFileFromMap

func InputFileFromMap(data map[string]any) InputFile

InputFileFromMap hydrates an InputFile from a decoded JSON object.

type InputType

type InputType string

InputType enumerates the kinds of source an input file can be created from (the input "type" field). A typed reference for building input descriptors by hand, e.g. AddInput(ctx, jobID, map[string]any{"type": string(InputTypeRemote), "source": "..."}).

const (
	InputTypeUpload       InputType = "upload"
	InputTypeRemote       InputType = "remote"
	InputTypeOutput       InputType = "output"
	InputTypeInputID      InputType = "input_id"
	InputTypeGdrivePicker InputType = "gdrive_picker"
	InputTypeBase64       InputType = "base64"
	InputTypeCloud        InputType = "cloud"
)

type Job

type Job struct {
	ID         string
	Status     Status
	Token      string
	Server     string
	Callback   string
	Conversion []Conversion
	Input      []InputFile
	Output     []OutputFile
	Errors     []JobMessage
	Warnings   []JobMessage
	Raw        map[string]any
}

Job is a conversion job — the central API2Convert resource.

Server and Token are needed to upload local files; Output holds the produced files once the job IsCompleted. Raw keeps the full decoded response for fields not surfaced as typed properties.

Nullable string fields from the API are represented as plain strings where the empty string means "absent"; consult Raw for the exact JSON value if the distinction matters.

func JobFromMap

func JobFromMap(data map[string]any) Job

JobFromMap hydrates a Job from a decoded JSON object. It never panics on a surprising payload; missing or wrong-typed fields fall back to zero values.

func (Job) IsCanceled

func (j Job) IsCanceled() bool

IsCanceled reports whether the job was canceled server-side (terminal, no output).

func (Job) IsCompleted

func (j Job) IsCompleted() bool

IsCompleted reports whether the job finished successfully (status.code == "completed").

func (Job) IsFailed

func (j Job) IsFailed() bool

IsFailed reports whether the job finished unsuccessfully (status.code == "failed").

func (Job) IsTerminal

func (j Job) IsTerminal() bool

IsTerminal reports whether the job finished (completed, failed or canceled) and will not change further.

type JobMessage

type JobMessage struct {
	// Code is int64 to match the wire type: nullableInt64 already decodes past 2^53,
	// and narrowing to int truncated on 32-bit builds for no benefit.
	Code     *int64
	Message  string
	Source   string
	IDSource string
	Details  map[string]any
}

JobMessage is an error or warning attached to a job (the errors[] / warnings[] entries).

func JobMessageFromMap

func JobMessageFromMap(data map[string]any) JobMessage

JobMessageFromMap hydrates a JobMessage from a decoded JSON object.

type JobStatus

type JobStatus string

JobStatus enumerates the well-known job status codes (the status.code field).

The API may introduce further codes; treat any code not listed here as non-terminal. Use IsTerminalCode for a raw status string rather than comparing by hand.

const (
	JobStatusCreated     JobStatus = "created"
	JobStatusIncomplete  JobStatus = "incomplete"
	JobStatusDownloading JobStatus = "downloading"
	JobStatusQueued      JobStatus = "queued"
	JobStatusProcessing  JobStatus = "processing"
	JobStatusCompleted   JobStatus = "completed"
	JobStatusFailed      JobStatus = "failed"
	JobStatusCanceled    JobStatus = "canceled"
)

type JobsResource

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

JobsResource gives full control over the job lifecycle. Most users only need Client.Convert, which is built on these methods. Methods are thin: build the request, call the transport, hydrate a model.

func (*JobsResource) AddInput

func (r *JobsResource) AddInput(ctx context.Context, jobID string, descriptor map[string]any) (*InputFile, error)

AddInput attaches an input by descriptor, e.g. a remote URL: AddInput(ctx, jobID, map[string]any{"type": "remote", "source": "https://..."}).

func (*JobsResource) Cancel

func (r *JobsResource) Cancel(ctx context.Context, jobID string) error

Cancel cancels a job (whether staged or processing).

func (*JobsResource) Create

func (r *JobsResource) Create(ctx context.Context, payload map[string]any, idempotencyKey ...string) (*Job, error)

Create creates a job. Pass {"process": false} to stage it for uploads, then Start it once inputs are attached. An optional idempotencyKey makes the create retry-safe (sent as the Idempotency-Key header).

func (*JobsResource) Get

func (r *JobsResource) Get(ctx context.Context, jobID string) (*Job, error)

Get fetches a job by id.

func (*JobsResource) List

func (r *JobsResource) List(ctx context.Context, status string, page int) ([]Job, error)

List lists the current key's jobs (paginated, 50 per page). An empty status lists all; page <= 0 defaults to 1.

func (*JobsResource) Outputs

func (r *JobsResource) Outputs(ctx context.Context, jobID string) ([]OutputFile, error)

Outputs returns the outputs produced by the job (use Get or Wait first).

func (*JobsResource) Start

func (r *JobsResource) Start(ctx context.Context, jobID string) (*Job, error)

Start begins processing a staged job (process: true).

func (*JobsResource) Update

func (r *JobsResource) Update(ctx context.Context, jobID string, payload map[string]any) (*Job, error)

Update patches a job (e.g. {"process": true} to start it).

func (*JobsResource) Upload

func (r *JobsResource) Upload(ctx context.Context, job Job, file any, filename ...string) (*InputFile, error)

Upload uploads a local file (path string, []byte or io.Reader) to the job's upload server. An optional filename overrides the advertised name.

func (*JobsResource) Wait

func (r *JobsResource) Wait(ctx context.Context, jobID string, timeout time.Duration, throwOnFailure bool) (*Job, error)

Wait polls with backoff until the job reaches a terminal status. It returns a *ConversionFailedError on a failed/canceled job (unless throwOnFailure is false) and a *ConversionTimeoutError past the deadline. A timeout <= 0 uses the configured default. The interval is floored and the total wait capped, so no configuration can busy-loop or poll unbounded.

type NetworkError

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

NetworkError means a request did not yield a usable response: a transport-level failure (DNS/connection/TLS/read) once idempotent retries are exhausted, a 2xx whose body is not valid JSON, or a malformed API-supplied URL.

func (*NetworkError) Error

func (e *NetworkError) Error() string

func (*NetworkError) Unwrap

func (e *NetworkError) Unwrap() error

type NotFoundError

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

NotFoundError means the requested resource does not exist (HTTP 404).

func (*NotFoundError) Body

func (e *NotFoundError) Body() map[string]any

func (*NotFoundError) RequestID

func (e *NotFoundError) RequestID() string

func (*NotFoundError) Status

func (e *NotFoundError) Status() int

type Option

type Option func(*clientBuilder)

Option configures the client at construction. Pass Options to New.

func WithBaseURL

func WithBaseURL(u string) Option

WithBaseURL sets the API base URL (default https://api.api2convert.com/v2).

func WithHTTPSender

func WithHTTPSender(s HttpSender) Option

WithHTTPSender brings your own HTTP transport (defaults to a net/http sender). Primarily a test seam.

func WithMaxDownloadBytes

func WithMaxDownloadBytes(n int64) Option

WithMaxDownloadBytes caps the size of a downloaded file; a larger response yields a NetworkError instead of an unbounded read. 0 (the default) means unlimited. This is an additive Go-only hardening beyond the shared contract.

func WithMaxRetries

func WithMaxRetries(n int) Option

WithMaxRetries sets the number of automatic retries for transient failures (429 / 5xx / network) (default 2, min 0).

func WithPollInterval

func WithPollInterval(d time.Duration) Option

WithPollInterval sets the first poll interval when waiting for a job (default 1s, floored to 500ms).

func WithPollMaxInterval

func WithPollMaxInterval(d time.Duration) Option

WithPollMaxInterval sets the upper bound the poll interval backs off to (default 5s).

func WithPollTimeout

func WithPollTimeout(d time.Duration) Option

WithPollTimeout sets how long to wait for a job before giving up (default 300s, capped at 14400s).

func WithRand

func WithRand(r Rand) Option

WithRand injects a [0,1) random source for backoff jitter (handy in tests).

func WithSleeper

func WithSleeper(s Sleeper) Option

WithSleeper injects the delay function used by retry/poll backoff (handy in tests).

func WithTimeout

func WithTimeout(d time.Duration) Option

WithTimeout sets the per-request network timeout (default 30s, min 1s).

type OutputFile

type OutputFile struct {
	ID          string
	URI         string
	Filename    string
	Size        *int64
	Status      string
	ContentType string
	Checksum    string
	Metadata    map[string]any
}

OutputFile is a produced output file. URI is a self-contained download URL (no auth required), valid for a limited time (24h by default).

func OutputFileFromMap

func OutputFileFromMap(data map[string]any) OutputFile

OutputFileFromMap hydrates an OutputFile from a decoded JSON object.

func OutputFileOf

func OutputFileOf(id, uri, filename string) OutputFile

OutputFileOf constructs an OutputFile from its essentials (mirrors the siblings' OutputFile.of).

type OutputTarget added in v10.3.0

type OutputTarget struct {
	// Type is the provider string (a CloudProvider value, kept as a raw string).
	Type string
	// Parameters are delivery locator keys (provider-specific).
	Parameters map[string]any
	// Credentials are secret keys (never surfaced on read).
	Credentials map[string]any
	// Status is the server-set delivery status on read
	// (waiting|uploading|completed|failed); never sent on create (empty means absent).
	Status string
}

OutputTarget is a cloud-storage delivery target for a conversion's output: { type:<provider>, parameters, credentials }.

Attach one (or more) to a conversion via Client.Convert / Client.ConvertAsync (the WithOutputTarget / WithOutputTargets controls), or inline in a raw Jobs().Create conversion map. When any output target is set the conversion delivers straight to your storage and produces no local output — so Convert returns the completed job without downloading.

This wave ships the generic shape only (type + free-form parameters/ credentials); the per-provider output keys live in a separate service and diverge per provider, so there are no per-provider output factories yet.

Descriptor emits { type, parameters, credentials } and omits status (server-set, read-only). On read (OutputTargetFromMap) type, parameters and status round-trip as raw values; credentials are never surfaced (the API returns them empty). credentials ride in the plaintext body, so String() masks the whole object to [REDACTED].

func OutputTargetFromMap added in v10.3.0

func OutputTargetFromMap(data map[string]any) OutputTarget

OutputTargetFromMap hydrates from a GET /jobs/{id} output_target[] element. type/status stay raw strings (an unknown provider round-trips untyped); credentials are deliberately not surfaced.

func OutputTargetOf added in v10.3.0

func OutputTargetOf(targetType CloudProvider, parameters, credentials map[string]any) OutputTarget

OutputTargetOf builds a generic output target for a typed provider or a forward-compat CloudProvider("...") value. status is server-set and left empty.

func (OutputTarget) Descriptor added in v10.3.0

func (o OutputTarget) Descriptor() map[string]any

Descriptor is the wire descriptor sent on create — { type, parameters, credentials } — with status omitted (server-set, read-only). Nil maps normalize to empty objects.

func (OutputTarget) String added in v10.3.0

func (o OutputTarget) String() string

String is a human-readable form with credentials masked — safe to log.

type PaymentRequiredError

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

PaymentRequiredError means the account has no remaining quota/credit (HTTP 402).

func (*PaymentRequiredError) Body

func (e *PaymentRequiredError) Body() map[string]any

func (*PaymentRequiredError) RequestID

func (e *PaymentRequiredError) RequestID() string

func (*PaymentRequiredError) Status

func (e *PaymentRequiredError) Status() int

type Preset

type Preset struct {
	ID       string
	Name     string
	Target   string
	Category string
	Scope    string
	Options  map[string]any
}

Preset is a saved conversion preset (a reusable named target + options).

func PresetFromMap

func PresetFromMap(data map[string]any) Preset

PresetFromMap hydrates a Preset from a decoded JSON object.

type PresetsResource

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

PresetsResource manages saved conversion presets (reusable named target + options).

func (*PresetsResource) Create

func (r *PresetsResource) Create(ctx context.Context, payload map[string]any) (*Preset, error)

Create creates a preset from {name, target, options, scope?, category?}.

func (*PresetsResource) Delete

func (r *PresetsResource) Delete(ctx context.Context, presetID string) error

Delete deletes a preset.

func (*PresetsResource) Get

func (r *PresetsResource) Get(ctx context.Context, presetID string) (*Preset, error)

Get fetches a preset by id.

func (*PresetsResource) List

func (r *PresetsResource) List(ctx context.Context, category, target, filter string) ([]Preset, error)

List lists presets, optionally filtered by category / target / filter (empty values are omitted).

func (*PresetsResource) Update

func (r *PresetsResource) Update(ctx context.Context, presetID string, payload map[string]any) (*Preset, error)

Update patches a preset.

type Rand

type Rand func() float64

Rand returns a [0,1) float for backoff jitter. Injectable for deterministic tests.

type RateLimitError

type RateLimitError struct {

	// RetryAfter is the seconds to wait before retrying, parsed from the
	// Retry-After header (raw, uncapped); nil when the header was absent.
	RetryAfter *int
	// contains filtered or unexported fields
}

RateLimitError means too many requests (HTTP 429); returned only once auto-retries are exhausted.

func (*RateLimitError) Body

func (e *RateLimitError) Body() map[string]any

func (*RateLimitError) RequestID

func (e *RateLimitError) RequestID() string

func (*RateLimitError) Status

func (e *RateLimitError) Status() int

type Request

type Request struct {
	Method  string
	URL     string
	Headers map[string]string

	// Body is a materialized, replayable body (e.g. JSON bytes). Ignored when
	// MakeBody is set.
	Body []byte

	// MakeBody produces a fresh body reader per attempt (for streamed / multipart
	// requests) so a replay re-creates it. Takes precedence over Body. May be nil.
	// If the returned reader is an io.Closer it is closed after the body is sent.
	MakeBody func() (io.Reader, error)

	// FollowRedirects: only a no-secret download opts in. Any request carrying an
	// X-Api2convert-* secret header must keep this false so a redirect cannot forward the
	// secret to another host.
	FollowRedirects bool

	// Replayable reports whether the body can be re-sent on a retry (false for
	// one-shot streams).
	Replayable bool

	// Timeout is the per-request network timeout. For a non-streamed (JSON
	// control-plane) request it is a whole-exchange deadline. For a streamed
	// request (Stream == true) it bounds only the pre-body phase (see Stream).
	Timeout time.Duration

	// Stream marks a request whose body is a large, possibly slow transfer (a file
	// download response or an upload request body). For such a request Timeout must
	// bound only the pre-body phase — connection, TLS handshake and waiting for the
	// response headers — never the body transfer itself, which is governed solely
	// by the caller's context. A whole-exchange deadline here would fail a healthy
	// large transfer purely because it took longer than the timeout.
	Stream bool
}

Request is a transport-agnostic HTTP request.

type Response

type Response struct {
	Status     int
	StatusText string
	Header     http.Header
	Body       io.ReadCloser
}

Response is a transport-agnostic HTTP response. Body is a single-use stream the caller must close.

func (*Response) HeaderGet

func (r *Response) HeaderGet(name string) string

HeaderGet returns the named response header (case-insensitive), or "".

type ServerError

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

ServerError is a server-side error (HTTP >= 500), returned once auto-retries are exhausted.

func (*ServerError) Body

func (e *ServerError) Body() map[string]any

func (*ServerError) RequestID

func (e *ServerError) RequestID() string

func (*ServerError) Status

func (e *ServerError) Status() int

type SignatureVerificationError

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

SignatureVerificationError means a webhook payload could not be verified against the provided signature/secret. Treat it as a security event: do not trust the payload.

func (*SignatureVerificationError) Error

func (e *SignatureVerificationError) Error() string

func (*SignatureVerificationError) Unwrap

func (e *SignatureVerificationError) Unwrap() error

type Sleeper

type Sleeper func(ctx context.Context, d time.Duration) error

Sleeper delays for d, returning early with ctx.Err() if ctx is canceled. Injectable; the real implementation uses a timer.

type StatsResource

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

StatsResource returns API usage statistics. The response shape is free-form (returned as-is). filter is "single" (only the calling API key) or "all" (every key on the account, the default); the spec enum is {"single","all"}. The request is scoped by the X-Api2convert-Api-Key header, so a key is never placed in the URL — do not pass a key as filter.

func (*StatsResource) Day

func (r *StatsResource) Day(ctx context.Context, day, filter string) (any, error)

Day returns usage for a day (format yyyy-mm-dd). filter is "single" or "all".

func (*StatsResource) Month

func (r *StatsResource) Month(ctx context.Context, month, filter string) (any, error)

Month returns usage for a month (format yyyy-mm). filter is "single" or "all".

func (*StatsResource) Year

func (r *StatsResource) Year(ctx context.Context, year, filter string) (any, error)

Year returns usage for a year (format yyyy). filter is "single" or "all".

type Status

type Status struct {
	Code string
	Info string
}

Status is a job's status: a machine-readable Code plus optional human Info.

func StatusFromMap

func StatusFromMap(data map[string]any) Status

StatusFromMap hydrates a Status from a decoded JSON object.

type ValidationError

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

ValidationError means the request was rejected as invalid, e.g. an unknown target (HTTP 400 / 422).

func (*ValidationError) Body

func (e *ValidationError) Body() map[string]any

func (*ValidationError) RequestID

func (e *ValidationError) RequestID() string

func (*ValidationError) Status

func (e *ValidationError) Status() int

type WebhookEvent

type WebhookEvent struct {
	// Job is the job whose status changed.
	Job Job
	// Payload is the full decoded callback body.
	Payload map[string]any
}

WebhookEvent is a verified webhook callback. The API posts the job whose status changed.

type WebhookVerifier

type WebhookVerifier struct{}

WebhookVerifier verifies and parses webhook callbacks. Obtain one via api2convert.Webhooks(); it needs no configured client.

func Webhooks

func Webhooks() *WebhookVerifier

Webhooks returns a webhook verifier — usable without a configured client.

func (WebhookVerifier) ConstructEvent

func (WebhookVerifier) ConstructEvent(payload []byte, signature, secret string) (*WebhookEvent, error)

ConstructEvent verifies the signature (when a secret is given) and returns the typed event.

payload must be the raw request body. signature is the value of the signature header (X-Oc-Signature). Pass an empty secret to skip verification. Returns a *SignatureVerificationError when the signature is missing or does not match (constant-time comparison via hmac.Equal).

func (WebhookVerifier) Parse

func (WebhookVerifier) Parse(payload []byte) (*WebhookEvent, error)

Parse parses a callback body into a typed event WITHOUT verifying a signature. Only use this when signed webhooks are not yet enabled for your account.

Directories

Path Synopsis
examples
add-watermark command
Command addwatermark mirrors the "Add a Watermark" guide: stamp a PDF with an image overlay by giving the job two remote inputs (the document and the stamp).
Command addwatermark mirrors the "Add a Watermark" guide: stamp a PDF with an image overlay by giving the job two remote inputs (the document and the stamp).
audio-operations command
Command audiooperations mirrors the "Audio Operations" guide: transcode audio to AAC with explicit codec, bitrate, channel and frequency options.
Command audiooperations mirrors the "Audio Operations" guide: transcode audio to AAC with explicit codec, bitrate, channel and frequency options.
authentication command
Command authentication mirrors the "Authentication" guide: prove the API key works by making an authenticated call — list the account's jobs.
Command authentication mirrors the "Authentication" guide: prove the API key works by making an authenticated call — list the account's jobs.
capture-website command
Command capturewebsite mirrors the "Capture a Website" guide: screenshot a URL by giving the job a remote input with the "screenshot" engine.
Command capturewebsite mirrors the "Capture a Website" guide: screenshot a URL by giving the job a remote input with the "screenshot" engine.
compare-files command
Command comparefiles mirrors the "Compare Files" guide: diff two images with the "compare-image" operation and produce a visual difference map.
Command comparefiles mirrors the "Compare Files" guide: diff two images with the "compare-image" operation and produce a visual difference map.
compress-files command
Command compressfiles mirrors the "Compress Files" guide: shrink a file with the "compress" operation.
Command compressfiles mirrors the "Compress Files" guide: shrink a file with the "compress" operation.
convert-files command
Command convertfiles mirrors the "Convert Files" guide: browse the conversions catalog (all, then filtered to a target), then run a conversion.
Command convertfiles mirrors the "Convert Files" guide: browse the conversions catalog (all, then filtered to a target), then run a conversion.
create-archives command
Command createarchives mirrors the "Create Archives" guide: bundle several remote files into a single ZIP archive.
Command createarchives mirrors the "Create Archives" guide: bundle several remote files into a single ZIP archive.
create-hashes command
Command createhashes mirrors the "Create Hashes" guide: compute a SHA-256 digest of a file via the "sha256" hash target.
Command createhashes mirrors the "Create Hashes" guide: compute a SHA-256 digest of a file via the "sha256" hash target.
create-thumbnails command
Command createthumbnails mirrors the "Create Thumbnails" guide: render a preview image of a document page via the "thumbnail" operation.
Command createthumbnails mirrors the "Create Thumbnails" guide: render a preview image of a document page via the "thumbnail" operation.
extract-assets command
Command extractassets mirrors the "Extract Assets" guide: pull the embedded assets (images, media, ...) out of a document via the "extract-assets" operation.
Command extractassets mirrors the "Extract Assets" guide: pull the embedded assets (images, media, ...) out of a document via the "extract-assets" operation.
file-analysis command
Command fileanalysis mirrors the "File Analysis" guide: extract a file's metadata as JSON via the "json" metadata target.
Command fileanalysis mirrors the "File Analysis" guide: extract a file's metadata as JSON via the "json" metadata target.
image-operations command
Command imageoperations mirrors the "Image Operations" guide: resize an image with the "resize-image" operation, keeping the aspect ratio via a crop.
Command imageoperations mirrors the "Image Operations" guide: resize an image with the "resize-image" operation, keeping the aspect ratio via a crop.
job-lifecycle command
Command joblifecycle mirrors the "Job Lifecycle" guide: drive the steps by hand — create a staged job, attach a remote input, start it, wait, list outputs.
Command joblifecycle mirrors the "Job Lifecycle" guide: drive the steps by hand — create a staged job, attach a remote input, start it, wait, list outputs.
presets command
Command presets mirrors the "Presets" guide: list saved conversion presets, optionally filtered by category and target.
Command presets mirrors the "Presets" guide: list saved conversion presets, optionally filtered by category and target.
quickstart command
Command quickstart mirrors the "Quickstart" guide: convert a remote JPG to PNG, fetch the finished job by id, then download the output.
Command quickstart mirrors the "Quickstart" guide: convert a remote JPG to PNG, fetch the finished job by id, then download the output.
rate-limits command
Command ratelimits mirrors the "Rate Limits" guide: inspect the account's active contracts (which govern quota and rate limits) via the contracts resource.
Command ratelimits mirrors the "Rate Limits" guide: inspect the account's active contracts (which govern quota and rate limits) via the contracts resource.
statistics command
Command statistics mirrors the "Statistics" guide: fetch usage figures for a month via the stats resource.
Command statistics mirrors the "Statistics" guide: fetch usage figures for a month via the stats resource.
uploading-files command
Command uploadingfiles mirrors the "Uploading Files" guide: convert a LOCAL file in one call — the SDK stages the job, streams the upload, starts and polls it.
Command uploadingfiles mirrors the "Uploading Files" guide: convert a LOCAL file in one call — the SDK stages the job, streams the upload, starts and polls it.
webhooks command
Command webhooks mirrors the "Webhooks" guide.
Command webhooks mirrors the "Webhooks" guide.
internal
testutil
Package testutil provides shared test helpers for the api2convert SDK: an injectable fake HTTP sender, a recording sleeper, and real loopback servers for the security suite.
Package testutil provides shared test helpers for the api2convert SDK: an injectable fake HTTP sender, a recording sleeper, and real loopback servers for the security suite.

Jump to

Keyboard shortcuts

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