DocuHook

Guides · Convert WooCommerce webhook to PDF invoice

Convert a WooCommerce Webhook to a PDF Invoice

2026-10-19 · 7 min read

Searching for convert WooCommerce webhook to PDF invoice usually means you already have order.completed firing — and you need a printable invoice without standing up a separate PDF microservice.

This guide wires WooCommerce → WordPress → DocuHook so each paid order becomes PDF-ready HTML in one function call.

Architecture

  1. WooCommerce emits order.completed (or you hook woocommerce_order_status_completed).
  2. Your theme/plugin builds a small JSON payload from the order.
  3. DocuHook merges that JSON into your invoice HTML template.
  4. You email, store, or stream the result as a PDF (browser print / html2pdf / your mailer attachment pipeline).

1. Install the DocuHook WordPress plugin

  1. Download docuhook.zip
  2. WP Admin → Plugins → Add New → Upload Plugin
  3. Activate → Settings → DocuHook
  4. API URL https://docuhook.com + API key from your account

Helper available in PHP: docuhook_render( $data, $html, $args ).

2. Invoice HTML template

Store this as an option, theme file, or constant. Tokens match nested JSON paths:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
  body { font-family: system-ui, sans-serif; margin: 36px; color: #111; }
  h1 { font-size: 22px; }
  table { width: 100%; border-collapse: collapse; margin-top: 20px; }
  th, td { text-align: left; padding: 8px 0; border-bottom: 1px solid #ddd; font-size: 14px; }
</style>
</head>
<body>
  <h1>Invoice {{order.number}}</h1>
  <p>{{billing.name}} · {{billing.email}}</p>
  <p>Date: {{order.date}} · Total: {{order.currency}} {{order.total}}</p>
  <table>
    <thead><tr><th>Item</th><th>Qty</th><th>Total</th></tr></thead>
    <tbody>
      <tr>
        <td>{{line_items.0.name}}</td>
        <td>{{line_items.0.quantity}}</td>
        <td>{{order.currency}} {{line_items.0.total}}</td>
      </tr>
    </tbody>
  </table>
</body>
</html>

For multi-line orders, either generate rows in PHP before merge, or map the first N lines into line_items.0, line_items.1, …

3. Hook order completion

Drop this in a small custom plugin or your theme’s functions.php (prefer a plugin):

add_action( 'woocommerce_order_status_completed', 'my_docuhook_invoice_on_complete', 20, 1 );

function my_docuhook_invoice_on_complete( $order_id ) {
    if ( ! function_exists( 'docuhook_render' ) || ! function_exists( 'wc_get_order' ) ) {
        return;
    }

    $order = wc_get_order( $order_id );
    if ( ! $order ) {
        return;
    }

    $items = [];
    foreach ( $order->get_items() as $item ) {
        $items[] = [
            'name'     => $item->get_name(),
            'quantity' => $item->get_quantity(),
            'total'    => $item->get_total(),
        ];
    }

    $data = [
        'order' => [
            'number'   => $order->get_order_number(),
            'date'     => $order->get_date_created() ? $order->get_date_created()->date( 'Y-m-d' ) : '',
            'total'    => $order->get_total(),
            'currency' => $order->get_currency(),
        ],
        'billing' => [
            'name'  => trim( $order->get_billing_first_name() . ' ' . $order->get_billing_last_name() ),
            'email' => $order->get_billing_email(),
        ],
        'line_items' => $items,
    ];

    $html = file_get_contents( WP_CONTENT_DIR . '/uploads/invoice-template.html' );
    if ( $html === false ) {
        return;
    }

    $result = docuhook_render( $data, $html, [
        'mode'     => 'async', // webhook-friendly: returns 202 job
        'filename' => 'invoice-' . $order->get_order_number() . '.pdf',
    ] );

    if ( ! empty( $result['job_id'] ) ) {
        update_post_meta( $order_id, '_docuhook_job_id', $result['job_id'] );
    }
}

Use mode => sync when you need the HTML in the same request (interactive admin actions). Prefer async for storefront webhooks so WooCommerce is not held open.

4. Optional: pure webhook URL

Point a WooCommerce webhook at DocuHook’s hook endpoint if you already wrap the payload:

POST https://docuhook.com/api/v1/hooks/render
Authorization: Bearer dh_...
Content-Type: application/json

{
  "mode": "async",
  "data": { "...order fields..." },
  "html": "<h1>Invoice {{order.number}}</h1>",
  "filename": "invoice.pdf"
}

Returns 202 with job_id, status_url, and result_url.

Checklist

  • API key saved under Settings → DocuHook
  • Template file readable by PHP
  • Test with a completed order in staging
  • Poll docuhook_job_result( $job_id ) if you need the HTML later (email, download link)

The 3-line fix

Once the plugin is configured, converting a WooCommerce order payload into a PDF-ready invoice is:

$result = docuhook_render( $order_data, $invoice_html, [ 'filename' => 'invoice.pdf' ] );
// ~200ms sync merge — or pass mode => 'async' for webhook bursts
$html = $result['html'] ?? null;

Get started: download the plugin · register for an API key.