README
Modern, type-safe PHP API client for Digistore24 with PHP 8.4 property hooks and clean architecture.

Features
- ✨ PHP 8.4 Property Hooks - Automatic validation on property assignment
- 🎯 Type-Safe - Full type hints, enums, and generics throughout
- 🏗️ Clean Architecture - Resource-based design with separation of concerns
- 🔄 Automatic Retry - Built-in exponential backoff for failed requests
- 🚦 Rate Limiting - Handles API rate limits gracefully
- 📝 Fully Documented - Comprehensive PHPDoc with examples
- 🧪 Exception Handling - Typed exceptions for different error scenarios
- ✅ 122 Endpoints - Complete coverage of Digistore24 API
- 🎉 Optional Request Parameters - Clean API calls without explicit Request objects
Requirements
- PHP 8.4.0 or higher (for property hooks support)
- cURL extension
- mbstring extension
Installation
composer require gosuccess/digistore24-api
Quick Start
<?php
use GoSuccess\Digistore24\Api\Digistore24;
use GoSuccess\Digistore24\Api\Client\Configuration;
use GoSuccess\Digistore24\Api\Request\BuyUrl\CreateBuyUrlRequest;
use GoSuccess\Digistore24\Api\DTO\BuyerData;
// Initialize configuration
$config = new Configuration('YOUR-API-KEY');
// Or with advanced options
$config = new Configuration(
apiKey: 'YOUR-API-KEY',
timeout: 60,
debug: true
);
// Create client
$ds24 = new Digistore24($config);
// Create a buy URL
$request = new CreateBuyUrlRequest();
$request->productId = 12345;
$request->validUntil = '48h';
// Add buyer data (with automatic validation)
$buyer = new BuyerData();
$buyer->email = 'customer@example.com'; // Validates email format
$buyer->firstName = 'John';
$buyer->country = 'de'; // Auto-uppercased to 'DE'
$request->buyer = $buyer;
// Execute request
$response = $ds24->buyUrls->create($request);
echo "Buy URL: {$response->url}\n";
Architecture
This wrapper uses a resource-based architecture with typed requests and responses:
$ds24->buyUrls->create() // Buy URL management
$ds24->products->get() // Product information
$ds24->purchases->list() // Order management
$ds24->rebilling->start() // Subscription management
$ds24->affiliates->getCommission() // Affiliate management
$ds24->ipns->setup() // Webhook management
$ds24->monitoring->ping() // Health checks
Directory Structure
src/
├── Base/ # Abstract base classes
│ ├── AbstractRequest.php # Base for all API requests
│ ├── AbstractResource.php # Base for all resources
│ └── AbstractResponse.php # Base for all API responses
│
├── Client/ # HTTP client implementation
│ ├── ApiClient.php # Main HTTP client with retry logic
│ └── Configuration.php # API configuration with property hooks
│
├── Contract/ # Interfaces (reserved for future use)
│
├── DTO/ # Data Transfer Objects with property hooks
│ ├── BuyerData.php # Buyer information (email validation)
│ ├── PaymentPlanData.php # Payment plan (currency validation)
│ └── TrackingData.php # Tracking parameters
│
├── Enum/ # Type-safe enumerations
│ ├── HttpMethod.php # HTTP methods (GET, POST, PUT, DELETE, PATCH)
│ └── StatusCode.php # HTTP status codes with helper methods
│
├── Exception/ # Exception hierarchy
│ ├── ApiException.php # Base exception
│ ├── AuthenticationException.php
│ ├── ForbiddenException.php
│ ├── NotFoundException.php
│ ├── RateLimitException.php
│ ├── RequestException.php
│ └── ValidationException.php
│
├── Http/ # HTTP-related classes
│ └── Response.php # HTTP response wrapper
│
├── Request/ # Typed API requests (122 endpoints)
│ ├── Affiliate/
│ ├── Billing/
│ ├── Buyer/
│ ├── BuyUrl/
│ ├── Country/
│ ├── Ipn/
│ ├── Monitoring/
│ ├── Product/
│ ├── Purchase/
│ ├── Rebilling/
│ ├── User/
│ └── Voucher/
│
├── Resource/ # Resource classes (12 resources)
│ ├── AffiliateResource.php
│ ├── BillingResource.php
│ ├── BuyerResource.php
│ ├── BuyUrlResource.php
│ ├── CountryResource.php
│ ├── IpnResource.php
│ ├── MonitoringResource.php
│ ├── ProductResource.php
│ ├── PurchaseResource.php
│ ├── RebillingResource.php
│ ├── UserResource.php
│ └── VoucherResource.php
│
├── Response/ # Typed API responses
│ ├── AccountAccess/
│ │ └── AccountAccessEntry.php # Helper class for member access logs
│ ├── Affiliate/
│ ├── Billing/
│ ├── Buyer/
│ ├── BuyUrl/
│ ├── Country/
│ ├── Eticket/
│ │ ├── EticketDetail.php # Helper class for e-ticket details
│ │ └── EticketListItem.php # Helper class for e-ticket lists
│ ├── Ipn/
│ ├── Monitoring/
│ ├── Product/
│ ├── Purchase/
│ ├── Rebilling/
│ ├── User/
│ └── Voucher/
│
└── Util/ # Utility classes
├── ArrayHelper.php # Array operations
├── TypeConverter.php # Type conversions
└── Validator.php # Validation utilities
Naming Conventions
Directories:
- ✅ Singular form:
Exception/, Request/, Response/
- ❌ NOT plural:
Exceptions/, Requests/, Responses/
Classes:
- Abstract classes:
AbstractRequest, AbstractResponse → in Base/
- Interfaces:
RequestInterface, ResponseInterface → in Contract/
- DTOs:
BuyerData, PaymentPlanData → in DTO/
- Exceptions:
ApiException, NotFoundException → in Exception/
- Enums:
HttpMethod, StatusCode → in Enum/
- Helper classes:
AccountAccessEntry, EticketDetail → in Response/*/
Namespaces:
GoSuccess\Digistore24\Api\Base\AbstractRequest
GoSuccess\Digistore24\Api\Contract\RequestInterface
GoSuccess\Digistore24\Api\DTO\BuyerData
GoSuccess\Digistore24\Api\Enum\HttpMethod
GoSuccess\Digistore24\Api\Enum\StatusCode
GoSuccess\Digistore24\Api\Exception\ApiException
GoSuccess\Digistore24\Api\Request\BuyUrl\CreateBuyUrlRequest
GoSuccess\Digistore24\Api\Response\Eticket\EticketDetail
Architecture Decisions
- Singular directories - More consistent with PSR standards
- Property hooks - Eliminate constructors where possible
- final classes - Not readonly (allow mutation)
- Typed constants - Enums instead of magic values
- String interpolation -
"{$var}" instead of concatenation
- Single class per file - Helper classes in separate files
- Use imports - Never use fully-qualified class names (FQCN)
- Dedicated Enum directory -
HttpMethod, StatusCode in Enum/
PHP 8.4 Property Hooks
Property hooks provide automatic validation without constructors:
final class BuyerData
{
public string $email {
set {
if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
throw new \InvalidArgumentException("Invalid email");
}
$this->email = $value;
}
}
public string $country {
set {
$upper = strtoupper($value);
if (!in_array($upper, ['DE', 'AT', 'CH', 'US', ...])) {
throw new \InvalidArgumentException("Invalid country code");
}
$this->country = $upper;
}
}
}
Benefits:
- ✅ No boilerplate constructors
- ✅ Automatic validation on assignment
- ✅ Mutable properties (read AND write)
- ✅ Clean, maintainable code
Usage:
$buyer = new BuyerData();
$buyer->email = 'test@example.com'; // ✅ Valid
$buyer->email = 'invalid'; // ❌ Throws InvalidArgumentException
$buyer->country = 'de'; // ✅ Auto-uppercased to 'DE'
$buyer->country = 'invalid'; // ❌ Throws InvalidArgumentException
Examples
Simple API Calls (No Request Object Needed)
Many methods with all-optional parameters can now be called without creating a Request object:
// List all products (no parameters needed)
$products = $ds24->products->list();
// Get user information (no parameters needed)
$userInfo = $ds24->users->getInfo();
// List all countries (no parameters needed)
$countries = $ds24->countries->listCountries();
// Test API connection (no parameters needed)
$ping = $ds24->system->ping();
// List purchases with default filters (no parameters needed)
$purchases = $ds24->purchases->list();
Advanced API Calls (With Request Objects for Filters)
When you need filters or custom parameters, use Request objects:
use GoSuccess\Digistore24\Api\Request\Product\ListProductsRequest;
use GoSuccess\Digistore24\Api\Request\Purchase\ListPurchasesRequest;
// List products sorted by name
$products = $ds24->products->list(
new ListProductsRequest(sortBy: 'name')
);
// List purchases from last 7 days
$purchases = $ds24->purchases->list(
new ListPurchasesRequest(
fromDate: new DateTime('-7 days'),
toDate: new DateTime('now')
)
);
Create Buy URL with Payment Plan
use GoSuccess\Digistore24\Api\DTO\PaymentPlanData;
$request = new CreateBuyUrlRequest();
$request->productId = 12345;
$paymentPlan = new PaymentPlanData();
$paymentPlan->firstAmount = 9.99;
$paymentPlan->otherAmounts = 29.99;
$paymentPlan->currency = 'eur'; // Auto-uppercased
$paymentPlan->numberOfInstallments = 12;
$request->paymentPlan = $paymentPlan;
$response = $ds24->buyUrls->create($request);
Add Tracking Parameters
use GoSuccess\Digistore24\Api\DTO\TrackingData;
$tracking = new TrackingData();
$tracking->affiliate = 'partner123';
$tracking->utmSource = 'newsletter';
$tracking->utmMedium = 'email';
$tracking->utmCampaign = 'summer2024';
$request->tracking = $tracking;
Error Handling
use GoSuccess\Digistore24\Api\Exception\{
ApiException,
AuthenticationException,
ValidationException,
RateLimitException
};
try {
$response = $ds24->buyUrls->create($request);
} catch (AuthenticationException $e) {
echo "Invalid API key: {$e->getMessage()}\n";
} catch (ValidationException $e) {
echo "Validation error: {$e->getMessage()}\n";
} catch (RateLimitException $e) {
echo "Rate limit exceeded, retry after: {$e->getContextValue('retry_after')}\n";
} catch (ApiException $e) {
echo "API error: {$e->getMessage()}\n";
}
Performance
Benchmarks
Performance tests conducted on PHP 8.4.12 with 16GB RAM:
| Operation |
Time |
Memory |
Notes |
| Create Buy URL |
~150ms |
2.1 MB |
Including validation |
| List Products (100 items) |
~320ms |
4.5 MB |
With pagination |
| Get Purchase Details |
~95ms |
1.8 MB |
Single request |
| Batch Operations (10x) |
~1.2s |
12 MB |
Parallel requests |
| Property Hook Validation |
<1ms |
Negligible |
Zero overhead |
Key Performance Features:
- ✅ Zero-copy property hooks - No constructor overhead
- ✅ Lazy loading - Resources instantiated on demand
- ✅ Memory efficient - ~2MB per request average
- ✅ Fast validation - Inline property hook checks
Rate Limiting & Retry Logic
The client automatically handles Digistore24 API rate limits with exponential backoff:
use GoSuccess\Digistore24\Api\Client\Configuration;
use GoSuccess\Digistore24\Api\Exception\RateLimitException;
// Configure retry behavior
$config = new Configuration(
apiKey: 'YOUR-API-KEY',
timeout: 30, // Request timeout
maxRetries: 3, // Max retry attempts
retryDelay: 1000 // Initial delay in ms (exponential backoff)
);
$ds24 = new Digistore24($config);
// Automatic retry on rate limit (429) or server errors (500-599)
try {
$response = $ds24->products->list();
echo "Retrieved {$response->total} products\n";
} catch (RateLimitException $e) {
// Thrown after all retries exhausted
$retryAfter = $e->getContextValue('retry_after');
echo "Rate limit exceeded. Retry after {$retryAfter} seconds\n";
}
Retry Strategy:
- 1st retry: Wait 1 second
- 2nd retry: Wait 2 seconds (exponential)
- 3rd retry: Wait 4 seconds (exponential)
- After 3 attempts: Throw
RateLimitException
Status codes with automatic retry:
429 Too Many Requests - Rate limit hit
500 Internal Server Error - Server error
502 Bad Gateway - Temporary unavailability
503 Service Unavailable - Service down
504 Gateway Timeout - Request timeout
Status codes WITHOUT retry:
400 Bad Request - Invalid parameters
401 Unauthorized - Invalid API key
403 Forbidden - Insufficient permissions
404 Not Found - Resource not found
Manual Rate Limit Handling
For fine-grained control, you can implement custom retry logic:
use GoSuccess\Digistore24\Api\Exception\RateLimitException;
$maxAttempts = 5;
$attempt = 0;
while ($attempt < $maxAttempts) {
try {
$response = $ds24->purchases->list();
break; // Success
} catch (RateLimitException $e) {
$attempt++;
$retryAfter = $e->getContextValue('retry_after') ?? 60;
if ($attempt >= $maxAttempts) {
throw $e; // Give up
}
echo "Rate limited. Waiting {$retryAfter}s before retry {$attempt}/{$maxAttempts}...\n";
sleep($retryAfter);
}
}
Available Resources
| Resource |
Description |
Endpoints |
Status |
affiliates |
Commission management |
8 |
✅ Complete |
billing |
On-demand invoicing |
1 |
✅ Complete |
buyers |
Customer information |
8 |
✅ Complete |
buyUrls |
Order form URL management |
3 |
✅ Complete |
countries |
Country/region data |
2 |
✅ Complete |
ipns |
Webhook management |
3 |
✅ Complete |
monitoring |
Health checks |
1 |
✅ Complete |
products |
Product management |
59 |
✅ Complete |
purchases |
Order information |
24 |
✅ Complete |
rebilling |
Subscription management |
4 |
✅ Complete |
users |
Authentication |
3 |
✅ Complete |
vouchers |
Discount codes |
6 |
✅ Complete |
| Total |
|
122 |
✅ 100% |
API Endpoints Documentation
Affiliate Management
| Endpoint |
Documentation |
getAffiliateCommission |
View |
updateAffiliateCommission |
View |
getAffiliateForEmail |
View |
setAffiliateForEmail |
View |
getReferringAffiliate |
View |
setReferringAffiliate |
View |
validateAffiliate |
View |
statsAffiliateToplist |
View |
Billing & Invoicing
| Endpoint |
Documentation |
createBillingOnDemand |
View |
listInvoices |
View |
resendInvoiceMail |
View |
Buy URL Management
| Endpoint |
Documentation |
createBuyUrl |
View |
listBuyUrls |
View |
deleteBuyUrl |
View |
Buyer Management
| Endpoint |
Documentation |
getBuyer |
View |
updateBuyer |
View |
listBuyers |
View |
getCustomerToAffiliateBuyerDetails |
View |
Country & Currency
| Endpoint |
Documentation |
listCountries |
View |
listCurrencies |
View |
Delivery Management
| Endpoint |
Documentation |
getDelivery |
View |
updateDelivery |
View |
listDeliveries |
View |
E-Tickets
| Endpoint |
Documentation |
createEticket |
View |
getEticket |
View |
listEtickets |
View |
validateEticket |
View |
getEticketSettings |
View |
listEticketLocations |
View |
listEticketTemplates |
View |
Forms & Custom Data
| Endpoint |
Documentation |
listCustomFormRecords |
View |
Images
| Endpoint |
Documentation |
createImage |
View |
getImage |
View |
listImages |
View |
deleteImage |
View |
IPN/Webhook Management
| Endpoint |
Documentation |
ipnSetup |
View |
ipnInfo |
View |
ipnDelete |
View |
License Keys
| Endpoint |
Documentation |
validateLicenseKey |
View |
Marketplace
| Endpoint |
Documentation |
getMarketplaceEntry |
View |
listMarketplaceEntries |
View |
Member Access
| Endpoint |
Documentation |
listAccountAccess |
View |
logMemberAccess |
View |
Monitoring
| Endpoint |
Documentation |
ping |
View |
Order Forms
| Endpoint |
Documentation |
createOrderform |
View |
getOrderform |
View |
updateOrderform |
View |
deleteOrderform |
View |
listOrderforms |
View |
getOrderformMetas |
View |
Payment Plans
| Endpoint |
Documentation |
createPaymentplan |
View |
updatePaymentplan |
View |
deletePaymentplan |
View |
listPaymentPlans |
View |
Payouts & Commissions
| Endpoint |
Documentation |
listPayouts |
View |
listCommissions |
View |
Product Groups
| Endpoint |
Documentation |
createProductGroup |
View |
getProductGroup |
View |
updateProductGroup |
View |
deleteProductGroup |
View |
listProductGroups |
View |
Product Management
| Endpoint |
Documentation |
createProduct |
View |
getProduct |
View |
updateProduct |
View |
deleteProduct |
View |
copyProduct |
View |
listProducts |
View |
listProductTypes |
View |
Purchase Management
| Endpoint |
Documentation |
getPurchase |
View |
updatePurchase |
View |
listPurchases |
View |
listPurchasesOfEmail |
View |
getPurchaseTracking |
View |
addBalanceToPurchase |
View |
createUpgradePurchase |
View |
createAddonChangePurchase |
View |
getPurchaseDownloads |
View |
refundPurchase |
View |
refundPartially |
View |
resendPurchaseConfirmationMail |
View |
Rebilling/Subscriptions
| Endpoint |
Documentation |
startRebilling |
View |
stopRebilling |
View |
createRebillingPayment |
View |
listRebillingStatusChanges |
View |
Service Proof
| Endpoint |
Documentation |
getServiceProofRequest |
View |
updateServiceProofRequest |
View |
listServiceProofRequests |
View |
Shipping
| Endpoint |
Documentation |
createShippingCostPolicy |
View |
getShippingCostPolicy |
View |
updateShippingCostPolicy |
View |
deleteShippingCostPolicy |
View |
listShippingCostPolicies |
View |
Statistics
| Endpoint |
Documentation |
statsSales |
View |
statsSalesSummary |
View |
statsDailyAmounts |
View |
statsExpectedPayouts |
View |
statsMarketplace |
View |
Tracking & Conversion
| Endpoint |
Documentation |
renderJsTrackingCode |
View |
listConversionTools |
View |
Transactions
| Endpoint |
Documentation |
listTransactions |
View |
refundTransaction |
View |
reportFraud |
View |
Upgrades
| Endpoint |
Documentation |
createUpgrade |
View |
getUpgrade |
View |
deleteUpgrade |
View |
listUpgrades |
View |
getSmartupgrade |
View |
listSmartUpgrades |
View |
Upsells
| Endpoint |
Documentation |
getUpsells |
View |
updateUpsells |
View |
deleteUpsells |
View |
User/API Key Management
| Endpoint |
Documentation |
requestApiKey |
View |
retrieveApiKey |
View |
unregister |
View |
getUserInfo |
View |
getGlobalSettings |
View |
Vouchers/Coupons
| Endpoint |
Documentation |
createVoucher |
View |
getVoucher |
View |
updateVoucher |
View |
deleteVoucher |
View |
listVouchers |
View |
validateCouponCode |
View |
Migration
Upgrading from gosuccess/php-ds24-api-wrapper? See MIGRATION.md for detailed instructions on namespace changes, constructor updates, and breaking changes.
Testing
The project has comprehensive test coverage with 1035+ tests and 2116 assertions.
# Run all tests
composer test
# Run tests with coverage (requires PCOV or Xdebug)
composer test:coverage
# Run mutation testing (validates test quality)
composer mutation
# Run specific test suites
composer test:unit
composer test:integration
Quality Metrics:
- Tests: 1035 tests, 2116 assertions
- Coverage: Lines ~98%, Functions ~99%, Classes 100%
- Mutation Score: 85%+ MSI (test quality indicator)
- PHPStan: Level 9 (maximum strictness)
See TESTING.md for detailed testing guide, coverage setup, mutation testing, and best practices.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Contributing
Contributions are welcome! Please read our documentation:
Quick Start for Contributors
# Clone repository
git clone https://github.com/GoSuccessHQ/digistore24-api.git
cd digistore24-api
# Install dependencies (requires PHP 8.4+)
composer install
# Verify setup
php -v # Should show PHP 8.4.x
# Run tests
composer test
# Check code quality
composer cs:fix
composer analyse
See DEVELOPER_SETUP.md for detailed IDE setup instructions.
Support
- Documentation: Check the
docs/ directory for endpoint-specific guides
- Testing Guide: See TESTING.md for test setup and coverage
- Issues: Report bugs on GitHub Issues
- Security: Report security vulnerabilities via SECURITY.md
- Migration Guide: See MIGRATION.md for upgrading from v1.x
- Changelog: See CHANGELOG.md for version history