laravel maintained by pdfgate
PDFGate for Laravel
Laravel integration for the PDFGate API, built on the official PHP SDK.
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-curlandext-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.
- Set
PDFGATE_WEBHOOK_SECRETin.env. - In the dashboard, create a webhook pointing at
https://your-app.example/pdfgate/webhook. - 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.