Pogodoc
SDKs

.NET

Complete reference for the Pogodoc .NET SDK with types, advanced configuration, and examples

.NET SDK

Complete documentation for the Pogodoc .NET SDK. This guide covers installation, configuration, all available methods, and advanced usage patterns.

New to Pogodoc? Start with the .NET Quickstart guide first.

Installation

dotnet add package Pogodoc.Net

Or via NuGet Package Manager:

Install-Package Pogodoc.Net

Client Configuration

Basic Configuration

using Pogodoc.Net;

var client = new PogodocClient("your-api-token");

With Base URL

var client = new PogodocClient(
    token: "your-api-token",
    baseUrl: "https://api.pogodoc.com"
);

Environment Variables

Configure using environment variables:

// Token from environment variables
var token = Environment.GetEnvironmentVariable("POGODOC_API_TOKEN");
var client = new PogodocClient(token);
appsettings.json
{
  "Pogodoc": {
    "ApiToken": "your_token_here",
    "BaseUrl": "https://api.pogodoc.com"
  }
}

The constructor requires a valid token. Ensure the token is provided either directly or via environment variables.

Core Methods

The SDK provides both synchronous and asynchronous methods for document generation and template management.

GenerateDocumentAsync()

The recommended method for most use cases. Generates a document and polls for completion automatically.

using Pogodoc.Net;

var client = new PogodocClient("your-token");

var result = await client.GenerateDocumentAsync(
    templateId: "your-template-id",
    data: new Dictionary<string, object>
    {
        ["name"] = "Jane Doe",
        ["amount"] = 1299.99
    },
    renderConfig: new RenderConfig
    {
        Type = TemplateType.React,
        Target = RenderTarget.Pdf
    }
);

Console.WriteLine($"Document URL: {result.Output.Data.Url}");

Parameters:

  • template (optional): Raw HTML/template string
  • templateId (optional): ID of a saved template
  • data: Dictionary containing data to populate the template
  • renderConfig: RenderConfig object with:
    • Type: Template format type
    • Target: Output format
    • FormatOpts (optional): Format-specific options

Important: You must provide either template or templateId, but not both. Exactly one is required.

Returns: Task<JobStatusResponse> - Job status with the final output URL

GenerateDocumentImmediateAsync()

For quick, synchronous rendering of small documents. Returns the result immediately without job polling.

var result = await client.GenerateDocumentImmediateAsync(
    templateId: "your-template-id",
    data: new Dictionary<string, object>
    {
        ["name"] = "Jane Doe"
    },
    renderConfig: new RenderConfig
    {
        Type = TemplateType.Ejs,
        Target = RenderTarget.Pdf
    }
);

Console.WriteLine($"Document URL: {result.Output.Data.Url}");

Important: You must provide either template or templateId, but not both. Exactly one is required.

Best for: Small, quick renders where you need immediate results

Use GenerateDocumentAsync() for larger documents or when reliability is critical. Use GenerateDocumentImmediateAsync() for small, quick renders.

StartGenerateDocumentAsync()

Lower-level method that only initializes the job. Use this if you want to implement custom polling logic.

var jobId = await client.StartGenerateDocumentAsync(
    templateId: "your-template-id",
    data: new Dictionary<string, object>
    {
        ["name"] = "Jane Doe"
    },
    renderConfig: new RenderConfig
    {
        Type = TemplateType.React,
        Target = RenderTarget.Pdf
    }
);

Console.WriteLine($"Started job: {jobId}");

Important: You must provide either template or templateId, but not both. Exactly one is required.

Returns: Task<string> - The job ID

PollForJobCompletionAsync()

Polls for the completion of a rendering job. Use with StartGenerateDocumentAsync() for custom workflows.

var result = await client.PollForJobCompletionAsync(
    jobId: jobId,
    maxAttempts: 60,    // default: 60
    intervalMs: 500     // default: 500
);

Console.WriteLine($"Job finished: {result.Output.Data.Url}");

Parameters:

  • jobId: The ID of the job to poll
  • maxAttempts: Maximum number of polling attempts (default: 60)
  • intervalMs: Interval between attempts in milliseconds (default: 500)

Returns: Task<JobStatusResponse> - The completed job response

Template Management

SaveTemplateAsync()

Save a new template from a local ZIP file.

using System.IO;

var templateInfo = new TemplateInfo
{
    Title = "My Template",
    Description = "Invoice template for customers",
    Type = TemplateType.React,
    Categories = new[] { "invoice" },
    SampleData = new Dictionary<string, object>
    {
        ["name"] = "John Doe",
        ["amount"] = 1299.99
    },
    SourceCode = "https://github.com/yourorg/template"
};

var templateId = await client.SaveTemplateAsync(
    filePath: "./path/to/template.zip",
    templateInfo: templateInfo
);

Console.WriteLine($"Template saved with ID: {templateId}");

Parameters:

  • filePath: Local file path to the ZIP file
  • templateInfo: Template metadata object

Returns: Task<string> - The new template ID

SaveTemplateFromStreamAsync()

Core method for saving templates from a stream. Useful for handling uploads in web applications.

using (var fileStream = File.OpenRead("./path/to/template.zip"))
{
    var templateId = await client.SaveTemplateFromStreamAsync(
        stream: fileStream,
        templateInfo: templateInfo
    );

    Console.WriteLine($"Template saved: {templateId}");
}

UpdateTemplateAsync()

Update an existing template with a new version from a ZIP file.

var updateInfo = new TemplateInfo
{
    Title = "My Updated Template",
    Description = "Updated invoice template",
    Type = TemplateType.React,
    Categories = new[] { "invoice", "updated" },
    SampleData = new Dictionary<string, object>
    {
        ["name"] = "John Doe",
        ["amount"] = 1599.99
    }
};

var contentId = await client.UpdateTemplateAsync(
    templateId: "existing-template-id",
    filePath: "./path/to/new-version.zip",
    templateInfo: updateInfo
);

Console.WriteLine($"Template updated. New content ID: {contentId}");

Returns: Task<string> - Updated template content ID

UpdateTemplateFromStreamAsync()

Update a template from a stream.

using (var fileStream = File.OpenRead("./path/to/new-version.zip"))
{
    var contentId = await client.UpdateTemplateFromStreamAsync(
        templateId: "existing-template-id",
        stream: fileStream,
        templateInfo: updateInfo
    );

    Console.WriteLine($"New content ID: {contentId}");
}

Template Types

Pogodoc supports multiple template formats for different use cases:

TypeDescriptionBest For
ReactAny frontend JS frameworkComplex layouts, reusable components
EjsEmbedded JavaScript templatesSimple variable substitution
Latex 🚧LaTeX for scientific documentsAcademic papers, mathematical content
Docx 🚧Microsoft Word templatesBusiness documents, form letters
Xlsx 🚧Microsoft Excel templatesSpreadsheets, data reports
Pptx 🚧Microsoft PowerPoint templatesPresentations, slides

React Templates: Any JavaScript framework works here! Use React, Vue, Angular, Svelte, or any other framework that renders to HTML/JSX. See our JavaScript Framework Templates guide for detailed setup instructions.

🚧 Coming Soon: LaTeX, DOCX, XLSX, and PPTX template types are currently in development and will be available soon.

JavaScript Framework Templates

JavaScript framework templates require a build process and must be uploaded as ZIP files. See the complete guide: JavaScript Framework Templates

Quick example of using a React template:

// Upload your built and zipped React template
var templateId = await client.SaveTemplateAsync(
    filePath: "./my-react-template.zip",
    templateInfo: new TemplateInfo
    {
        Title = "Invoice Template",
        Type = TemplateType.React,
        Categories = new[] { "invoice" }
    }
);

// Generate documents using the template
var result = await client.GenerateDocumentAsync(
    templateId: templateId,
    data: new Dictionary<string, object>
    {
        ["customer"] = new { Name = "Jane Smith" },
        ["items"] = new[]
        {
            new { Name = "Service A", Price = 150.00 },
            new { Name = "Service B", Price = 250.00 }
        },
        ["total"] = 400.00
    },
    renderConfig: new RenderConfig
    {
        Type = TemplateType.React,
        Target = RenderTarget.Pdf
    }
);

Console.WriteLine($"Document URL: {result.Output.Data.Url}");

EJS/HTML Template

EJS/HTML templates can be provided as inline strings:

var result = await client.GenerateDocumentAsync(
    template: @"
        <h1>Hello <%= name %></h1>
        <p>Your order #<%= orderId %> has been confirmed.</p>
        <% if (premium) { %>
          <p>Thank you for being a premium member!</p>
        <% } %>
    ",
    data: new Dictionary<string, object>
    {
        ["name"] = "John Doe",
        ["orderId"] = 12345,
        ["premium"] = true
    },
    renderConfig: new RenderConfig
    {
        Type = TemplateType.Ejs,
        Target = RenderTarget.Pdf
    }
);

Render Targets

Generate documents in multiple output formats:

TargetDescriptionUse Cases
PdfPDF documentsInvoices, reports, printable documents
PngPNG imagesSocial media graphics, thumbnails
Jpg 🚧JPEG imagesCompressed images for web
Html 🚧HTML outputWeb previews, email content
Docx 🚧Word documentsEditable business documents
Xlsx 🚧Excel spreadsheetsData reports, financial documents
Pptx 🚧PowerPoint presentationsSlides, presentations

🚧 Coming Soon: JPG, HTML, DOCX, XLSX, and PPTX render targets are currently in development and will be available soon.

Format Options

Customize the rendering process with format-specific options:

var result = await client.GenerateDocumentAsync(
    templateId: "invoice-template",
    data: invoiceData,
    renderConfig: new RenderConfig
    {
        Type = TemplateType.React,
        Target = RenderTarget.Pdf,
        FormatOpts = new FormatOptions
        {
            Format = "A4",
            WaitForSelector = ".ready",
            FromPage = 1,
            ToPage = 5
        }
    }
);

Available Format Options

OptionTypeDescription
FormatstringPage format (A3, A4, A5, Letter, Legal, Tabloid)
WaitForSelectorstringCSS selector to wait for before rendering
FromPageint?Starting page number for partial renders
ToPageint?Ending page number for partial renders

Using Saved Templates

Instead of providing template content inline, you can use templates saved in your Pogodoc dashboard:

Create a Template

Go to your Pogodoc Dashboard and create a new template. Save it and copy the template ID.

Reference the Template

var result = await client.GenerateDocumentAsync(
    templateId: "your-template-id",
    data: new Dictionary<string, object>
    {
        ["name"] = "John Doe",
        ["amount"] = 1299.99
    },
    renderConfig: new RenderConfig
    {
        Target = RenderTarget.Pdf
    }
);

Best Practices

1. Use Configuration Files

Store API tokens in configuration files:

// appsettings.json
{
  "Pogodoc": {
    "ApiToken": "your_token_here"
  }
}

// Program.cs
var token = configuration["Pogodoc:ApiToken"];
var client = new PogodocClient(token);

2. Use Saved Templates

For production, use saved templates instead of inline templates:

// ✅ Good
var result = await client.GenerateDocumentAsync(
    templateId: "invoice-v2",
    data: data,
    renderConfig: new RenderConfig { Target = RenderTarget.Pdf }
);

// ❌ Less ideal - template in code
var result = await client.GenerateDocumentAsync(
    template: "<html>...</html>",
    data: data,
    renderConfig: new RenderConfig
    {
        Type = TemplateType.Html,
        Target = RenderTarget.Pdf
    }
);

3. Error Handling

Always wrap SDK calls in try-catch blocks:

try
{
    var result = await client.GenerateDocumentAsync(
        templateId: "invoice",
        data: data,
        renderConfig: new RenderConfig { Target = RenderTarget.Pdf }
    );

    Console.WriteLine($"Document URL: {result.Output.Data.Url}");
}
catch (Exception ex)
{
    Console.WriteLine($"Document generation failed: {ex.Message}");
    // Handle error appropriately
}

4. Use Dependency Injection

Inject the client as a singleton in ASP.NET Core:

// Program.cs or Startup.cs
services.AddSingleton<IPogodocClient>(sp =>
{
    var token = configuration["Pogodoc:ApiToken"];
    return new PogodocClient(token);
});

// Controller
public class InvoiceController : ControllerBase
{
    private readonly IPogodocClient _pogodocClient;

    public InvoiceController(IPogodocClient pogodocClient)
    {
        _pogodocClient = pogodocClient;
    }

    [HttpPost("generate")]
    public async Task<IActionResult> GenerateInvoice([FromBody] InvoiceData data)
    {
        var result = await _pogodocClient.GenerateDocumentAsync(
            templateId: "invoice-template",
            data: data.ToDictionary(),
            renderConfig: new RenderConfig { Target = RenderTarget.Pdf }
        );

        return Ok(new { url = result.Output.Data.Url });
    }
}

Examples

Invoice Generation

public async Task<string> GenerateInvoiceAsync(
    PogodocClient client,
    InvoiceData invoiceData)
{
    var result = await client.GenerateDocumentAsync(
        templateId: "invoice-template",
        data: new Dictionary<string, object>
        {
            ["invoiceNumber"] = invoiceData.Number,
            ["customer"] = invoiceData.Customer,
            ["items"] = invoiceData.Items,
            ["subtotal"] = invoiceData.Subtotal,
            ["tax"] = invoiceData.Tax,
            ["total"] = invoiceData.Total,
            ["date"] = DateTime.Now.ToString("MM/dd/yyyy")
        },
        renderConfig: new RenderConfig
        {
            Target = RenderTarget.Pdf,
            FormatOpts = new FormatOptions { Format = "A4" }
        }
    );

    return result.Output.Data.Url;
}

Social Media Graphics

public async Task<string> GenerateSocialGraphicAsync(
    PogodocClient client,
    PostData post)
{
    var result = await client.GenerateDocumentAsync(
        templateId: "social-media-card",
        data: new Dictionary<string, object>
        {
            ["title"] = post.Title,
            ["author"] = post.Author,
            ["image"] = post.FeaturedImage
        },
        renderConfig: new RenderConfig { Target = RenderTarget.Png }
    );

    return result.Output.Data.Url;
}

Batch Document Generation

public async Task<List<string>> GenerateMultipleDocumentsAsync(
    PogodocClient client,
    List<Dictionary<string, object>> dataList)
{
    var urls = new List<string>();

    foreach (var data in dataList)
    {
        try
        {
            var result = await client.GenerateDocumentAsync(
                templateId: "report-template",
                data: data,
                renderConfig: new RenderConfig
                {
                    Type = TemplateType.React,
                    Target = RenderTarget.Pdf
                }
            );

            urls.Add(result.Output.Data.Url);
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Failed to generate document: {ex.Message}");
            continue;
        }
    }

    return urls;
}

Using with Dependency Injection

public class DocumentService : IDocumentService
{
    private readonly IPogodocClient _client;
    private readonly ILogger<DocumentService> _logger;

    public DocumentService(
        IPogodocClient client,
        ILogger<DocumentService> logger)
    {
        _client = client;
        _logger = logger;
    }

    public async Task<string> GenerateDocumentAsync(
        string templateId,
        object data)
    {
        try
        {
            var result = await _client.GenerateDocumentAsync(
                templateId: templateId,
                data: ConvertToDict(data),
                renderConfig: new RenderConfig { Target = RenderTarget.Pdf }
            );

            _logger.LogInformation(
                "Generated document: {Url}",
                result.Output.Data.Url
            );

            return result.Output.Data.Url;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Failed to generate document");
            throw;
        }
    }

    private Dictionary<string, object> ConvertToDict(object data)
    {
        // Convert object to dictionary using your preferred method
        // (e.g., System.Text.Json, Newtonsoft.Json, reflection)
        return JsonSerializer.Deserialize<Dictionary<string, object>>(
            JsonSerializer.Serialize(data)
        );
    }
}

Next Steps