matav5/vies-sdk

PHP SDK for the EU VIES (VAT Information Exchange System) REST API

Maintainers

Package info

github.com/Matav5/vies-sdk

pkg:composer/matav5/vies-sdk

Statistics

Installs: 115

Dependents: 0

Suggesters: 0

Stars: 2

Open Issues: 0

v0.0.3 2026-02-20 15:08 UTC

This package is auto-updated.

Last update: 2026-03-20 15:20:02 UTC


README

PHP SDK for the EU VIES (VAT Information Exchange System) REST API.

Validate EU VAT numbers and check the availability of member states via a clean, PSR-18 compatible HTTP client.

Requirements

  • PHP 8.1+
  • A PSR-18 HTTP client (e.g. symfony/http-client)
  • A PSR-17 request & stream factory (e.g. nyholm/psr7)

Installation

composer require matav5/vies-sdk

You also need a PSR-18 client and PSR-17 factories. The recommended combination:

composer require symfony/http-client nyholm/psr7

Usage

Setup

use Matav5\ViesSdk\ViesClient;
use Nyholm\Psr7\Factory\Psr17Factory;
use Symfony\Component\HttpClient\Psr18Client;

$psr17 = new Psr17Factory();
$http  = new Psr18Client(null, $psr17, $psr17);

$vies = new ViesClient($http, $http, $http);

Psr18Client implements PSR-18, PSR-17 RequestFactory and PSR-17 StreamFactory simultaneously, which is why it is passed three times.

Validate a VAT number

use Matav5\ViesSdk\Request\CheckVatRequest;

$response = $vies->vat()->check(new CheckVatRequest('CZ', '27082440'));

$response->isValid();        // true
$response->getCountryCode(); // 'CZ'
$response->getVatNumber();   // '27082440'
$response->getName();        // 'Alza.cz a.s.'
$response->getAddress();     // 'Jankovcova 1522/53 ...'
$response->getRequestDate(); // '2024-01-01T00:00:00Z'

Approximate trader matching

Pass optional trader fields to verify company details against the VIES registry. The API returns a MatchStatus for each field if the member state supports approximate matching.

use Matav5\ViesSdk\Enum\MatchStatus;
use Matav5\ViesSdk\Request\CheckVatRequest;

$request = new CheckVatRequest(
    countryCode: 'DE',
    vatNumber:   '123456789',
    traderName:  'Example GmbH',
    traderCity:  'Berlin',
);

$response = $vies->vat()->check($request);

$response->getTraderNameMatch(); // MatchStatus::VALID | INVALID | NOT_PROCESSED | null
$response->getTraderCityMatch();

NOT_PROCESSED means the member state does not support approximate matching for that field.

To also receive a requestIdentifier, provide your own VAT number as the requester:

$request = new CheckVatRequest(
    countryCode:              'DE',
    vatNumber:                '123456789',
    requesterMemberStateCode: 'CZ',
    requesterNumber:          'CZ27082440',
);

$response->getRequestIdentifier(); // 'WAPPws...'

Test endpoint

The VIES API provides a test endpoint that works without a real VAT number:

// vatNumber 100 → valid, 200 → invalid (documented test values)
$response = $vies->vat()->checkTest(new CheckVatRequest('CZ', '100'));
$response->isValid(); // true

Member state availability

$status = $vies->status()->check();

$status->isVowAvailable(); // true
$status->getCountries();   // array<CountryStatus>

foreach ($status->getCountries() as $country) {
    echo $country->getCountryCode();  // 'CZ'
    echo $country->getAvailability(); // 'Available' | 'Unavailable' | 'Monitoring Disabled'
}

Error handling

use Matav5\ViesSdk\Exception\ApiException;
use Matav5\ViesSdk\Exception\ViesSdkException;

try {
    $response = $vies->vat()->check(new CheckVatRequest('CZ', ''));
} catch (ApiException $e) {
    // HTTP error response from the VIES API
    $e->getStatusCode();  // 400
    $e->getErrorCodes();  // ['VOW-ERR-11']
    $e->getResponse();    // PSR-7 ResponseInterface
} catch (ViesSdkException $e) {
    // Network error or invalid JSON response
}

ApiException extends ViesSdkException, so you can catch all SDK errors with a single catch (ViesSdkException $e).

Custom configuration

use Matav5\ViesSdk\Config;
use Matav5\ViesSdk\ViesClient;

$config = new Config(
    baseUrl: 'https://ec.europa.eu/taxation_customs/vies/rest-api',
    timeout: 10,
);

$vies = new ViesClient($http, $http, $http, $config);

Running tests

# Unit tests only
composer test

# Integration tests (calls the real VIES API)
composer test:integration

# All tests
composer test:all

License

MIT