gigerit / laravel-swiss-post-postcard-api-client
This is my package laravel-swiss-post-postcard-api-client
Fund package maintenance!
gigerIT
Requires
- php: ^8.3
- illuminate/contracts: ^10.0||^11.0||^12.0
- saloonphp/saloon: ^3.0
- spatie/laravel-package-tools: ^1.16
Requires (Dev)
- larastan/larastan: ^2.9||^3.0
- laravel/pint: ^1.14
- nunomaduro/collision: ^8.1.1||^7.10.0
- orchestra/testbench: ^10.6
- pestphp/pest: ^2.0||^3.0
- pestphp/pest-plugin-arch: ^2.5||^3.0
- pestphp/pest-plugin-laravel: ^2.0||^3.0
- phpstan/extension-installer: ^1.3
- phpstan/phpstan-deprecation-rules: ^1.1||^2.0
- phpstan/phpstan-phpunit: ^1.3||^2.0
This package is auto-updated.
Last update: 2025-09-01 14:08:21 UTC
README
A Laravel package for sending physical postcards through the Swiss Post Postcard API. This package provides a complete, type-safe wrapper around the Swiss Post Postcard API, allowing you to programmatically send real postcards with images, addresses, branding, and QR codes.
Features:
- π Complete API coverage for all Swiss Post Postcard endpoints
- π OAuth2 authentication with automatic token management
- β Client-side validation for addresses, text, and image dimensions
- π¨ Support for branding (text, images, QR codes, custom stamps)
- π§ Type-safe DTOs for all request and response data
- π‘οΈ Comprehensive error handling with descriptive error codes
- π± Laravel facades and dependency injection support
- π§ͺ Built with Saloon HTTP client and OAuth2 for robust API communication
Requirements
- PHP 8.3 or higher
- Laravel 10.0, 11.0, or 12.0
- Swiss Post Postcard API credentials (obtained through contract with Swiss Post)
Installation
Install the package via Composer:
composer require gigerit/laravel-swiss-post-postcard-api-client
Publish the configuration file:
php artisan vendor:publish --tag="swiss-post-postcard-api-client-config"
Configuration
Add your Swiss Post API credentials to your .env
file:
SWISS_POST_POSTCARD_API_CLIENT_ID=your_client_id SWISS_POST_POSTCARD_API_CLIENT_SECRET=your_client_secret SWISS_POST_POSTCARD_API_DEFAULT_CAMPAIGN=your_campaign_uuid
Note: The URLs shown above are for the integration environment. Swiss Post will provide you with production URLs and credentials upon contract signing.
Quick Start
Using Dependency Injection
use Gigerit\PostcardApi\PostcardApi; use Gigerit\PostcardApi\DTOs\Address\RecipientAddress; class PostcardController extends Controller { public function __construct(private PostcardApi $postcardApi) {} public function sendPostcard() { // Create recipient address $recipient = new RecipientAddress( street: 'Musterstrasse', zip: '8000', city: 'ZΓΌrich', country: 'CH', firstname: 'John', lastname: 'Doe', houseNr: '123' ); // Send postcard $result = $this->postcardApi->postcards()->createComplete( recipientAddress: $recipient, imagePath: storage_path('postcards/my-image.jpg'), senderText: 'Hello from Laravel!' ); return response()->json(['cardKey' => $result->cardKey]); } }
Using Facades
use Gigerit\PostcardApi\Facades\PostcardApi; use Gigerit\PostcardApi\DTOs\Address\RecipientAddress; // Check campaign quota $stats = PostcardApi::campaigns()->getDefaultCampaignStatistics(); if ($stats->freeToSendPostcards === 0) { throw new Exception('No postcards remaining in campaign'); } // Create and send postcard $recipient = new RecipientAddress(/* ... */); $result = PostcardApi::postcards()->createComplete( recipientAddress: $recipient, imagePath: 'path/to/image.jpg' );
Manual Instantiation
use Gigerit\PostcardApi\PostcardApi; use Gigerit\PostcardApi\Connectors\SwissPostConnector; // Auto-authenticate using configured OAuth2 credentials $api = new PostcardApi(); // Or provide specific access token $api = new PostcardApi('your_access_token_here'); // Using Saloon's OAuth2 directly $connector = new SwissPostConnector(); $authenticator = $connector->getAccessToken(); // Uses client credentials grant $connector->authenticate($authenticator);
Core Concepts
Postcard Workflow
- Check quota - Verify campaign has remaining postcards
- Create postcard - Initialize with recipient address
- Upload content - Add image, sender text, addresses
- Add branding - Optional logos, QR codes, custom stamps
- Approve - Submit for printing and sending
Image Requirements
Type | Dimensions | Format | Purpose |
---|---|---|---|
Front Image | 1819Γ1311 px | JPEG/PNG | Main postcard image |
Branding Image | 777Γ295 px | JPEG/PNG | Company branding |
Stamp | 343Γ248 px | JPEG/PNG | Custom stamp |
All images should be RGB color mode at 300 DPI for optimal print quality.
Address Validation
The package validates addresses according to Swiss Post requirements:
- Required fields: street, ZIP, city, country (for recipients)
- Name requirements: firstname/lastname OR company name
- Text length limits enforced
- Character encoding validation (CP850 compatibility)
API Services
The package is organized into three main services:
PostcardService
$postcards = $api->postcards(); // Create postcards $result = $postcards->create($campaignKey, $postcard); $result = $postcards->createComplete($recipient, $imagePath, $sender, $text); // Upload content $postcards->uploadImage($cardKey, $imagePath); $postcards->uploadSenderText($cardKey, $text); $postcards->uploadSenderAddress($cardKey, $senderAddress); $postcards->uploadRecipientAddress($cardKey, $recipientAddress); // Manage postcards $postcards->approve($cardKey); $state = $postcards->getState($cardKey); $frontPreview = $postcards->getPreviewFront($cardKey); $backPreview = $postcards->getPreviewBack($cardKey);
BrandingService
$branding = $api->branding(); // Text branding $branding->addSimpleText($cardKey, 'Your Company', '#FF0000', '#FFFFFF'); // QR code branding $branding->addSimpleQRCode($cardKey, 'https://yoursite.com', 'Visit us!'); // Image branding $branding->uploadImage($cardKey, 'path/to/logo.jpg'); $branding->uploadStamp($cardKey, 'path/to/stamp.jpg');
CampaignService
$campaigns = $api->campaigns(); // Get statistics $stats = $campaigns->getDefaultCampaignStatistics(); $stats = $campaigns->getStatistics($campaignKey); // Check quota $hasQuota = $campaigns->hasRemainingQuota($campaignKey); $remaining = $campaigns->getRemainingQuota($campaignKey);
Error Handling
The package provides comprehensive error handling:
use Gigerit\PostcardApi\Exceptions\SwissPostApiException; use Gigerit\PostcardApi\Enums\ErrorCode; try { $result = $api->postcards()->create(); // Check for warnings if ($result->hasWarnings()) { foreach ($result->getWarningMessages() as $warning) { Log::warning("Postcard warning: {$warning}"); } } } catch (SwissPostApiException $e) { // API errors (quota exceeded, invalid data, etc.) Log::error("Swiss Post API error: {$e->getMessage()}"); } catch (\InvalidArgumentException $e) { // Validation errors (invalid image dimensions, text too long, etc.) Log::error("Validation error: {$e->getMessage()}"); } // Error codes are available as enums $errorCode = ErrorCode::CAMPAIGN_QUOTA_EXCEEDED; echo $errorCode->getDescription(); // "Campaign quota exceeded"
Validation
Client-side validation helps catch errors before API calls:
use Gigerit\PostcardApi\Validation\PostcardValidator; use Gigerit\PostcardApi\Enums\ImageDimensions; // Validate addresses $errors = PostcardValidator::validateRecipientAddress($recipient); // Validate text $errors = PostcardValidator::validateSenderText($text); // Validate images $errors = PostcardValidator::validateImageDimensions( '/path/to/image.jpg', ImageDimensions::FRONT_IMAGE ); // Disable validation if needed $api->postcards()->uploadImage($cardKey, $path, null, false); // Skip validation
Advanced Usage
For more detailed examples and advanced usage patterns, see USAGE_EXAMPLES.md.
Testing
composer test
Changelog
Please see CHANGELOG for more information on what has changed recently.
Contributing
Please see CONTRIBUTING for details.
Security Vulnerabilities
Please review our security policy on how to report security vulnerabilities.
Credits
License
The MIT License (MIT). Please see License File for more information.