Pogodoc
SDKs

Custom SDK

Build a custom SDK for your preferred language using the Pogodoc REST API

Create Your Own SDK

If an official SDK doesn't exist for your preferred programming language, you can easily build your own by wrapping the Pogodoc REST API. This guide explains the API call patterns and workflows used in our official SDKs.

API Reference

Complete REST API documentation

This guide follows the implementation patterns from the TypeScript SDK. You can reference it while building your own SDK.

Built an SDK? We'd love to feature it! Submit a PR to add your SDK to our official documentation, or reach out to us at [email protected].

Authentication

All API requests require authentication using a Bearer token:

Authorization: Bearer YOUR_API_TOKEN

Set the base URL to:

https://api.pogodoc.com

Security Best Practice: Never hardcode API tokens. Use environment variables or secure configuration management.

Core Workflows

There are three main workflows for document generation:

  1. Standard Generation - Initialize job, upload data/template, start render, poll for completion
  2. Immediate Render - Single API call for quick, synchronous rendering
  3. Template Management - Upload, extract, preview, and save templates

1. Standard Document Generation

This is the recommended workflow for most use cases. It provides reliability and handles larger documents well.

High-Level Flow

Initialize Render Job

Create a new render job and get presigned URLs for uploading data and templates.

Endpoint: POST /documents/initAPI Reference

  • Use templateId for saved templates
  • presignedTemplateUploadUrl is only provided if you're using an inline template (not a saved template)
  • formatOpts is optional

Upload Data to S3 Upload your template data as JSON to the presigned S3

URL.

This is a direct S3 upload - do not include the Authorization header.

Upload Template (if inline) If you're using an inline template (not a

saved template), upload it to S3.

Skip this step if you're using a templateId - the template is already stored.

Start Render Job

Trigger the actual rendering process.

Endpoint: POST /documents/{jobId}/renderAPI Reference

Set shouldWaitForRenderCompletion: true for synchronous rendering, but note this may timeout for large documents.

Poll for Job Completion

Repeatedly check the job status until it's complete.

Endpoint: GET /jobs/{jobId}API Reference

Polling Strategy:

  • Wait 1 second before first poll
  • Poll every 500ms
  • Maximum 60 attempts (30 seconds total)
  • Return final status even if not "done"

Implementation Example (Pseudocode)

async function generateDocument(config) {
  // Step 1: Initialize
  const initResponse = await POST("/documents/init", {
    type: config.renderConfig.type,
    target: config.renderConfig.target,
    templateId: config.templateId,
    formatOpts: config.renderConfig.formatOpts,
  });

  // Step 2: Upload data to S3
  await PUT(initResponse.presignedDataUploadUrl, JSON.stringify(config.data), {
    "Content-Type": "application/json",
  });

  // Step 3: Upload template to S3 (if inline)
  if (config.template && initResponse.presignedTemplateUploadUrl) {
    await PUT(initResponse.presignedTemplateUploadUrl, config.template, {
      "Content-Type": "text/html",
    });
  }

  // Step 4: Start render
  await POST(`/documents/${initResponse.jobId}/render`, {
    shouldWaitForRenderCompletion: false,
  });

  // Step 5: Poll for completion
  return await pollForCompletion(initResponse.jobId);
}

async function pollForCompletion(jobId, maxAttempts = 60, intervalMs = 500) {
  await sleep(1000); // Initial wait

  for (let i = 0; i < maxAttempts; i++) {
    const job = await GET(`/jobs/${jobId}`);

    if (job.status === "done") {
      return job;
    }

    await sleep(intervalMs);
  }

  // Return final status even if not complete
  return await GET(`/jobs/${jobId}`);
}

2. Immediate Render

For small documents that need quick, synchronous rendering, use the immediate render endpoint.

Single API Call

Endpoint: POST /documents/immediate-renderAPI Reference

Limitations: - May timeout for large or complex documents - No progress tracking - Not recommended for production use cases Use the standard generation workflow for reliability.

Implementation Example (Pseudocode)

async function generateDocumentImmediate(config) {
  const response = await POST("/documents/immediate-render", {
    template: config.template,
    templateId: config.templateId,
    data: config.data,
    type: config.renderConfig.type,
    target: config.renderConfig.target,
    formatOpts: config.renderConfig.formatOpts,
  });

  return response;
}

3. Template Management

Save and update templates for reuse across multiple document generations.

Saving a New Template

Initialize Template Creation

Get a template ID and presigned S3 upload URL.

Endpoint: GET /templates/initAPI Reference

Generate Previews Create PDF and PNG previews using sample data.

Endpoint: POST /templates/{templateId}/render-previewsAPI Reference

Finalize Template

Save the template with metadata and get templateId.

Endpoint: POST /templates/{templateId}API Reference

Implementation Example (Pseudocode)

async function saveTemplate(filePath, metadata) {
  // Step 1: Initialize
  const initResponse = await GET("/templates/init");
  const templateId = initResponse.templateId;

  // Step 2: Upload ZIP to S3
  const fileData = readFile(filePath);
  const fileSize = getFileSize(filePath);

  await PUT(initResponse.presignedTemplateUploadUrl, fileData, {
    "Content-Type": "application/zip",
    "Content-Length": fileSize,
  });

  // Step 3: Extract files
  await POST(`/templates/${templateId}/unzip`);

  // Step 4: Generate previews
  const previews = await POST(`/templates/${templateId}/render-previews`, {
    type: metadata.type,
    data: metadata.sampleData,
  });

  // Step 5: Finalize template
  await POST(`/templates/${templateId}`, {
    templateInfo: {
      title: metadata.title,
      description: metadata.description,
      type: metadata.type,
      categories: metadata.categories,
      sampleData: metadata.sampleData,
      sourceCode: metadata.sourceCode,
    },
    previewIds: {
      pdfJobId: previews.pdfPreview.jobId,
      pngJobId: previews.pngPreview.jobId,
    },
  });

  return templateId;
}

Updating a Template

The update flow is identical to saving, except:

  1. You get a new contentId instead of templateId from init
  2. Use PUT /templates/{templateId} (API Reference) instead of POST
  3. Pass the original templateId in the URL, and the new contentId in the body
async function updateTemplate(templateId, filePath, metadata) {
  // Get new content ID
  const initResponse = await GET("/templates/init");
  const contentId = initResponse.templateId;

  // Upload, extract, preview (same as save)
  // ...

  // Update template
  await PUT(`/templates/${templateId}`, {
    contentId: contentId,
    templateInfo: {
      /* metadata */
    },
    previewIds: {
      /* preview job IDs */
    },
  });

  return contentId;
}

Type Definitions

Template Types

  • react - React/Vue/Angular/Svelte templates
  • ejs - Embedded JavaScript templates
  • html - Plain HTML templates
  • latex - LaTeX documents (🚧 coming soon)
  • docx - Word documents (🚧 coming soon)
  • xlsx - Excel spreadsheets (🚧 coming soon)
  • pptx - PowerPoint presentations (🚧 coming soon)

Render Targets

  • pdf - PDF documents
  • png - PNG images
  • jpg - JPEG images (🚧 coming soon)
  • html - HTML output (🚧 coming soon)
  • docx - Word documents (🚧 coming soon)
  • xlsx - Excel spreadsheets (🚧 coming soon)
  • pptx - PowerPoint presentations (🚧 coming soon)

Format Options

{
  format?: 'A3' | 'A4' | 'A5' | 'Letter' | 'Legal' | 'Tabloid';
  waitForSelector?: string;  // CSS selector to wait for
  fromPage?: number;          // Starting page (partial render)
  toPage?: number;            // Ending page (partial render)
}

Job Status

  • initialized - Job created but not started
  • in-progress - Currently rendering
  • done - Rendering complete
  • failed - Rendering failed (check error details)

Built an SDK? We'd love to feature it! Submit a PR to add your SDK to our official documentation, or reach out to us at [email protected].