Api2Convert 10.3.1
dotnet add package Api2Convert --version 10.3.1
NuGet\Install-Package Api2Convert -Version 10.3.1
<PackageReference Include="Api2Convert" Version="10.3.1" />
<PackageVersion Include="Api2Convert" Version="10.3.1" />
<PackageReference Include="Api2Convert" />
paket add Api2Convert --version 10.3.1
#r "nuget: Api2Convert, 10.3.1"
#:package Api2Convert@10.3.1
#addin nuget:?package=Api2Convert&version=10.3.1
#tool nuget:?package=Api2Convert&version=10.3.1
API2Convert .NET SDK
Official .NET / C# SDK for the API2Convert file-conversion API. Convert, compress and transform images, documents, audio, video, ebooks, archives and CAD with one line of code.
- One-call conversions —
ConvertAsync(input, to)hides the create → upload → poll → download lifecycle for local files, URLs and streams. - Async-first — every I/O method returns a
Taskand takes aCancellationToken. - Typed errors —
AuthenticationException,ValidationException,RateLimitException,ConversionFailedException, … all under oneApi2ConvertExceptionbase. - Secure by default — secrets never appear in logs, URLs or exceptions, and a request carrying a secret never follows an HTTP redirect. See SECURITY.md.
- Zero third-party runtime dependencies —
HttpClient,System.Text.JsonandSystem.Security.Cryptographyonly.
Targets .NET 8.
Install
dotnet add package Api2Convert
Quick start
using Api2Convert;
using var client = new Api2ConvertClient("YOUR_API_KEY"); // or set API2CONVERT_API_KEY
// Convert a local file and save the result.
var result = await client.ConvertAsync("invoice.docx", "pdf");
string path = await result.SaveAsync("invoice.pdf");
// Convert a public URL and read the bytes into memory.
var png = await client.ConvertAsync("https://example.com/photo.jpg", "png");
byte[] bytes = await png.ContentsAsync();
The API key is read from the constructor argument, or falls back to the API2CONVERT_API_KEY
environment variable.
Conversion options
Discover the valid options for a target, then pass them to ConvertAsync:
IReadOnlyDictionary<string, object?> schema = await client.OptionsAsync("jpg");
var result = await client.ConvertAsync(
"photo.png",
"jpg",
new Dictionary<string, object?> { ["quality"] = 80, ["strip"] = true });
Less-common controls live on ConvertOptions, kept separate from the open-ended options map so they
can never collide with an API option key:
var result = await client.ConvertAsync(
"scan.tiff",
"pdf",
options: null,
opts: new ConvertOptions { Category = "document", DownloadPassword = "hunter2", Timeout = 600 });
A download password supplied at conversion time is remembered on the result and sent
automatically (as X-Api2convert-Download-Password) on every download from it.
Async (webhook-driven) conversions
StartConversionAsync starts a job and returns immediately without polling. Pass a callback URL to be
notified when it finishes (this is the contract's convertAsync, renamed so the Async suffix keeps
its .NET "returns a Task" meaning):
var job = await client.StartConversionAsync(
"https://example.com/big.mov",
"mp4",
opts: new AsyncOptions { Callback = "https://app.example.com/hooks/a2c" });
// later — poll it yourself, or handle the webhook (below)
var done = await client.Jobs.WaitAsync(job.Id);
Verifying webhooks
Point a job's callback at your endpoint, then verify the raw request body against your signing secret before trusting it:
using Api2Convert;
using Api2Convert.Exceptions;
// framework-agnostic; wire rawBody / signatureHeader to your web request
try
{
var evt = Api2ConvertClient.Webhooks().ConstructEvent(rawBody, signatureHeader, secret);
if (evt.Job.IsCompleted)
{
foreach (var output in evt.Job.Output)
{
// e.g. enqueue a download of output.Uri
}
}
}
catch (SignatureVerificationException)
{
// respond 400 Bad Request — do not trust the payload
}
Verification is HMAC-SHA256 over the raw body with a constant-time comparison. An empty secret
deliberately skips verification (use Webhooks().Parse(rawBody) when signed webhooks are not enabled
on your account yet).
Cloud storage
Read an input straight from customer-owned storage (S3, Azure Blob, FTP, Google Cloud), deliver the
converted output into a bucket, or both. Build a cloud input with a per-provider factory whose
arguments carry each provider's required keys verbatim (flat/lowercase, exactly as the API expects) and
hand it to ConvertAsync like any other input:
using Api2Convert.Models;
// Import from S3 — the API fetches the object itself (like a URL: a single started job).
var input = CloudInput.AmazonS3(
bucket: "my-bucket",
file: "invoices/invoice.docx",
accesskeyid: "AKIA...",
secretaccesskey: "...");
var result = await client.ConvertAsync(input, "pdf");
await result.SaveAsync("invoice.pdf"); // a normal, downloadable result
To deliver the output into a bucket, attach an OutputTarget via the OutputTargets option. Output
uses the generic target (a CloudProvider plus free-form parameters / credentials), not a
per-provider factory:
using Api2Convert.Enums;
using Api2Convert.Models;
var target = OutputTarget.Of(
CloudProvider.AmazonS3,
parameters: new Dictionary<string, object?> { ["bucket"] = "my-bucket", ["file"] = "out/invoice.pdf" },
credentials: new Dictionary<string, object?> { ["accesskeyid"] = "AKIA...", ["secretaccesskey"] = "..." });
// With an output target set, the conversion delivers straight to your storage and produces no local
// output — ConvertAsync returns the completed job (result.Job) and there is nothing to download.
var result = await client.ConvertAsync(
"invoice.docx",
"pdf",
opts: new ConvertOptions { OutputTargets = new[] { target } });
Azure, Ftp and GoogleCloud input factories exist too (same shape). Credentials ride in the request
body, so the SDK masks the whole credentials object to [REDACTED] in ToString() / logs and never
prints or echoes it in error text.
Full control: the Jobs API
ConvertAsync is built on the resource API, which you can use directly for compound jobs, job
chaining, custom polling or presets:
var job = await client.Jobs.CreateAsync(new Dictionary<string, object?>
{
["conversion"] = new[] { new Dictionary<string, object?> { ["target"] = "png" } },
["process"] = false,
});
await client.Jobs.UploadAsync(job, "input.jpg");
await client.Jobs.StartAsync(job.Id);
var done = await client.Jobs.WaitAsync(job.Id);
Resources: client.Jobs, client.Conversions, client.Presets, client.Stats, client.Contracts.
Typed errors
using Api2Convert.Exceptions;
try
{
await client.ConvertAsync("photo.jpg", "not-a-format");
}
catch (ValidationException e) { Console.WriteLine($"Invalid request: {e.Message} (HTTP {e.StatusCode})"); }
catch (RateLimitException e) { Console.WriteLine($"Slow down; retry after {e.RetryAfter}s"); }
catch (ConversionFailedException e) { Console.WriteLine($"Job {e.Job.Id} failed: {e.Message}"); }
catch (Api2ConvertException e) { Console.WriteLine($"SDK error: {e.Message}"); } // catch-all base
Transient failures (429 / 5xx / network) are retried automatically with capped, jittered exponential
backoff honoring Retry-After; a non-idempotent POST is never blindly retried, so a transient error
cannot create a duplicate job.
Configuration
var config = new Config.Builder()
.BaseUrl("https://api.api2convert.com/v2")
.Timeout(30) // per-request seconds
.MaxRetries(2)
.PollInterval(1.0) // seconds; floored so it can never busy-loop
.PollMaxInterval(5.0)
.PollTimeout(300) // seconds; capped so it can never poll unbounded
.Build();
using var client = new Api2ConvertClient("YOUR_API_KEY", config);
Plug in your own transport (or a mock) via the IHttpSender seam:
new Api2ConvertClient(apiKey, config, myHttpSender).
Testing
make check # build + offline unit suite + independent security suite (no API key)
make test-security # just the security suite (real loopback servers)
# Live conformance against the real API (auto-skips without a key):
API2CONVERT_API_KEY=<your key> make test-live
# Or run everything in a container on a pinned .NET SDK:
make docker-check
The live conformance suite doubles as an
executable, end-to-end tour of the SDK — there is one test per documented guide (plus two negative
tests), each a self-contained usage example that mirrors the runnable file of the same name in
examples/.
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.
Examples
Every documented guide has a runnable, self-contained example in
examples/Examples. They live in one console project; pass the guide slug to run
one (the key is read from API2CONVERT_API_KEY, and API2CONVERT_BASE_URL retargets the host):
API2CONVERT_API_KEY=your-key dotnet run --project examples/Examples -- quickstart
Run it with no argument to list every guide.
| Guide | File |
|---|---|
| Quickstart — convert a remote JPG to PNG, then download | Quickstart.cs |
| Convert Files — browse the catalog, then convert | ConvertFiles.cs |
| Uploading Files — one-call upload + convert of a local file | UploadingFiles.cs |
| Job Lifecycle — create → add input → start → wait → outputs | JobLifecycle.cs |
| Add a Watermark — stamp a PNG onto a PDF | AddWatermark.cs |
| Create Thumbnails — first PDF page → PNG thumbnail | CreateThumbnails.cs |
| Compress Files — shrink a JPG | CompressFiles.cs |
| Create Archives — bundle two files into a ZIP | CreateArchives.cs |
| Create Hashes — SHA-256 of a ZIP | CreateHashes.cs |
| Extract Assets — pull assets out of a DOCX | ExtractAssets.cs |
| File Analysis — read a JPG's metadata as JSON | FileAnalysis.cs |
| Compare Files — SSIM diff of two images | CompareFiles.cs |
| Capture a Website — screenshot a URL to PNG | CaptureWebsite.cs |
| Audio Operations — re-encode WAV → AAC | AudioOperations.cs |
| Image Operations — resize a JPG | ImageOperations.cs |
| Webhooks — async convert with a callback, and verify a delivery | Webhooks.cs |
| Presets — list saved presets | Presets.cs |
| Statistics — usage stats for a month | Statistics.cs |
| Rate Limits — read contract information | RateLimits.cs |
| Authentication — list jobs to confirm the key works | Authentication.cs |
License
MIT © Qaamgo Media GmbH.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.