Download the PHP package taxora/sdk-php without Composer
On this page you can find all versions of the php package taxora/sdk-php. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download taxora/sdk-php
More information about taxora/sdk-php
Files in taxora/sdk-php
Package sdk-php
Short Description Official PHP SDK for the Taxora VAT API (sandbox & production).
License MIT
Informations about the package sdk-php
Taxora PHP SDK
Official PHP SDK for the Taxora VAT Validation API Validate EU VAT numbers, generate compliance certificates, and integrate VAT checks seamlessly into your systems โ all with clean, modern PHP.
๐ Overview
The Taxora SDK provides an elegant, PSR-compliant interface to the Taxora API, supporting:
- โ Secure API-Key and Bearer Token authentication
- โ Single & multiple VAT validation with AI-based company matching
- โ VAT state history and search endpoints
- โ Certificate generation (PDF) and bulk/list exports (ZIP or PDF)
- โ Full test coverage & PSR-18 compatible HTTP client
- โ PHP 8.3, 8.4, and (soon) 8.5 ready
๐ The SDK itself is free to use, but a Taxora API subscription is required. You can obtain your
x-api-keyfrom your Taxora account developer settings.
๐งฎ Installation
Install via Composer:
The package supports all PSR-18 clients (e.g. Guzzle, Symfony, Buzz) and PSR-17/PSR-7 factories.
Example dependencies for Guzzle:
โ๏ธ Quick Start
๐ Smart Enrichment (reverse VAT lookup)
Resolve a company name + address + country โ VAT number + confidence. A confident match
returns synchronously; harder cases (and all bulk batches) are processed asynchronously and
delivered via the enrichment.completed webhook โ poll with get($jobId) in the meantime.
Requires the Smart Enrichment add-on to be active on your account.
Note:
no_vat_existsmeans the company was identified but legitimately has no VAT/UID number (common for purely-domestic German firms). It is a definitive answer โ not a failure โ and is not billed.
๐ซ๐ท E-Reporting / Compliance (DGFiP Flux 10)
Full French e-reporting flow: enroll a company with the provider, record (and
optionally submit) transactions, follow the resulting DGFiP tax reports, and pull
turnover statistics. All endpoints require an active E-Reporting subscription /
feature grant โ except requestEReportingAccess(), which is exactly how you ask
for one. Provider failures (B2Brouter/DGFiP) surface as HttpException with
status code 502.
1. Enroll (SIRENE lookup โ enrollment)
2. Record & submit transactions
3. CSV bulk import
4. Tax reports (DGFiP ledger outcomes)
5. Revenue statistics & VAT rates
Read-only turnover aggregation over your e-reporting transactions โ totals, a time
series and breakdowns by transaction type, counterparty country and state. All headline
figures are expressed in the most frequent currency in the range (primaryCurrency);
when more than one currency is present, isMultiCurrency is true and byCurrency
lists each one. Monetary values are returned as 4-decimal strings to preserve precision.
6. No access yet?
๐ณ๐ด E-Invoicing Norway (EHF / Peppol)
Compliance services are booked per country: each enrollment covers one
country and one service โ France offers e-reporting (and e-invoicing) via DGFiP
Flux 10 (regime: dgfip_flux10), Norway offers e-invoicing via EHF 3.0 =
Peppol BIS Billing 3.0 (regime: peppol_bis3). $enrollment->service tells you
which service an enrollment books (ComplianceService::E_REPORTING /
E_INVOICING). Billing is per country as well: Norway is charged a one-off setup
fee when the country is activated plus a price per document sent.
The company needs the e-invoicing service unlocked โ otherwise enrolling fails
with an HttpException (status 403, body code service_not_active); use
requestEReportingAccess(service: 'e_invoicing', countries: ['NO']) to ask for it.
Norwegian organisation numbers are validated locally (9 digits, modulus-11 check
digit) before any request; Taxora\Sdk\Support\NorwegianOrgNumber exposes the
same helpers (normalize(), isValid(), toVatNumber() โ NO923609016MVA).
1. Registry lookup โ enrollment
2. Can the buyer receive e-invoices? (Peppol lookup)
3. Send an invoice
4. Send a credit note
company()->get() returns the raw company payload. New company limit fields are exposed as api_rate_limit and vat_rate_limit. The legacy rate_limit field may still appear temporarily for backward compatibility, but it should be treated as deprecated.
vat()->validate() returns a VatResource object that includes the canonical VAT number, status, requested company name echo, optional scoring data, and optional API error metadata. state remains backward-compatible and still carries the canonical business result, while has_api_error, error_message, and next_api_recheck_at expose technical provider failures without breaking existing integrations. The score reflects the overall confidence (higher is better), while breakdown provides an array of ScoreBreakdown objects describing every validation step, its score contribution, and any metadata (e.g. matched addresses or mismatched fields).
Need to plug in your own PSR-18 client or PSR-17 factories (e.g. to add logging or retries)? Call the constructor directly or pass them as optional overrides to the factory:
๐งฉ Architecture
The SDK follows clean separation of concerns:
Each endpoint handles:
- Request signing with
x-api-key - Bearer token refresh if expired or unauthorized
- PSR-7 response parsing into DTOs
๐ฆ DTOs
| Class | Description |
|---|---|
VatResource |
Represents a single VAT validation result (normalized VAT UID, state, score, breakdown, company data) |
ScoreBreakdown |
Scoring fragment with validation step name, score contribution, and metadata context for the decision |
VatCollection |
Iterable list of VatResource objects |
Token |
Auth token with expiry & type |
ComplianceEnrollment |
Compliance enrollment for one country + service (service, regime, status, provider account) |
ComplianceTransaction |
Recorded e-reporting / e-invoicing transaction incl. buyer register data, documentType, credit-note reference and providerState |
ComplianceTaxReport |
DGFiP tax report outcome of a transaction ledger (France) |
SireneLookupResult |
French SIRENE company data (prefill for createEnrollment()) |
RegistryCompany |
Norwegian register (Brรธnnรธysund) company data from registryLookup() |
PeppolLookupResult |
Peppol directory answer (status reachable / not_reachable / pending, supported document types) |
RevenueStatistics |
Aggregated turnover statistics over compliance transactions |
SmartEnrichmentJob |
Smart Enrichment (reverse VAT lookup) job with its results |
Example:
๐ Authentication Flow
-
Login
Need to authenticate with a technical
client_idinstead of an email?Advanced: you can still pass
loginIdentifier: LoginIdentifier::CLIENT_IDintologin()if you prefer an explicit enum instead of the helper.โ Stores and returns a
TokenDTO (valid for ~3600 seconds). -
Auto-refresh The client automatically refreshes the token on
401responses. -
Manual refresh (optional)
- Token storage By default, tokens are stored in memory. You can provide a PSR-16 cache adapter for persistence:
๐คช Testing
Run the test suite locally:
CI runs on PHP 8.3, 8.4, and (soon) 8.5, verifying:
- PHPUnit 12
- Psalm static analysis
- Code style checks
๐๏ธ Environments
| Environment | Base URL |
|---|---|
| Sandbox | https://sandbox.taxora.io/v1 |
| Production | https://api.taxora.io/v1 |
Need sandbox sample data? Known VAT UIDs with deterministic responses live in tests/Fixtures/SandboxVatFixtures.php.
Switch easily via the constructor:
๐จ Error Handling
| Exception | When |
|---|---|
ValidationException |
HTTP 422 โ getErrors() holds the per-field messages |
AuthenticationException |
HTTP 401 โ credentials rejected, or the token refresh failed |
HttpException |
Every other non-success status โ getStatusCode() / getResponseBody() |
TimeoutException |
A client-side wait gave up; the server-side job keeps running |
Exception messages are always short and safe to log. A response body is
never used as the message: gateways in front of the API answer 502/503/504
with a full HTML error page, and that page would otherwise land in every log
line and error mail of your application. The SDK uses the message / error
field of a JSON error body when there is one, and falls back to the status line
(Taxora API request failed (HTTP 504 Gateway Timeout).) otherwise. The
untouched body stays available via HttpException::getResponseBody().
Automatic retries
The SDK retries what never produced an answer from the API itself: 3 attempts, with 500 ms and 1000 ms of backoff in between. That covers
- gateway failures (
502,503,504) โ the infrastructure in front of the API, where a second attempt a moment later usually succeeds; - connection-level failures โ reset connections, client-side timeouts, DNS hiccups. Once the attempts are used up, the transport exception of your own HTTP client is rethrown unchanged, so nothing about its type or message changes for you;
429 Too Many Requests, but only with aRetry-Afterโ then the SDK waits exactly as long as the API asked instead of using its own backoff. Without that header a retry would only hammer a rate limit that is already tripped, so the error is surfaced immediately. ARetry-Afterlonger thanmaxRetryAfterMs(10 s by default) also fails immediately rather than blocking your worker โ the raw header stays readable viaHttpException::getRetryAfter().
Everything else fails on the first attempt, including any 5xx the API produced
itself (a 500 is a bug, not a hiccup โ repeating it just costs time).
Retries apply to read-only calls only โ VAT validation, lookups, state, history,
search, certificate downloads, company and e-reporting reads, login and token
refresh. Calls that change state or cost quota (certificatesBulkExport(),
smartEnrichment()->lookup(), e-reporting enrollment/transaction writes) are
never retried automatically, because a gateway timeout does not tell us
whether the API already processed the request.
Once the attempts are used up you get one clean error:
Tune or disable it via RetryPolicy:
โ ๏ธ Deprecations
So fresh there aren't even any deprecated features yet. Check back in a few months when we're on v47 and have made some regrettable decisions. ๐
๐ชช License
Licensed under the MIT License ยฉ 2025 theconcept technologies. The SDK is open-source, but API usage requires a valid Taxora subscription.
๐ค Contributing
Contributions and pull requests are welcome!
- Follow PSR-12 coding style (
composer fix). - Run
composer testbefore submitting a PR. - Ensure new endpoints include DTOs + tests.
๐ฌ Support
Need help or enterprise support? ๐ง [email protected] ๐ https://taxora.io
All versions of sdk-php with dependencies
php-http/discovery Version ^1.19
psr/http-client Version ^1.0
psr/http-message Version ^2.0
psr/http-factory Version ^1.0
psr/simple-cache Version ^3.0