Skip to content
Documentation menu

API

SDKs

Official .NET and TypeScript clients: render, jobs, templates, datasets, typed errors, safe retries and webhook verification.

The official SDKs wrap the public API with the same surface in every language: render a template, wait for large documents, read templates and datasets, typed errors with the correlation id, safe retries and webhook signature verification.

Official SDKs
FieldTypeDescription
Prynt.Client.NETNuGet package for .NET Framework 4.6.2+ (netstandard2.0) and .NET 8, 9, 10, with HttpClientFactory integration.
@prynt/sdkTypeScriptnpm package, ESM with types and no dependencies: Node.js 18+, Deno, Bun and edge runtimes with fetch and WebCrypto.

Keep the key on your server

API keys are secrets. Use the SDKs from your backend, ERP or worker, never from a browser bundle or a mobile app.

Install

1dotnet add package Prynt.Client

Render a document

RenderAsync / render send the template code, the parameters and the environment, and return the document bytes with their metadata: version, page count, environment, correlation id and the run in the Logs.

1using Prynt.Client;2 3using var prynt = new PryntClient(Environment.GetEnvironmentVariable("PRYNT_API_KEY")!);4 5var pdf = await prynt.Documents.RenderAsync(6    "DDT_STANDARD",7    new { DOCUMENT_ID = 82422 },   // parameter names are sent as written8    environment: "production");9 10await pdf.SaveAsync("ddt-82422.pdf");11Console.WriteLine($"v{pdf.Version}, {pdf.PageCount} pages, correlation id {pdf.CorrelationId}");12 13// ASP.NET Core: builder.Services.AddPrynt(o => o.ApiKey = builder.Configuration["Prynt:ApiKey"]);14// then inject PryntClient.

Large documents and jobs

When a document is too large or slow for a synchronous answer, the API replies 202 Accepted with a job. The SDKs handle it for you: they poll the job with growing intervals and download the document through its signed link, without sending your key. To manage the job yourself, start it explicitly:

1var job = await prynt.Documents.StartRenderJobAsync(new RenderRequest("DDT_STANDARD")2{3    Parameters = new { DOCUMENT_ID = 82422 },4    CorrelationId = "erp-ddt-82422",5});6 7var done = await prynt.Jobs.WaitAsync(job.JobId);         // throws PryntJobFailedException on failure8var document = await prynt.Documents.DownloadAsync(done); // renews an expired link by itself

Templates and datasets

1foreach (var template in await prynt.Templates.ListAsync())2    Console.WriteLine($"{template.Code} v{template.Version}");3 4var rows = await prynt.Datasets.ExecuteAsync("DDT_STANDARD", "RIGHE", new { DOCUMENT_ID = 82422 }, maxRows: 100);

Errors

Every error answer is an RFC 9457 problem; the SDKs throw it as a typed error with errorCode, detail, the HTTP status, the correlationId to give to support and, for 429, the Retry-After delay.

1try2{3    await prynt.Documents.RenderAsync("DDT_STANDARD", new { DOCUMENT_ID = 82422 });4}5catch (PryntApiException e)6{7    // e.Status, e.ErrorCode, e.Detail, e.CorrelationId, e.RetryAfter, e.Extensions8    Console.Error.WriteLine($"{e.ErrorCode}: {e.Detail} (correlation id {e.CorrelationId})");9}

Retries

  • Reads (jobs, templates, document downloads, datasets) are retried on 429, 502, 503, 504, network errors and timeouts, with exponential backoff and jitter, always honoring Retry-After.
  • Renders are retried only when Prynt guarantees nothing was generated: 429 RATE_LIMITED, 503 RENDER_BUSY or DATA_SOURCE_UNAVAILABLE. After a network error or a timeout the document may already exist, so the error is returned to you instead of rendering twice. Pass your own correlation id to find the render in the Logs.

Webhooks

Both SDKs verify the Prynt-Signature header (HMAC-SHA256 of {t}.{raw body}, constant-time comparison, 5-minute tolerance) before you parse the event.

C#
// The raw body, before any JSON binding.if (!WebhookSignature.Verify(rawBody, request.Headers["Prynt-Signature"], secret))    return Results.Unauthorized();var evt = PryntWebhookEvent.Parse(rawBody);   // deduplicate on evt.Id
TypeScript
// Express: express.raw({ type: "application/json" }) keeps the raw body.if (!(await verifyWebhookSignature(req.body, req.get("Prynt-Signature"), secret))) return res.sendStatus(401);const event = parseWebhookEvent(req.body); // deduplicate on event.id