Skip to content

SDKs

TODO: Still needs to be updated. If the code would be hosted publicly then there can be a link to the repository.

You can call the Pagr API directly over HTTP, but the official SDKs make it easier: they wrap the base URL, attach your API key, parse responses into typed objects, turn HTTP errors into exceptions you can catch, retry transient read failures, and validate list filters client-side. They cover the whole API — templates and versions, every rendering shape, validation, document browsing, fonts, org stats, service probes, and webhook payload parsing.

Language Package (working name) Client Sync / async Notes
cURL (raw HTTP) Call the API directly with any HTTP client — no library to install. See Quickstart.
Python pagr (PyPI) PagrApiClient Async only Built on httpx, full type hints. The reference implementation — most actively maintained; the others are kept at feature parity with it.
TypeScript pagr (npm) PagrApiClient Async only (native fetch) Zero runtime dependencies, Node.js 18+. Classes parse API responses into iterable result types.
Java final Maven coordinates TBD PagrApiClient / PagrAsyncApiClient Both — a sync client plus an async client returning CompletableFuture Gradle library on a Java 21 toolchain; JSON handling kept internal.
C# / .NET Pagr.Sdk (NuGet) PagrApiClient Async only net8.0, sealed strongly-typed models, Async suffix, CancellationToken throughout, built on System.Text.Json.
Ruby pagr (RubyGems, unpublished) Pagr::Client Synchronous only Ruby 3.0+, built on Faraday, idiomatic Ruby naming (see below).
C++ pagr_sdk (CMake package) pagr::PagrApiClient Both — every call has a sync form and an _async form C++20, integrated via CMake, RAII for resource management.

The Java SDK’s package is still on a placeholder identifier internally — don’t build against a Maven coordinate for it yet; ask us for the current artifact when you request access.

Construct a client with your API key, render one document, and save the PDF:

Terminal window
curl -X POST "https://pagr-prd-api-public.azurewebsites.net/v1/render/8bec66ff-6f3d-4c1e-9a2b-1f0e5d7c4a90" \
-H "Authorization: Bearer pagr_test_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"documents": [
{ "Title": "Acme Q3 Invoice", "Amount": 42 }
],
"includeDocument": true
}'

No SDK required — this is the same call every official SDK below wraps.

Whichever language you use, the SDKs share the same behaviour — so what you learn in one carries over:

  • Same authentication — a bearer API key passed at construction, swappable at runtime with set_api_key. See Authentication.
  • Same error split — protocol failures raise; business outcomes (validation failure, insufficient credit, partial batch) come back as data on the result object.
  • Same error mapping — one small exception tree, with transport failures (timeouts, connection errors) folded into it, so you only ever catch one family. See Handle errors and retries.
  • Same retry policy — idempotent GETs retried on 500/502/503/504, timeouts and connection errors, with capped exponential backoff and full jitter. Writes never; 429 never.
  • Same rendering model — single, synchronous batch, async job and stateless renders, with the same counts, status values and issues on every result. See Choose a rendering shape.
  • Same pagingskip/take with a total and a client-side “more pages?” flag. See Listing & pagination.
  • Same client-side filter validation — an unknown filter field or operator raises immediately instead of silently returning the unfiltered result set.
  • Same webhook parsing — one function turns an incoming callback body into the right typed progress or completion object, validating the shape first.

Nearly everything is at parity. These are the genuine differences worth knowing before you pick a language:

Capability Python TypeScript Java C# Ruby C++
Every endpoint
Retry policy on reads
Webhook payload parsing
Raw-PDF render (render_pdf)
Per-call timeout override
Typed list/batch overload for validate
Bundled webhook receiver (dev only)
Filename sanitisation on save()
Sync and async client
Cancellation tokens

Where a cell is ❌, there’s a documented workaround on the linked page — e.g. C# and Java get the PDF bytes via includeDocument: true instead of render_pdf, and Java uses a longer-timeout client instead of a per-call override.

Method names follow each language’s conventions rather than Python’s, so the same call reads natively everywhere:

Operation Python TypeScript Java C# Ruby C++
Render render render render RenderAsync render render
Render a batch render_batch renderBatch renderBatch RenderBatchAsync render_batch render_batch
Enqueue async enqueue_batch_render enqueueBatchRender enqueueBatchRender EnqueueBatchRenderAsync enqueue_batch_render enqueue_batch_render
Poll a job get_job_status getJobStatus getJobStatus GetJobStatusAsync job_status get_job_status
Validate validate validate validate ValidateAsync validate validate
List templates get_templates getTemplates getTemplates GetTemplatesAsync templates get_templates
List documents get_documents getDocuments getDocuments GetDocumentsAsync documents get_documents
Download a PDF download_document downloadDocument downloadDocument DownloadDocumentAsync download_document download_document
Org stats get_org_stats getOrgStats getOrgStats GetOrgStatsAsync org_stats get_org_stats
Parse a callback parse_callback parseCallback RenderCallback.parse RenderCallback.Parse Pagr.parse_callback pagr::parse_callback

Note Ruby drops the get_ prefix throughout (client.templates, not client.get_templates) — an accessor doesn’t announce itself as a getter in Ruby.