vatly / vatly-api-php
PHP API client for Vatly, the Merchant of Record for European software and digital products
Requires
- php: ^8.0
- ext-bcmath: *
- ext-curl: *
- ext-intl: *
- ext-json: *
- ext-openssl: *
- composer/ca-bundle: ^1.3
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.13
- guzzlehttp/guzzle: ^7.5
- phpstan/phpstan: ^1.9
- phpunit/phpunit: ^9.5
- spatie/ray: ^1.19
Suggests
None
Provides
None
Conflicts
None
Replaces
None
- dev-main
- v0.1.0-alpha.32
- v0.1.0-alpha.31
- v0.1.0-alpha.30
- v0.1.0-alpha.29
- v0.1.0-alpha.28
- v0.1.0-alpha.27
- v0.1.0-alpha.26
- v0.1.0-alpha.25
- v0.1.0-alpha.24
- v0.1.0-alpha.23
- v0.1.0-alpha.22
- v0.1.0-alpha.21
- v0.1.0-alpha.20
- v0.1.0-alpha.19
- v0.1.0-alpha.18
- v0.1.0-alpha.17
- v0.1.0-alpha.16
- v0.1.0-alpha.15
- v0.1.0-alpha.14
- v0.1.0-alpha.13
- v0.1.0-alpha.12
- v0.1.0-alpha.11
- v0.1.0-alpha.10
- v0.1.0-alpha.9
- v0.1.0-alpha.8
- v0.1.0-alpha.7
- v0.1.0-alpha.6
- v0.1.0-alpha.5
- v0.1.0-alpha.4
- v0.1.0-alpha.3
- v0.1.0-alpha.2
- v0.1.0-alpha.1
- dev-feat/credit-note-and-invoice-urls
- dev-claude/sync-php-sdk-openapi-aa4b10
- dev-fix/refund-event-order-id
- dev-docs/list-to-page
- dev-docs/subscription-proration-charge
- dev-claude/adopt-simulate-payment-and-event-reason
- dev-claude/sync-openapi-create-endpoints
- dev-claude/vigilant-franklin-6458bb
- dev-docs/checkout-pricing-and-spec-pointer
- dev-feat/testmode-on-business-events
- dev-chore/sync-openapi-vatlify-1495
- dev-feat/own-webhook-event-factory
- dev-refactor/money-event-dtos-orderline-types-compat
- dev-feat/rename-payment-failed-add-webhook-setup
- dev-feat/own-webhook-event-dtos
- dev-feat/orderline-product-link
- dev-feat/checkout-customer-id
- dev-feat/subscription-billing-updated-event-name
- dev-fix/fix-webhook-parse-for-test-call-when-declaring-webhook
- dev-feat/webhook-setup-event
- dev-claude/tender-tesla-86c01c
- dev-claude/dreamy-euclid-75032b
- dev-claude/xenodochial-lalande-b7870c
- dev-claude/confident-khayyam-7438c9
- dev-fix/fixes_to_docs
This package is auto-updated.
Last update: 2026-11-07 12:48:42 UTC
README
Vatly API client for PHP
PHP client for the Vatly API. Vatly is the Merchant of Record for European software and digital products. You just ship. Vatly is the legal seller on every sale and handles payments, tax and compliance, from Europe.
Using a framework?
This is the raw API client. If you're building a Laravel application, you almost certainly want vatly/vatly-laravel instead — it provides a Cashier-style Billable trait, Eloquent models, a wired webhook endpoint, and event-bus integration on top of this SDK.
Other framework drivers (Symfony, WordPress) are on the roadmap. To build one, see the Driver Author Guide in vatly/vatly-fluent-php.
Installation
You can install the package via composer:
composer require vatly/vatly-api-php
Usage
use Vatly\API\VatlyApiClient; $vatly = new VatlyApiClient(); $vatly->setApiKey('test_your_api_key_here'); $vatly->checkouts->create([...]);
For detailed documentation, see docs/README.md.
Source of truth. The complete, canonical schema for every request and response — including fields the guides below don't spell out — lives in the OpenAPI spec. If you (or an AI assistant) are unsure whether a field exists or what it's called, check the spec rather than guessing from an example.
Idempotency
The SDK automatically sends an Idempotency-Key header on every POST and PATCH request.
$checkout = $vatly->checkouts->create([ 'products' => [ ['id' => 'subscription_plan_abc123', 'quantity' => 1], ], 'redirectUrlSuccess' => 'https://yourapp.com/success', 'redirectUrlCanceled' => 'https://yourapp.com/canceled', ]);
To set a custom key for the next mutating request, use setIdempotencyKey(). The manual key is cleared after the request is sent.
$vatly->setIdempotencyKey('checkout-create-123'); $checkout = $vatly->checkouts->create([ 'products' => [ ['id' => 'subscription_plan_abc123', 'quantity' => 1], ], 'redirectUrlSuccess' => 'https://yourapp.com/success', 'redirectUrlCanceled' => 'https://yourapp.com/canceled', ]);
Some endpoint methods also accept a per-request idempotencyKey option:
$checkout = $vatly->checkouts->create([...], [ 'idempotencyKey' => 'checkout-create-123', ]); $subscription = $vatly->subscriptions->update('subscription_123', [ 'quantity' => 2, ], [ 'idempotencyKey' => 'subscription-update-123', ]);
You can replace or disable the automatic generator when needed:
$vatly->setIdempotencyKeyGenerator(new MyIdempotencyKeyGenerator()); $vatly->clearIdempotencyKeyGenerator();
Webhooks
Verify and parse incoming Vatly webhooks with Webhook::parse(), which returns a typed WebhookPayload:
use Vatly\API\Webhooks\Webhook; $event = Webhook::parse($rawBody, $signatureHeader, $webhookSecret);
For strongly-typed, per-event objects, this package also owns immutable event DTOs under Vatly\API\Webhooks\Events\* (e.g. OrderPaid, RefundCompleted, SubscriptionStarted). Money fields are Vatly\API\Types\Money (decimal-string + currency; call $event->total->toCents() / read $event->total->currency to flatten at your persistence edge) and the VAT breakdown is Vatly\API\Types\TaxSummaryCollection; order lines are Vatly\API\Types\OrderLineData. These are the canonical event shapes that higher-level integrations build on.
Vatly\API\Webhooks\WebhookEventFactory turns a verified payload into one of these typed events — verify, parse, and map all happen in api-php now. Pass it a VatlyApiClient and hand it the WebhookReceived from fromPayload():
use Vatly\API\Webhooks\Webhook; use Vatly\API\Webhooks\WebhookEventFactory; $payload = Webhook::parse($rawBody, $signatureHeader, $webhookSecret); $factory = new WebhookEventFactory($client); $event = $factory->createFromWebhook($factory->fromPayload($payload)); // e.g. $event instanceof Vatly\API\Webhooks\Events\OrderPaid
Because Vatly sends fat, HMAC-signed payloads — the delivery's object is byte-identical to the corresponding GET /…/{id} body — the factory builds every event straight from the signed payload (hydrating the matching api-php resource in memory for money/tax-bearing events). It makes no follow-up API call. Use getSupportedEvents() / isSupported() to inspect the event surface.
The incoming webhook payloads are described in the webhooks: section of the OpenAPI spec. See docs/Webhooks.md for the full guide.
Testing
composer test
Changelog
Please see CHANGELOG for more information on what has changed recently.
Contributing
Send in a Pull Request if you'd like to contribute to this package.
Security Vulnerabilities
In case of a security vulnerability, please shoot us an email at security@vatly.com.
Credits
License
The MIT License (MIT). Please see License File for more information.
