푸터 콘텐츠로 바로가기
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

Aspect CraftMyPDF IronPDF
Data Location Cloud (your data leaves your system) On-premise (data never leaves)
Latency 1.5-30 seconds per PDF Milliseconds
Pricing Per-PDF subscription One-time perpetual license
Template System Proprietary drag-and-drop only Any HTML/CSS/JavaScript
Output Quality Print-optimized Pixel-perfect screen rendering
Works Offline No (requires internet) Yes
Compliance Data leaves organization SOC2/HIPAA friendly

Feature Comparison

Feature CraftMyPDF IronPDF
HTML to PDF Via API templates ✅ Native
URL to PDF Via API ✅ Native
Custom templates Proprietary editor only ✅ Any HTML
CSS3 support Limited ✅ Full
JavaScript rendering Limited ✅ Full
Merge/Split PDFs Via API ✅ Native
Watermarks Via 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

Change CraftMyPDF IronPDF Impact
Architecture Cloud REST API Local .NET library Remove HTTP calls
Templates Proprietary editor Standard HTML Convert templates to HTML
API Key Required for every call License at startup Remove API key handling
Async pattern Required (HTTP) Optional Remove await if preferred
Error handling HTTP status codes Exceptions Change try/catch patterns
Data binding JSON templates String interpolation Simplify 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

CraftMyPDF IronPDF
POST /v1/create renderer.RenderHtmlAsPdf(html)
X-API-KEY header License.LicenseKey = "..."
template_id Standard HTML string
{%name%} placeholders $"{name}" C# interpolation
POST /v1/merge PdfDocument.Merge(pdfs)
POST /v1/add-watermark pdf.ApplyWatermark(html)
Webhook callbacks Not needed
Rate limiting Not applicable

Configuration Mapping

CraftMyPDF Option IronPDF Equivalent
template_id HTML string
data JSON C# interpolation
page_size: "A4" PaperSize = PdfPaperSize.A4
orientation: "landscape" PaperOrientation = Landscape
margin_top: 20 MarginTop = 20
header HtmlHeader
footer HtmlFooter

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.

커티스 차우
기술 문서 작성자

커티스 차우는 칼턴 대학교에서 컴퓨터 과학 학사 학위를 취득했으며, Node.js, TypeScript, JavaScript, React를 전문으로 하는 프론트엔드 개발자입니다. 직관적이고 미적으로 뛰어난 사용자 인터페이스를 만드는 데 열정을 가진 그는 최신 프레임워크를 활용하고, 잘 구성되고 시각적으로 매력적인 매뉴얼을 제작하는 것을 즐깁니다.

커티스는 개발 분야 외에도 사물 인터넷(IoT)에 깊은 관심을 가지고 있으며, 하드웨어와 소프트웨어를 통합하는 혁신적인 방법을 연구합니다. 여가 시간에는 게임을 즐기거나 디스코드 봇을 만들면서 기술에 대한 애정과 창의성을 결합합니다.