Looking to hire Laravel developers? Try LaraJobs

laravel maintained by pdfgate

Description
Laravel integration for the PDFGate API: HTML to PDF, PDF forms, e-signature envelopes and signed webhooks.
Author
Last update
2026/10/28 09:08 (dev-main)
License
Downloads
0

Comments
comments powered by Disqus

PDFGate for Laravel

Laravel integration for the PDFGate API, built on the official PHP SDK.

CI Latest Version License

PDFGate lets you generate, process and sign PDFs from your Laravel app:

  • HTML or URL to PDF
  • Fillable forms and adding form fields
  • Create signing envelopes from source documents
  • Embedded signing inside your own application
  • Flatten, compress, watermark and protect PDFs
  • Extract PDF form data
  • Receive signed webhook events as Laravel events

📘 API Documentation: https://pdfgate.com/documentation 🔑 Dashboard & API keys: https://dashboard.pdfgate.com

Requirements

  • PHP 8.2 or newer
  • Laravel 12 or 13
  • ext-curl and ext-json

Installation

composer require pdfgate/laravel

The service provider and the PdfGate facade are registered automatically.

Add your API key to .env. Keys that start with live_ call the production API and keys that start with test_ call the sandbox API.

PDFGATE_API_KEY=test_your_api_key
PDFGATE_WEBHOOK_SECRET=your_webhook_secret

To change the defaults, publish the config file:

php artisan vendor:publish --tag=pdfgate-config

Usage

Every method of the SDK's PdfGateClient is available on the PdfGate facade. See the API documentation for the full list of endpoints and request options.

Generate a PDF

use PdfGate\Laravel\Facades\PdfGate;

$document = PdfGate::generatePdf([
    'html' => view('invoices.show', ['invoice' => $invoice])->render(),
    'pageSizeType' => 'a4',
    'preSignedUrlExpiresIn' => 1200,
]);

$document->getId();
$document->getFileUrl();

Send a PDF to the browser

// Download
return PdfGate::download($document->getId(), 'invoice.pdf');

// Show inline in the browser's PDF viewer
return PdfGate::inline($document->getId(), 'invoice.pdf');

Store a PDF on a disk

PdfGate::store($document->getId(), 'invoices/' . $invoice->id . '.pdf', 's3');

The third argument is the disk name from config/filesystems.php. Leave it out to use the default disk.

Create and send a signing envelope

$envelope = PdfGate::createEnvelope([
    'requesterName' => 'Acme Inc.',
    'documents' => [
        [
            'sourceDocumentId' => $document->getId(),
            'name' => 'Service Agreement',
            'recipients' => [
                ['email' => 'anna@example.com', 'name' => 'Anna Smith'],
            ],
        ],
    ],
    'metadata' => ['orderId' => $order->id],
]);

PdfGate::sendEnvelope($envelope->getId());

Dependency injection

The SDK client is bound as a singleton, so you can inject it instead of using the facade:

use PdfGate\PdfGateClient;

public function __construct(private PdfGateClient $pdfGate)
{
}

Inject PdfGate\Laravel\PdfGateManager when you also want the download(), inline() and store() helpers.

Webhooks

The package registers POST /pdfgate/webhook. Every request is checked against your webhook secret using the x-pdfgate-signature header. Requests with a missing, wrong or expired signature are rejected with a 403 before any event is dispatched.

  1. Set PDFGATE_WEBHOOK_SECRET in .env.
  2. In the dashboard, create a webhook pointing at https://your-app.example/pdfgate/webhook.
  3. Listen for the events below.

Events

A verified delivery dispatches PdfGate\Laravel\Events\WebhookReceived and, when the event type is known, one typed event:

Webhook event Laravel event
envelope.sent EnvelopeSent
envelope.completed EnvelopeCompleted
envelope.expired EnvelopeExpired
envelope.voided EnvelopeVoided
envelope.deleted EnvelopeDeleted
envelope.recipient.signed EnvelopeRecipientSigned
envelope.recipient.activated EnvelopeRecipientActivated
envelope.document.completed EnvelopeDocumentCompleted

All event classes live in PdfGate\Laravel\Events and carry two properties. $webhook is the name of the endpoint that received the delivery, default unless you registered more (see below). $payload holds:

Property Description
eventId Unique ID of the delivery. Use it to skip duplicates.
type Event type, for example envelope.completed.
timestamp When the event occurred, ISO 8601.
resourceKind, resourceId The resource the event refers to.
data Event data. Its shape depends on the event type, see the webhook docs.
toArray() The full decoded request body.

Laravel discovers listeners by their type-hinted event class:

namespace App\Listeners;

use PdfGate\Laravel\Events\EnvelopeCompleted;
use PdfGate\Laravel\Facades\PdfGate;

class ArchiveSignedAgreement
{
    public function handle(EnvelopeCompleted $event): void
    {
        $envelope = $event->payload->data['envelope'];

        foreach ($envelope['documents'] as $document) {
            PdfGate::store($document['signedDocumentId'], 'agreements/' . $document['signedDocumentId'] . '.pdf');
        }
    }
}

Deliveries can be retried and arrive out of order. Fetch the current state with PdfGate::getEnvelope() before acting on it when ordering matters.

Your own routes and several webhooks

Each webhook you create in the dashboard has its own signing secret. To use a different path, or to receive more than one webhook, publish the config, turn the automatic route off and declare the endpoints yourself with the Route::pdfgateWebhook() macro.

// config/pdfgate.php
'webhook' => [
    'auto_route' => false,
    'secrets' => [
        'default' => env('PDFGATE_WEBHOOK_SECRET'),
        'billing' => env('PDFGATE_BILLING_WEBHOOK_SECRET'),
    ],
],
// routes/web.php
Route::pdfgateWebhook('hooks/pdfgate');                   // verified with the "default" secret
Route::pdfgateWebhook('hooks/pdfgate-billing', 'billing'); // verified with the "billing" secret

The macro registers the controller with the signature middleware for that name, names the route pdfgate.webhook.{name}, and excludes Laravel's CSRF middleware so the route can live inside the web group. Events dispatched from the second endpoint have $event->webhook === 'billing'.

Testing your application

Bind a client with a fake transport so your tests never reach the API:

use PdfGate\Http\HttpTransportInterface;
use PdfGate\PdfGateClient;

$this->app->instance(
    PdfGateClient::class,
    PdfGateClient::createWithTransport('test_key', $fakeTransport)
);

$fakeTransport is any class implementing HttpTransportInterface. To test webhook listeners, use Event::fake() and dispatch the event class with a WebhookPayload built from WebhookPayload::fromArray().

Contributing

composer install
composer check

composer check validates composer.json, runs PHPStan and the test suite.

License

MIT. See LICENSE.