truetrial / sdk
Official PHP SDK for the TrueTrial API
v1.0.0
2026-05-07 15:37 UTC
Requires
- php: ^8.2
- guzzlehttp/guzzle: ^7.0
Requires (Dev)
- phpunit/phpunit: ^11.0
README
Official PHP SDK for the TrueTrial API. Manage orders, shipments, temporal elements (trials, warranties, subscriptions), cancellations, and webhooks.
Requirements
- PHP 8.2 or higher
- Guzzle HTTP 7.x
Installation
composer require truetrial/sdk
Quick Start
Create a Client
use TrueTrial\TrueTrial; $truetrial = new TrueTrial('your-api-key'); // Or with a custom base URL $truetrial = new TrueTrial('your-api-key', 'https://api.truetrial.com/api/v1');
Create an Order
$order = $truetrial->orders->create([ 'external_order_id' => 'ORD-12345', 'product_name' => 'Premium Supplement', 'product_type' => 'physical', 'product_price_cents' => 4999, 'product_currency' => 'USD', 'consumer_email' => 'customer@example.com', 'consumer_first_name' => 'Jane', 'consumer_last_name' => 'Doe', 'temporal_type' => 'trial', 'temporal_duration_value' => 30, 'temporal_duration_unit' => 'days', ]); echo $order['id']; // ULID
List Orders
// All orders $response = $truetrial->orders->list(); // With filters $response = $truetrial->orders->list([ 'status' => 'trial_active', 'page' => 1, 'per_page' => 25, ]); foreach ($response['data'] as $order) { echo $order['product_name'] . ' - ' . $order['status'] . "\n"; }
Get Order Status
$status = $truetrial->orders->status('01HQ4X5K...'); // Returns: order_status, temporal_element_status, shipment_status
Create a Shipment
$shipment = $truetrial->shipments->create('01HQ4X5K...', [ 'carrier' => 'ups', 'tracking_number' => '1Z999AA10123456784', ]);
Confirm Digital Delivery
$delivery = $truetrial->digitalDelivery->confirm('01HQ4X5K...', [ 'method' => 'link_click', 'delivered_at' => '2026-02-08T12:00:00Z', ]);
Manage Temporal Elements
// Get temporal element for an order $temporal = $truetrial->temporal->get('01HQ4X5K...'); // Extend a trial $truetrial->temporal->extend('01HQ4X5K...', [ 'additional_days' => 7, 'reason' => 'Customer request - shipping delay', ]); // Adjust temporal element $truetrial->temporal->adjust('01HQ4X5K...', [ 'new_end_time' => '2026-04-01T00:00:00Z', 'reason' => 'Manual adjustment', ]); // Submit a warranty claim $truetrial->temporal->claim('01HQ4X5K...', [ 'description' => 'Product defect - screen crack', 'evidence' => ['photo_url' => 'https://...'], ]); // Resolve a warranty claim $truetrial->temporal->resolveClaim('01HQ4X5K...', [ 'resolution' => 'claim_approved', 'notes' => 'Replacement authorized', ]);
Cancellations
// Initiate cancellation $cancellation = $truetrial->cancellations->create('01HQ4X5K...', [ 'reason' => 'Customer changed their mind', ]); // Get cancellation details $cancellation = $truetrial->cancellations->get('01HQ4X5K...');
Webhooks
// List webhook subscriptions $webhooks = $truetrial->webhooks->list(); // Create a webhook subscription $webhook = $truetrial->webhooks->create([ 'url' => 'https://yourapp.com/webhooks/truetrial', 'events' => ['order.delivered', 'trial.started', 'trial.expiring'], ]); // Delete a webhook $truetrial->webhooks->delete('01HQ4WEBHOOK...');
System Health
$health = $truetrial->system->carrierHealth();
Webhook Verification
Verify incoming webhook signatures to ensure authenticity:
use TrueTrial\Webhook; $payload = file_get_contents('php://input'); $signature = $_SERVER['HTTP_X_TRUETRIAL_SIGNATURE']; $timestamp = (int) $_SERVER['HTTP_X_TRUETRIAL_TIMESTAMP']; $secret = 'your-webhook-secret'; // Simple verification $isValid = Webhook::verify($payload, $signature, $secret); // With timestamp tolerance (reject webhooks older than 5 minutes) $isValid = Webhook::verify($payload, $signature, $secret, 300, $timestamp); // Verify and decode in one step try { $event = Webhook::constructEvent($payload, $signature, $secret, 300, $timestamp); match ($event['event']) { 'order.delivered' => handleDelivery($event['data']), 'trial.started' => handleTrialStart($event['data']), 'trial.expiring' => handleTrialExpiring($event['data']), default => null, }; } catch (\TrueTrial\Exceptions\TrueTrialException $e) { http_response_code(400); echo 'Invalid signature'; }
Data Objects
The SDK includes optional data objects for convenience:
use TrueTrial\DataObjects\Order; use TrueTrial\DataObjects\PaginatedResponse; $response = $truetrial->orders->list(); $paginated = PaginatedResponse::fromArray($response); echo "Page {$paginated->currentPage} of {$paginated->lastPage}\n"; $order = Order::fromArray($response['data'][0]); echo $order->productName; echo $order->status;
Available data objects:
Order-- id, tenantId, consumerId, externalOrderId, productName, productType, productPriceCents, productCurrency, status, metadata, createdAt, consumerConsumer-- id, email, firstName, lastName, phoneShipment-- id, orderId, carrier, trackingNumber, status, estimatedDelivery, deliveredAtTemporalElement-- id, orderId, type, status, durationValue, durationUnit, beginTime, endTime, expiresAtCancellation-- id, orderId, reason, status, cancelledAtWebhookSubscription-- id, url, events, secret, lastTriggeredAtOrderStatus-- orderId, externalOrderId, orderStatus, temporalElementStatus, shipmentStatusPaginatedResponse-- data, currentPage, lastPage, perPage, total
Error Handling
The SDK throws specific exceptions for different error conditions:
use TrueTrial\Exceptions\AuthenticationException; use TrueTrial\Exceptions\NotFoundException; use TrueTrial\Exceptions\ValidationException; use TrueTrial\Exceptions\RateLimitException; use TrueTrial\Exceptions\ServerException; use TrueTrial\Exceptions\TrueTrialException; try { $order = $truetrial->orders->get('01HNONEXISTENT'); } catch (AuthenticationException $e) { // 401 - Invalid or missing API key echo "Auth failed: " . $e->getMessage(); } catch (NotFoundException $e) { // 404 - Resource not found echo "Not found: " . $e->getMessage(); } catch (ValidationException $e) { // 422 - Validation errors echo "Validation failed: " . $e->getMessage(); foreach ($e->errors() as $field => $messages) { echo "{$field}: " . implode(', ', $messages) . "\n"; } } catch (RateLimitException $e) { // 429 - Rate limit exceeded $retryAfter = $e->retryAfter(); // seconds until retry, or null echo "Rate limited. Retry after: {$retryAfter}s"; } catch (ServerException $e) { // 500+ - Server error echo "Server error: " . $e->getMessage(); } catch (TrueTrialException $e) { // Catch-all for any other SDK error echo "Error [{$e->statusCode}]: " . $e->getMessage(); }
All exceptions extend TrueTrialException and include:
$statusCode-- HTTP status code$responseBody-- raw response body string
Enums
The SDK provides string-backed enums for type safety:
use TrueTrial\Enums\OrderStatus; use TrueTrial\Enums\TemporalType; use TrueTrial\Enums\TemporalStatus; $truetrial->orders->list(['status' => OrderStatus::TrialActive->value]);
| Enum | Values |
|---|---|
OrderStatus |
received, shipped, in_transit, delivered, trial_active, converted, returned, expired, cancelled |
TemporalType |
trial, evaluation, subscription, warranty, guarantee |
TemporalStatus |
pending, active, expiring, expired, converted, cancelled, suspended, renewed, claimed, claim_approved, claim_denied |
ShipmentStatus |
pending, in_transit, out_for_delivery, delivered, failed, returned_to_sender |
ProductType |
physical, digital |
Carrier |
ups, fedex, usps, dhl, shippo, aftership |
DurationUnit |
days, weeks, months, years |
DeliverySource |
webhook, poll, manual, fallback_carrier |
DigitalDeliveryMethod |
link_click, installation, first_login, first_execution, license_key |
WebhookEvent |
order.created, order.delivered, trial.started, trial.expiring, trial.expired, trial.converted, cancellation.initiated, risk_score.changed, subscription.renewed, warranty.claimed, temporal.extended, temporal.adjusted, warranty.claim_resolved, payment.succeeded, payment.failed, dispute.created, dispute.won, dispute.lost |
API Reference
| Method | HTTP | Path |
|---|---|---|
$client->orders->list($filters) |
GET | /orders |
$client->orders->create($data) |
POST | /orders |
$client->orders->get($id) |
GET | /orders/{id} |
$client->orders->status($id) |
GET | /orders/{id}/status |
$client->shipments->create($orderId, $data) |
POST | /orders/{orderId}/shipments |
$client->shipments->list($orderId) |
GET | /orders/{orderId}/shipments |
$client->digitalDelivery->confirm($orderId, $data) |
POST | /orders/{orderId}/digital-delivery |
$client->temporal->get($orderId) |
GET | /orders/{orderId}/temporal |
$client->temporal->extend($orderId, $data) |
POST | /orders/{orderId}/temporal/extend |
$client->temporal->adjust($orderId, $data) |
POST | /orders/{orderId}/temporal/adjust |
$client->temporal->claim($orderId, $data) |
POST | /orders/{orderId}/temporal/claim |
$client->temporal->resolveClaim($orderId, $data) |
POST | /orders/{orderId}/temporal/resolve-claim |
$client->cancellations->create($orderId, $data) |
POST | /orders/{orderId}/cancellations |
$client->cancellations->get($orderId) |
GET | /orders/{orderId}/cancellations |
$client->webhooks->list() |
GET | /webhooks |
$client->webhooks->create($data) |
POST | /webhooks |
$client->webhooks->delete($id) |
DELETE | /webhooks/{id} |
$client->system->carrierHealth() |
GET | /carrier-health |
License
MIT