Skip to footer content
MIGRATION GUIDES

How to Migrate from CraftMyPDF to IronPDF in C#

Why Migrate from CraftMyPDF to IronPDF?

Cloud-based PDF APIs like CraftMyPDF introduce fundamental issues that make them unsuitable for many production environments.

The Problem with Cloud-Based PDF APIs

  1. Your Data Leaves Your System: Every HTML template and JSON data payload is transmitted to CraftMyPDF's servers. For invoices, contracts, medical records, or any sensitive business data, this creates HIPAA, GDPR, and SOC2 compliance risks.

  2. Network Latency: CraftMyPDF's own documentation states 1.5-30 seconds per PDF. IronPDF generates locally in milliseconds.

  3. Per-PDF Costs Add Up: 10,000 PDFs/month at subscription rates creates significant recurring costs versus a one-time perpetual license.

  4. Print-Optimized Output: Cloud APIs often optimize for print—reducing backgrounds and simplifying colors to save "ink." The result never looks like your HTML on screen.

  5. Template Lock-In: CraftMyPDF requires their proprietary drag-and-drop editor. You cannot use standard HTML/CSS freely.

Architecture Comparison

AspectCraftMyPDFIronPDF
Data LocationCloud (your data leaves your system)On-premise (data never leaves)
Latency1.5-30 seconds per PDFMilliseconds
PricingPer-PDF subscriptionOne-time perpetual license
Template SystemProprietary drag-and-drop onlyAny HTML/CSS/JavaScript
Output QualityPrint-optimizedPixel-perfect screen rendering
Works OfflineNo (requires internet)Yes
ComplianceData leaves organizationSOC2/HIPAA friendly

Feature Comparison

FeatureCraftMyPDFIronPDF
HTML to PDFVia API templates✅ Native
URL to PDFVia API✅ Native
Custom templatesProprietary editor only✅ Any HTML
CSS3 supportLimited✅ Full
JavaScript renderingLimited✅ Full
Merge/Split PDFsVia API✅ Native
WatermarksVia API✅ Native
Works offline
Self-hosted

Pre-Migration Preparation

Prerequisites

Ensure your environment meets these requirements:

  • .NET Framework 4.6.2+ or .NET Core 3.1 / .NET 5-9
  • Visual Studio 2019+ or VS Code with C# extension
  • NuGet Package Manager access
  • IronPDF license key (free trial available at ironpdf.com)

Audit CraftMyPDF Usage

Run these commands in your solution directory to identify all CraftMyPDF references:

# Find all CraftMyPDF usages in your codebase
grep -r "CraftMyPdf\|craftmypdf\|api.craftmypdf.com" --include="*.cs" .
grep -r "X-API-KEY" --include="*.cs" .

# Find API key references
grep -r "your-api-key\|template-id\|template_id" --include="*.cs" .

# Find NuGet package references
grep -r "CraftMyPdf\|RestSharp" --include="*.csproj" .
# Find all CraftMyPDF usages in your codebase
grep -r "CraftMyPdf\|craftmypdf\|api.craftmypdf.com" --include="*.cs" .
grep -r "X-API-KEY" --include="*.cs" .

# Find API key references
grep -r "your-api-key\|template-id\|template_id" --include="*.cs" .

# Find NuGet package references
grep -r "CraftMyPdf\|RestSharp" --include="*.csproj" .
SHELL

Breaking Changes to Anticipate

ChangeCraftMyPDFIronPDFImpact
ArchitectureCloud REST APILocal .NET libraryRemove HTTP calls
TemplatesProprietary editorStandard HTMLConvert templates to HTML
API KeyRequired for every callLicense at startupRemove API key handling
Async patternRequired (HTTP)OptionalRemove await if preferred
Error handlingHTTP status codesExceptionsChange try/catch patterns
Data bindingJSON templatesString interpolationSimplify data binding

Step-by-Step Migration Process

Step 1: Update NuGet Packages

Remove the HTTP client library and install IronPDF:

# Remove RestSharp HTTP client
dotnet remove package RestSharp

# Install IronPDF
dotnet add package IronPdf
# Remove RestSharp HTTP client
dotnet remove package RestSharp

# Install IronPDF
dotnet add package IronPdf
SHELL

Step 2: Update Namespace References

Replace HTTP client namespaces with IronPDF:

// Remove these
using RestSharp;
using System.IO;

// Add this
using IronPdf;
// Remove these
using RestSharp;
using System.IO;

// Add this
using IronPdf;
$vbLabelText   $csharpLabel

Step 3: Configure License (Once at Startup)

Replace per-request API key headers with a single license configuration:

// Add at application startup (Program.cs or Global.asax)
// This replaces all X-API-KEY headers
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
// Add at application startup (Program.cs or Global.asax)
// This replaces all X-API-KEY headers
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
$vbLabelText   $csharpLabel

Complete API Migration Reference

API Endpoint Mapping

CraftMyPDFIronPDFNotes
POST /v1/createrenderer.RenderHtmlAsPdf(html)No API call needed
X-API-KEY headerLicense.LicenseKey = "..."Set once at startup
template_idStandard HTML stringUse any HTML
{%name%} placeholders$"{name}" C# interpolationStandard .NET
POST /v1/mergePdfDocument.Merge(pdfs)Local, instant
POST /v1/add-watermarkpdf.ApplyWatermark(html)HTML-based
Webhook callbacksNot neededResults are synchronous
Rate limitingNot applicableNo limits

Configuration Mapping

CraftMyPDF OptionIronPDF EquivalentNotes
template_idHTML stringUse your own HTML
data JSONC# interpolation$"Hello {name}"
page_size: "A4"PaperSize = PdfPaperSize.A4
orientation: "landscape"PaperOrientation = Landscape
margin_top: 20MarginTop = 20In millimeters
headerHtmlHeaderFull HTML support
footerHtmlFooterFull HTML support

Code Migration Examples

HTML to PDF Conversion

The most common operation demonstrates the fundamental architecture shift from cloud API to local rendering.

CraftMyPDF Implementation:

// NuGet: Install-Package RestSharp
using System;
using RestSharp;
using System.IO;

class Program
{
    static void Main()
    {
        var client = new RestClient("https://api.craftmypdf.com/v1/create");
        var request = new RestRequest(Method.POST);
        request.AddHeader("X-API-KEY", "your-api-key");
        request.AddJsonBody(new
        {
            template_id = "your-template-id",
            data = new
            {
                html = "<h1>Hello World</h1><p>This is a PDF from HTML</p>"
            }
        });

        var response = client.Execute(request);
        File.WriteAllBytes("output.pdf", response.RawBytes);
    }
}
// NuGet: Install-Package RestSharp
using System;
using RestSharp;
using System.IO;

class Program
{
    static void Main()
    {
        var client = new RestClient("https://api.craftmypdf.com/v1/create");
        var request = new RestRequest(Method.POST);
        request.AddHeader("X-API-KEY", "your-api-key");
        request.AddJsonBody(new
        {
            template_id = "your-template-id",
            data = new
            {
                html = "<h1>Hello World</h1><p>This is a PDF from HTML</p>"
            }
        });

        var response = client.Execute(request);
        File.WriteAllBytes("output.pdf", response.RawBytes);
    }
}
$vbLabelText   $csharpLabel

IronPDF Implementation:

// NuGet: Install-Package IronPdf
using System;
using IronPdf;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderHtmlAsPdf("<h1>Hello World</h1><p>This is a PDF from HTML</p>");
        pdf.SaveAs("output.pdf");
    }
}
// NuGet: Install-Package IronPdf
using System;
using IronPdf;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderHtmlAsPdf("<h1>Hello World</h1><p>This is a PDF from HTML</p>");
        pdf.SaveAs("output.pdf");
    }
}
$vbLabelText   $csharpLabel

IronPDF eliminates the RestClient setup, API key headers, template IDs, and HTTP response handling—reducing a 15-line cloud operation to 4 lines of local code. For more options, see the HTML to PDF documentation.

URL to PDF Conversion

CraftMyPDF Implementation:

// NuGet: Install-Package RestSharp
using System;
using RestSharp;
using System.IO;

class Program
{
    static void Main()
    {
        var client = new RestClient("https://api.craftmypdf.com/v1/create");
        var request = new RestRequest(Method.POST);
        request.AddHeader("X-API-KEY", "your-api-key");
        request.AddJsonBody(new
        {
            template_id = "your-template-id",
            data = new
            {
                url = "https://example.com"
            },
            export_type = "pdf"
        });

        var response = client.Execute(request);
        File.WriteAllBytes("webpage.pdf", response.RawBytes);
    }
}
// NuGet: Install-Package RestSharp
using System;
using RestSharp;
using System.IO;

class Program
{
    static void Main()
    {
        var client = new RestClient("https://api.craftmypdf.com/v1/create");
        var request = new RestRequest(Method.POST);
        request.AddHeader("X-API-KEY", "your-api-key");
        request.AddJsonBody(new
        {
            template_id = "your-template-id",
            data = new
            {
                url = "https://example.com"
            },
            export_type = "pdf"
        });

        var response = client.Execute(request);
        File.WriteAllBytes("webpage.pdf", response.RawBytes);
    }
}
$vbLabelText   $csharpLabel

IronPDF Implementation:

// NuGet: Install-Package IronPdf
using System;
using IronPdf;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderUrlAsPdf("https://example.com");
        pdf.SaveAs("webpage.pdf");
    }
}
// NuGet: Install-Package IronPdf
using System;
using IronPdf;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderUrlAsPdf("https://example.com");
        pdf.SaveAs("webpage.pdf");
    }
}
$vbLabelText   $csharpLabel

IronPDF's RenderUrlAsPdf method captures the complete webpage including JavaScript-rendered content. For more options, see the URL to PDF documentation.

Headers and Footers

CraftMyPDF Implementation:

// NuGet: Install-Package RestSharp
using System;
using RestSharp;
using System.IO;

class Program
{
    static void Main()
    {
        var client = new RestClient("https://api.craftmypdf.com/v1/create");
        var request = new RestRequest(Method.POST);
        request.AddHeader("X-API-KEY", "your-api-key");
        request.AddJsonBody(new
        {
            template_id = "your-template-id",
            data = new
            {
                html = "<h1>Document Content</h1>",
                header = "<div>Page Header</div>",
                footer = "<div>Page {page} of {total_pages}</div>"
            }
        });

        var response = client.Execute(request);
        File.WriteAllBytes("document.pdf", response.RawBytes);
    }
}
// NuGet: Install-Package RestSharp
using System;
using RestSharp;
using System.IO;

class Program
{
    static void Main()
    {
        var client = new RestClient("https://api.craftmypdf.com/v1/create");
        var request = new RestRequest(Method.POST);
        request.AddHeader("X-API-KEY", "your-api-key");
        request.AddJsonBody(new
        {
            template_id = "your-template-id",
            data = new
            {
                html = "<h1>Document Content</h1>",
                header = "<div>Page Header</div>",
                footer = "<div>Page {page} of {total_pages}</div>"
            }
        });

        var response = client.Execute(request);
        File.WriteAllBytes("document.pdf", response.RawBytes);
    }
}
$vbLabelText   $csharpLabel

IronPDF Implementation:

// NuGet: Install-Package IronPdf
using System;
using IronPdf;
using IronPdf.Rendering;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        renderer.RenderingOptions.TextHeader = new TextHeaderFooter()
        {
            CenterText = "Page Header"
        };
        renderer.RenderingOptions.TextFooter = new TextHeaderFooter()
        {
            CenterText = "Page {page} of {total-pages}"
        };

        var pdf = renderer.RenderHtmlAsPdf("<h1>Document Content</h1>");
        pdf.SaveAs("document.pdf");
    }
}
// NuGet: Install-Package IronPdf
using System;
using IronPdf;
using IronPdf.Rendering;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        renderer.RenderingOptions.TextHeader = new TextHeaderFooter()
        {
            CenterText = "Page Header"
        };
        renderer.RenderingOptions.TextFooter = new TextHeaderFooter()
        {
            CenterText = "Page {page} of {total-pages}"
        };

        var pdf = renderer.RenderHtmlAsPdf("<h1>Document Content</h1>");
        pdf.SaveAs("document.pdf");
    }
}
$vbLabelText   $csharpLabel

IronPDF supports placeholder tokens like {page} and {total-pages} for dynamic page numbering. For more options, see the headers and footers documentation.

Template Variable Conversion

CraftMyPDF uses proprietary template placeholders that must be converted to C# string interpolation:

CraftMyPDF Pattern:

// CraftMyPDF template variables
request.AddJsonBody(new
{
    template_id = "invoice-template",
    data = new
    {
        customer = "John Doe",
        amount = "$1,000",
        items = invoiceItems
    }
});
// CraftMyPDF template variables
request.AddJsonBody(new
{
    template_id = "invoice-template",
    data = new
    {
        customer = "John Doe",
        amount = "$1,000",
        items = invoiceItems
    }
});
$vbLabelText   $csharpLabel

IronPDF Pattern:

// C# string interpolation
var html = $@"
<html>
<body>
    <h1>Invoice</h1>
    <p>Customer: {customerName}</p>
    <p>Amount: {amount}</p>
    {GenerateItemsTable(invoiceItems)}
</body>
</html>";

var pdf = renderer.RenderHtmlAsPdf(html);
// C# string interpolation
var html = $@"
<html>
<body>
    <h1>Invoice</h1>
    <p>Customer: {customerName}</p>
    <p>Amount: {amount}</p>
    {GenerateItemsTable(invoiceItems)}
</body>
</html>";

var pdf = renderer.RenderHtmlAsPdf(html);
$vbLabelText   $csharpLabel

Critical Migration Notes

Remove All HTTP Code

The most significant change is eliminating network dependencies. IronPDF runs locally—no RestClient, no API calls, no response handling:

// CraftMyPDF - HTTP required
var client = new RestClient("https://api.craftmypdf.com/v1/create");
var request = new RestRequest(Method.POST);
request.AddHeader("X-API-KEY", "your-api-key");
var response = await client.ExecuteAsync(request);

// IronPDF - no HTTP
var pdf = renderer.RenderHtmlAsPdf(html);
// CraftMyPDF - HTTP required
var client = new RestClient("https://api.craftmypdf.com/v1/create");
var request = new RestRequest(Method.POST);
request.AddHeader("X-API-KEY", "your-api-key");
var response = await client.ExecuteAsync(request);

// IronPDF - no HTTP
var pdf = renderer.RenderHtmlAsPdf(html);
$vbLabelText   $csharpLabel

Remove Rate Limiting Code

CraftMyPDF imposes API rate limits requiring retry logic. IronPDF has no limits:

// CraftMyPDF - needed to avoid 429 errors
await Task.Delay(100);
if (response.StatusCode == TooManyRequests) { /* retry */ }

// IronPDF - no limits, just generate
var pdf = renderer.RenderHtmlAsPdf(html);
// Remove all rate limit code!
// CraftMyPDF - needed to avoid 429 errors
await Task.Delay(100);
if (response.StatusCode == TooManyRequests) { /* retry */ }

// IronPDF - no limits, just generate
var pdf = renderer.RenderHtmlAsPdf(html);
// Remove all rate limit code!
$vbLabelText   $csharpLabel

Remove Webhook Handlers

CraftMyPDF uses async webhooks for PDF completion. IronPDF is synchronous—the PDF is ready immediately:

// CraftMyPDF - webhook callback required
// POST with webhook_url, wait for callback

// IronPDF - PDF ready immediately
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
// No callback needed!
// CraftMyPDF - webhook callback required
// POST with webhook_url, wait for callback

// IronPDF - PDF ready immediately
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
// No callback needed!
$vbLabelText   $csharpLabel

Sync by Default

Remove async/await patterns if they were only needed for HTTP calls:

// CraftMyPDF - async required
var response = await client.ExecuteAsync(request);

// IronPDF - sync by default (async available if needed)
var pdf = renderer.RenderHtmlAsPdf(html);
// CraftMyPDF - async required
var response = await client.ExecuteAsync(request);

// IronPDF - sync by default (async available if needed)
var pdf = renderer.RenderHtmlAsPdf(html);
$vbLabelText   $csharpLabel

Post-Migration Checklist

After completing the code migration, verify the following:

  • Run all PDF generation tests
  • Compare output quality (IronPDF's Chromium engine renders pixel-perfect)
  • Measure performance improvement (milliseconds vs. seconds)
  • Verify all templates converted correctly
  • Test batch processing without rate limits
  • Test in all target environments
  • Update CI/CD pipelines
  • Cancel CraftMyPDF subscription
  • Remove API key from secrets/config

Future-Proofing Your PDF Infrastructure

With .NET 10 on the horizon and C# 14 introducing new language features, choosing a local PDF library eliminates cloud API deprecation risks and version compatibility concerns. IronPDF's perpetual licensing model means your migration investment pays dividends indefinitely as projects extend into 2025 and 2026—without recurring subscription costs or data leaving your infrastructure.

Additional Resources


Migrating from CraftMyPDF to IronPDF eliminates cloud dependencies, network latency, per-PDF costs, and template lock-in while delivering pixel-perfect Chromium rendering that runs offline. The transition from REST API calls to local method invocations simplifies your codebase and keeps sensitive document data within your infrastructure.

Curtis Chau
Technical Writer

Curtis Chau holds a Bachelor’s degree in Computer Science (Carleton University) and specializes in front-end development with expertise in Node.js, TypeScript, JavaScript, and React. Passionate about crafting intuitive and aesthetically pleasing user interfaces, Curtis enjoys working with modern frameworks and creating well-structured, visually appealing manuals.

...

Read More