PHP SDK

Send invoices to Complyance from a PHP application: first a sample payload to build your mapping, then real invoices from the same source. You need PHP 7.4 or later, Composer and an API key.

Install

Install the SDKbash
composer require io.complyance/unify-sdk:3.0.11

Version 3.0.11 is a stable release. Run the command from your project directory, then load Composer’s autoloader in your code.

Configure the SDK

Configure the SDK once, when your application starts.

Configure the SDKphp
<?php
require __DIR__ . '/vendor/autoload.php';

use ComplyanceSDK\GETSUnifySDK;
use ComplyanceSDK\Models\SDKConfig;
use ComplyanceSDK\Enums\Environment;

$config = new SDKConfig(
    getenv('COMPLYANCE_API_KEY'),
    Environment::from(Environment::SANDBOX)
);
GETSUnifySDK::configure($config);

// The source this application sends as, and its version.
$sourceName = 'acme-erp';
$sourceVersion = '1.0';
  • The environment must match the key. Use Environment::SANDBOX with a sandbox key. When you go live, use Environment::PRODUCTION with a production key.
  • $sourceName and $sourceVersion name the source: the system that sends invoices to Complyance. Send the same pair in every call. When you go live, the source must be registered in your workspace. See Manage sources and their links.
  • Never write the key into your code. If COMPLYANCE_API_KEY is not set, the SDK cannot send anything.

Send a sample payload for mapping

Your system has its own names for invoice fields. Before Complyance can turn your invoices into e-invoices, you build a mapping from your fields to GETS, the Complyance standard invoice format. To start, send one invoice as your system produces it, with the purpose MAPPING. Complyance stores it for mapping and does not validate it or send it anywhere.

Send a sample payloadphp
use ComplyanceSDK\Enums\Country;
use ComplyanceSDK\Enums\Mode;
use ComplyanceSDK\Enums\Operation;
use ComplyanceSDK\Enums\Purpose;
use ComplyanceSDK\Models\GetsDocumentType;

// Your invoice, in your system's own field names.
$payload = [
    'invoice_number' => 'INV-2026-0142',
    'issue_date' => '2026-09-30',
    'currency' => 'AED',
    'seller' => ['name' => 'Acme Trading LLC', 'trn' => '100000000000003'],
    'buyer' => ['name' => 'Gulf Office Supplies LLC', 'trn' => '100000000000017'],
    'lines' => [
        ['description' => 'Office chair', 'quantity' => 10, 'unit_price' => 500.00, 'vat_rate' => 5],
    ],
    'total' => 5250.00,
];

$documentType = GetsDocumentType::builder()
    ->base('tax_invoice')
    ->build();

$raw = GETSUnifySDK::pushToUnifyWithDocumentType(
    $sourceName,
    $sourceVersion,
    $documentType,
    Country::from(Country::AE),
    Operation::from(Operation::SINGLE),
    Mode::from(Mode::DOCUMENTS),
    Purpose::from(Purpose::MAPPING),
    $payload,
    null,
    true
);

$response = json_decode($raw, true);
echo $response['message'];

The last argument, true, sends the request in the current Unify format, so the response matches the Unify API reference. Pass it in every call on this page.

You should see:

Payload savedjson
{
  "message": "Payload saved for mapping."
}

Next, open the Integration engine in the Developer portal and create an integration. At Payload Selection, choose the payload you sent. Map its fields, test the result, and link the integration to your source. See Create an integration and Map your fields to GETS.

Submit an invoice

Once the integration is tested and linked to your source, send invoices with the purpose INVOICING. Use the same source name and version, and the same payload shape you mapped. Complyance converts the invoice with your mapping, validates it, and continues delivery to the tax authority or the Peppol network.

Submit an invoicephp
$documentType = GetsDocumentType::builder()
    ->base('tax_invoice')
    ->build();

$raw = GETSUnifySDK::pushToUnifyWithDocumentType(
    $sourceName,
    $sourceVersion,
    $documentType,
    Country::from(Country::AE),
    Operation::from(Operation::SINGLE),
    Mode::from(Mode::DOCUMENTS),
    Purpose::from(Purpose::INVOICING),
    $payload,
    null,
    true
);

$response = json_decode($raw, true);
$documentId = $response['documentId'];
echo $response['message'];

The document type is the GETS document type: a base such as tax_invoice or credit_note, plus modifiers that describe the transaction. For an export invoice, add ->modifiers(['export']) before ->build(). Modifiers can change which fields are required. The fields each combination needs are in the field reference.

You should see:

Invoice validatedjson
{
  "documentId": "01K5EXAMPLE00000000000142",
  "documentNumber": "INV-2026-0142",
  "message": "Your invoice was validated and is ready for submission.",
  "Base64XML": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4…"
}

The invoice passed validation and was stored. Save the documentId; you need it to check the status. Base64XML is the e-invoice that was produced, Base64-encoded. Every field is described in Submit and retrieve.

Run your invoices in sandbox, and through the testbed, until they pass. Then switch to a production key and Environment::PRODUCTION.

Check a document’s status

Delivery continues after the response. Follow it with the documentId:

Check the statusphp
$status = GETSUnifySDK::getDocumentStatus($documentId);

echo $status['data']['state'];
Invoice acceptedjson
{
  "success": true,
  "data": {
    "documentId": "01K5EXAMPLE00000000000142",
    "documentNumber": "INV-2026-0142",
    "country": "AE",
    "environment": "sandbox",
    "state": "final_valid",
    "isTerminal": true,
    "errors": []
  }
}

While isTerminal is false, the invoice is still being processed, so check again later. final_valid means it was accepted as compliant. final_invalid or rejected means it was not; errors says why. To be told when the status changes instead of asking, use webhooks.

Retrieve purchase invoices

To read invoices your suppliers sent you, call the API directly with the same key: Get a purchase invoice by its documentId, or List purchase invoices for a date range, one page at a time.

Handle errors

When Complyance refuses a request, the call throws ComplyanceSDK\Exceptions\SDKException. Read the HTTP status and the response body from its error detail:

Handle errorsphp
use ComplyanceSDK\Exceptions\SDKException;

try {
    $raw = GETSUnifySDK::pushToUnifyWithDocumentType(/* as above */);
} catch (SDKException $e) {
    $detail = $e->getErrorDetail();
    $httpStatus = $detail->getContextValue('httpStatus');
    $body = json_decode((string) $detail->getContextValue('responseBody'), true);

    if ($httpStatus === 422) {
        foreach ($body['errors'] ?? [] as $error) {
            echo $error['payloadPath'] . ': ' . $error['message'] . "\n";
        }
    }
}

The SDK retries rate limits and server errors on its own. If server errors continue while you submit an invoice, the call returns an object instead of a JSON string, and its getStatus() is queued: the invoice has not been validated yet, so do not record it as sent.

401: the API key is missing, invalid, revoked or expired. Check that COMPLYANCE_API_KEY is set where your application runs.

403: the key belongs to a different environment. Use a sandbox key with Environment::SANDBOX, and a production key with Environment::PRODUCTION.

422: the invoice failed validation. Each entry in errors names the field in your payload (payloadPath), the field in GETS (getsPath) and the rule it broke. Fix every one, then send the invoice again. With GETS-HEAD-010, the invoice number was already sent: use a new one.

Every status and what to do about it is in Errors.

Next, check which fields your invoices need in the field reference.

Last updated