Render Blade templates to PDF via one Http call. Full Chromium. Queue-friendly.
Generate PDFs from Blade templates in Laravel 10+ with nothing more than the Http facade. No Dompdf CSS limitations, no wkhtmltopdf binary on the server, no Snappy configuration. Just render your view, POST to the API, return a download response. Works identically on Forge, Vapor, Envoyer, Laravel Cloud, or your own VPS.
<?php
namespace App\Http\Controllers;
use Illuminate\Support\Facades\Http;
class InvoicePdfController extends Controller
{
public function show(int $id)
{
$invoice = Invoice::findOrFail($id);
$html = view("invoices.pdf", compact("invoice"))->render();
$res = Http::withHeaders([
"X-API-Key" => config("services.html2dochub.key"),
])->post("https://api.html2dochub.com/v1/render", [
"type" => "pdf",
"html" => $html,
"options" => ["format" => "A4", "margin" => "18mm"],
])->throw()->json();
$pdf = Http::get($res["download_url"])->body();
return response($pdf, 200, [
"Content-Type" => "application/pdf",
"Content-Disposition" => 'attachment; filename="invoice-' . $id . '.pdf"',
]);
}
}// config/services.php
return [
// ...
"html2dochub" => [
"key" => env("HTML2DOCHUB_API_KEY"),
],
];
// .env
HTML2DOCHUB_API_KEY=sk_live_YOUR_KEY<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Http;
class GenerateReportPdf implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public int $tries = 3;
public int $backoff = 30;
public function __construct(public int $reportId) {}
public function handle(): void
{
$report = Report::findOrFail($this->reportId);
$html = view("reports.pdf", compact("report"))->render();
$res = Http::withHeaders(["X-API-Key" => config("services.html2dochub.key")])
->timeout(30)
->post("https://api.html2dochub.com/v1/render", [
"type" => "pdf",
"mode" => "async",
"html" => $html,
"webhook_url" => route("webhooks.pdf_ready"),
"tag" => "report:" . $this->reportId,
"idempotency_key" => "report-" . $this->reportId . "-v" . $report->version,
])
->throw()
->json();
$report->update(["html2dochub_job_id" => $res["id"]]);
}
}<?php
// routes/web.php
Route::post("/webhooks/pdf-ready", [PdfWebhookController::class, "handle"])
->withoutMiddleware([\Illuminate\Foundation\Http\Middleware\VerifyCsrfToken::class])
->name("webhooks.pdf_ready");
// app/Http/Controllers/PdfWebhookController.php
public function handle(Request $request)
{
$payload = $request->all();
if ($payload["status"] !== "completed") {
return response()->noContent();
}
$report = Report::where("html2dochub_job_id", $payload["id"])->firstOrFail();
$pdfBytes = Http::get($payload["download_url"])->body();
Storage::disk("s3")->put("reports/{$report->id}.pdf", $pdfBytes);
$report->update(["status" => "ready"]);
return response()->noContent();
}Pay only for pages rendered. No subscriptions. No minimum monthly fee.
Free account. No credit card required. API ready in minutes.
Get your free API key