signwell / signwell-sdk-php
PHP SDK for the SignWell API - electronic signature platform
Requires
- php: >=8.2
- ext-curl: *
- ext-json: *
- ext-mbstring: *
- guzzlehttp/guzzle: ^7.8
- guzzlehttp/psr7: ^2.6
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.64
- illuminate/support: ^10.0 || ^11.0 || ^12.0
- phpstan/phpstan: ^1.11 || ^2.0
- phpunit/phpunit: ^10.5 || ^11.0
- vlucas/phpdotenv: ^5.6
Suggests
- illuminate/support: Required only when using SignWell's optional Laravel service provider and facade.
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-09-18 03:18:56 UTC
README
PHP SDK for the SignWell API.
Install
composer require signwell/signwell-sdk-php
Requires PHP 8.2 or newer.
Quick Start
<?php require __DIR__ . '/vendor/autoload.php'; use SignWell\Sdk\Client; $signwell = Client::fromApiKey(getenv('SIGNWELL_API_KEY') ?: ''); $document = $signwell->createDocument([ 'test_mode' => true, 'name' => 'NDA', 'files' => [ ['name' => 'nda.pdf', 'file_url' => 'https://example.com/nda.pdf'], ], 'recipients' => [ ['id' => '1', 'name' => 'Jane Doe', 'email' => 'jane@example.com'], ], 'fields' => [ [ ['page' => 1, 'x' => 120, 'y' => 240, 'type' => 'signature', 'recipient_id' => '1'], ], ], ]);
Resources, Models, And Errors
use SignWell\Sdk\Errors; use SignWell\Sdk\Models; use SignWell\Sdk\Resources; $documents = new Resources\DocumentApi(); $request = new Models\DocumentRequest(['name' => 'NDA']); try { $documents->getDocument('document-id'); } catch (Errors\NotFoundError $error) { // Document was not found. } catch (Errors\RateLimitError $error) { // Retry after backing off. $rateLimit = $error->getRateLimit(); } catch (Errors\ApiError $error) { // Generic SDK error. }
HTTP 403 responses raise Errors\PermissionDeniedError, which remains compatible with Errors\ForbiddenError catches. Transport failures raise Errors\ApiConnectionError; Errors\TransportError is available as an additive alias. Local required-argument validation uses PHP's native \InvalidArgumentException.
Binary And JSON Response Modes
Some SignWell endpoints can return either binary files or JSON objects. The SDK selects the expected response type from the request flags.
$documents = $signwell->documents(); $pdf = $documents->getCompletedPdf('document-id'); // $pdf is an SplFileObject. $urlResponse = $documents->getCompletedPdf('document-id', url_only: true); // $urlResponse is a SignWell\Sdk\Models\CompletedPdfUrlResponse. $regional = $signwell->regional(); $certificate = $regional->getNom151Certificate('document-id', object_only: true);
getNom151Certificate rejects url_only: true and object_only: true together.
Convenience Workflows
Client provides thin wrappers for common API workflows while keeping the generated resources available when you need every option.
$account = $signwell->getMe(); $document = $signwell->createDocument([...]); $templateDocument = $signwell->createDocumentFromTemplate([...]); $sent = $signwell->sendDocument('draft-document-id', ['subject' => 'Please sign']); $signwell->sendReminder('document-id'); $template = $signwell->createTemplate([...]); $updatedTemplate = $signwell->updateTemplate('template-id', ['name' => 'Updated NDA']); $bulkSend = $signwell->createBulkSend([...]); $csvCheck = $signwell->validateBulkSendCsv([...]); $csvTemplate = $signwell->getBulkSendCsvTemplate(['template-id'], base64: true);
Embedded Helpers
use SignWell\Sdk\Client; $signwell = Client::fromApiKey(getenv('SIGNWELL_API_KEY') ?: ''); $document = $signwell->createSigningDocument([ 'name' => 'NDA', 'test_mode' => true, 'files' => [ ['name' => 'nda.pdf', 'file_url' => 'https://example.com/nda.pdf'], ], 'recipients' => [ ['name' => 'Jane Doe', 'email' => 'jane@example.com'], ], 'fields' => [ [ ['page' => 1, 'x' => 120, 'y' => 240, 'type' => 'signature'], ], ], ]); $signingUrl = $signwell->embeddedSigningUrl($document); $nonce = base64_encode(random_bytes(16)); $loader = $signwell->scriptTag($nonce); $script = $signwell->signingIframe([ 'url' => $signingUrl, 'nonce' => $nonce, 'events' => ['completed' => 'SignWellHandlers.completed'], ]);
Embedded signing documents must include fields for every recipient, set with_signature_page: true, or set text_tags: true. The helper validates this before calling the API.
Pass the same CSP nonce to scriptTag() and iframe helpers when your page uses nonce-based script-src.
The static SignWell\Sdk\Embedded helper remains available when you do not need a configured client object.
Webhook Verification
use SignWell\Sdk\Webhook; use SignWell\Sdk\Webhook\MemoryReplayStore; $payload = json_decode(file_get_contents('php://input'), true, flags: JSON_THROW_ON_ERROR); $event = $payload['event']; $webhookId = getenv('SIGNWELL_WEBHOOK_ID'); if (!is_string($webhookId) || $webhookId === '') { throw new RuntimeException('SIGNWELL_WEBHOOK_ID must be set.'); } Webhook::verifyEventOrThrow( event: $event, webhookId: $webhookId, toleranceSeconds: 300, ); $store = new MemoryReplayStore(); Webhook::verifyEventOnceOrThrow( event: $event, webhookId: $webhookId, replayStore: $store, toleranceSeconds: 300, );
Use verifyEventOnce or verifyEventOnceOrThrow with an application-provided atomic replay store for side-effecting webhook handlers. Replay stores should return false only for duplicate keys. The included memory store is for local development and single-process examples; when full, it evicts the oldest unexpired entry.
Laravel
The package auto-discovers SignWell\Sdk\Laravel\SignWellServiceProvider when installed in a Laravel app. Publish configuration:
php artisan vendor:publish --tag=signwell-config
Set SIGNWELL_API_KEY in your environment, then resolve APIs from the container:
$documents = app(SignWell\Sdk\Resources\DocumentApi::class); $document = $documents->getDocument('document-id');
The facade exposes configured resources and the same convenience helpers as the vanilla client:
$documents = SignWell::documents(); $document = SignWell::createSigningDocument([ 'name' => 'NDA', 'test_mode' => true, 'files' => [['name' => 'nda.pdf', 'file_url' => 'https://example.com/nda.pdf']], 'recipients' => [['name' => 'Jane Doe', 'email' => 'jane@example.com']], 'fields' => [[['page' => 1, 'x' => 120, 'y' => 240, 'type' => 'signature']]], ]);
Use SignWell\Sdk\Webhook directly for webhook signature verification.
Examples
The generated package includes runnable examples:
SIGNWELL_API_KEY=your_key php examples/vanilla_send_request.php SIGNWELL_API_KEY=your_key php examples/laravel_facade_send_request.php
These examples create test-mode signing requests. Set SIGNWELL_EXAMPLE_RECIPIENT_EMAIL and SIGNWELL_EXAMPLE_RECIPIENT_NAME to override the placeholder signer.
Documentation
Generated API and model references are in docs/.
License
MIT