Search by

pdfgate / pdfgate-sdk-php

pdfgate

Official PDFGate PHP SDK

v1.2.0 2026-09-09 10:06 UTC

This package is auto-updated.

Last update: 2026-09-09 10:08:28 UTC


README

Official PHP SDK for the PDFGate HTTP API.

CI Release

PDFGate lets you generate, process, and secure PDFs via a simple API:

  • HTML or URL to PDF
  • Fillable forms and adding form fields
  • Create signing envelopes from source documents
  • Embedded signing inside your own application
  • Store and reuse recipients across envelopes
  • Flatten (all or specific fields), compress, watermark, protect PDFs
  • Extract PDF form data
  • Delete stored documents
  • Manage and verify webhooks

🚀 SDK Documentation: https://pdfgate.github.io/pdfgate-sdk-php
🧭 API Reference: https://pdfgate.github.io/pdfgate-sdk-php/api/
📘 API Documentation: https://pdfgate.com/documentation
🔑 Dashboard & API keys: https://dashboard.pdfgate.com

Requirements

  • PHP 7.4+
  • ext-curl
  • ext-json

Installation

composer require pdfgate/pdfgate-sdk-php

Quick Start

<?php

use PdfGate\PdfGateClient;

$client = new PdfGateClient('live_your_api_key');

$generated = $client->generatePdf([
    'url' => 'https://example.com',
    'pageSizeType' => 'a4',
    'preSignedUrlExpiresIn' => 1200
]);

echo $generated->getFileUrl();

Usage Examples

Generate PDF

$client->generatePdf([
    'html' => '<h1>Hello</h1>',
    'pageSizeType' => 'a4',
    'metadata' => ['source' => 'sdk'],
]);

Upload PDF

$client->uploadFile([
    'file' => new \CURLFile('/absolute/path/source.pdf', 'application/pdf', 'source.pdf'),
    'preSignedUrlExpiresIn' => 1200,
]);

Create Envelope

Each recipient is given either as email and name or as the recipientId of a stored recipient (see Manage Recipients). Recipients marked embedded receive no email and get their signing links via createEmbedLink() after sending (see Embedded Signing).

use PdfGate\Enum\EnvelopeStatus;

$envelope = $client->createEnvelope([
    'requesterName' => 'John Doe',
    'documents' => [
        [
            'sourceDocumentId' => '6642381c5c61',
            'name' => 'Employment Agreement',
            'recipients' => [
                [
                    'email' => 'anna@example.com',
                    'name' => 'Anna Smith',
                ],
            ],
        ],
    ],
    'metadata' => ['customerId' => 'cus_123'],
]);

if ($envelope->getStatus() === EnvelopeStatus::CREATED) {
    echo $envelope->getId();
}

Send Envelope

use PdfGate\Enum\EnvelopeStatus;

$sentEnvelope = $client->sendEnvelope('69c0fa44f83ca6a7015f1c8c');

if ($sentEnvelope->getStatus() === EnvelopeStatus::IN_PROGRESS) {
    echo 'Envelope emails have been sent.';
}

Get Envelope

use PdfGate\Enum\EnvelopeStatus;

$envelope = $client->getEnvelope('69c0fa44f83ca6a7015f1c8c');

if ($envelope->getStatus() === EnvelopeStatus::IN_PROGRESS) {
    echo 'Envelope is still awaiting signatures.';
}

Void Envelope

Cancel an envelope in created or in_progress status. Recipients who have not signed are notified by email and their signing links stop working; documents already signed by all recipients are not affected. The optional reason is visible to recipients.

use PdfGate\Enum\EnvelopeStatus;

$voided = $client->voidEnvelope('69c0fa44f83ca6a7015f1c8c', 'Contract terms changed');

if ($voided->getStatus() === EnvelopeStatus::VOIDED) {
    echo 'Envelope has been voided.';
}

Delete Envelope

Permanently delete an envelope and the files it produced (signed documents and audit logs). Recipient data is anonymized and recipients lose access; source documents are not deleted. Only envelopes in draft, completed, expired, or voided status can be deleted — void an active envelope first.

$client->deleteEnvelope('69c0fa44f83ca6a7015f1c8c');

Embedded Signing

Embedded recipients sign inside your own application through an embed link and receive no emails from PDFGate. Create the envelope with an embedded recipient, send it, then create an embed link and render the returned URL in an iframe.

$envelope = $client->createEnvelope([
    'requesterName' => 'John Doe',
    'documents' => [
        [
            'sourceDocumentId' => '6642381c5c61',
            'name' => 'Employment Agreement',
            'recipients' => [
                [
                    'email' => 'anna@example.com',
                    'name' => 'Anna Smith',
                    'embedded' => true,
                ],
            ],
        ],
    ],
]);

$client->sendEnvelope($envelope->getId());

The envelope must be in in_progress status and the link expires after 10 minutes, so create it when the signer is ready — one link per signing session.

$embedLink = $client->createEmbedLink($envelope->getId(), [
    'documentId' => '6642381c5c61',
    'recipientId' => 'rcp_1a2b3c4d5e6f',
    'returnUrl' => 'https://example.com/signed',
]);

echo '<iframe src="' . htmlspecialchars($embedLink->getUrl()) . '"></iframe>';

When the session ends the iframe redirects to returnUrl with event (signing_complete, voided, expired or not_found), envelopeId, documentId and recipientId appended as query parameters; existing returnUrl query parameters are preserved.

Manage Recipients

Store recipients once and reference them from envelopes by recipientId. Emails are not unique — every createRecipient() call creates a new recipient — so list existing recipients first when reuse is intended.

// Email is stored lowercased and cannot be changed later.
$recipient = $client->createRecipient([
    'email' => 'anna@example.com',
    'name' => 'Anna Smith',
    'metadata' => ['customerId' => 'cus_123'],
]);

// Case-insensitive lookup, oldest first.
$recipients = $client->listRecipients('anna@example.com');

$fetched = $client->getRecipient($recipient->getId());

// Updates do not affect existing envelopes; they keep the recipient
// name they were created with.
$updated = $client->updateRecipient($recipient->getId(), [
    'name' => 'Anna Jones',
]);

Download File

$stream = $client->getFile($documentId);
$output = fopen('output.pdf', 'wb');
stream_copy_to_stream($stream, $output);
fclose($output);
fclose($stream);

Add Form Fields

use PdfGate\Enum\DocumentFieldType;

$doc = $client->addFormFields([
    'documentId' => $documentId,
    // Customize placeholder fields detected in the PDF, keyed by field name.
    'fieldOverrides' => [
        'signature' => ['role' => 'signer', 'optional' => false],
    ],
    // Or place fields at explicit positions on a given page.
    'fields' => [
        [
            'name' => 'signed_on',
            'type' => DocumentFieldType::DATE,
            'page' => 1,
            'x' => 100,
            'y' => 650,
            'width' => 160,
            'height' => 24,
        ],
    ],
]);

Flatten Specific Fields

$flattened = $client->flattenPdf([
    'documentId' => $documentId,
    // Omit fieldNames to flatten the whole document.
    'fieldNames' => ['signature', 'date'],
]);

Delete a Document

$client->deleteDocument($documentId);

Manage Webhooks

use PdfGate\Enum\WebhookEventType;

// The returned secret is shown only once — store it to verify payloads.
$webhook = $client->createWebhook([
    'url' => 'https://example.com/pdfgate-callback',
    'eventTypes' => [
        WebhookEventType::ENVELOPE_COMPLETED,
        WebhookEventType::ENVELOPE_SENT,
    ],
    'description' => 'Production signing events',
]);

$fetched = $client->getWebhook($webhook->getId());
$client->deleteWebhook($webhook->getId());

For complete operation examples (flattenPdf, addFormFields, compressPdf, protectPdf, watermarkPdf, extractPdfFormData, getDocument, deleteDocument, createEnvelope, sendEnvelope, getEnvelope, createEmbedLink, createRecipient, listRecipients, getRecipient, updateRecipient, createWebhook, getWebhook, deleteWebhook), see API.

To download generated files, enable Save files for one month in PDFGate Dashboard settings.

Error Handling

Non-2xx responses throw PdfGate\Exception\ApiException with:

  • getStatusCode()
  • getResponseBody() (truncated)

Transport and parsing failures throw PdfGate\Exception\TransportException and preserve original causes. Webhook verification failures throw PdfGate\Exception\SignatureVerificationException.

See Error handling guide for patterns and retry guidance.

Webhook Verification

Use WebhookSignatureVerifier to verify the x-pdfgate-signature header against the raw request body and your webhook secret.

use PdfGate\Exception\SignatureVerificationException;
use PdfGate\Webhook\WebhookSignatureVerifier;

$secret = 'whsecret_...';
$signatureHeader = $_SERVER['HTTP_X_PDFGATE_SIGNATURE'] ?? null;
$rawBody = file_get_contents('php://input');

try {
    WebhookSignatureVerifier::verify($secret, $signatureHeader, $rawBody === false ? '' : $rawBody);
    http_response_code(200);
} catch (SignatureVerificationException $e) {
    error_log($e->getMessage());
    http_response_code(400);
}

Development

This section is the source of truth for setup and test commands.

Local setup

composer install

Run tests

Unit tests:

composer run test:unit

Acceptance tests (real API calls):

PDFGATE_API_KEY=your_key composer run test:acceptance

Static analysis

composer run stan

Build documentation

Generate API docs (requires phpDocumentor in PATH, or PHPDOC_BIN):

composer run docs:api

Render the curated guides into the published site layout:

composer run docs:site

Validate markdown links:

composer run docs:check-links

Run both:

composer run docs:build

The combined docs site is generated into build/docs/site, with curated guides at the site root and API reference under build/docs/site/api. GitHub Pages publishes that combined artifact.

Generate the changelog manually

If you want to update CHANGELOG.md before or after making a release, run the generator manually. It reads commit subjects since the previous semver tag and updates CHANGELOG.md for the release version you provide.

Generate changelog content for a release version:

RELEASE_VERSION=1.2.3 php scripts/prepare-release.php

Preview the update without writing CHANGELOG.md:

DRY_RUN=1 RELEASE_VERSION=1.2.3 php scripts/prepare-release.php

If there are no updates since the previous release, the script generates a fallback Changed note instead of failing.