Complyance Logo

Complyance Python SDK v3.0

Production-ready Python SDK for multi-country e-invoicing across KSA, Malaysia, Belgium, Germany, and UAE, with enterprise-grade features built for real-world applications.

Feature Summary

  • 34 Types - Registered DocType support
  • 5 Countries - KSA, Malaysia, Belgium, Germany, UAE supported
  • Sync + Async - Compatible with both sync and async Python workflows
  • v3.0 - Production ready

Installation

pip

pip install complyance-sdk==3.0.1b0

poetry

poetry add complyance-sdk==3.0.1b0

conda

conda install -c complyance complyance-sdk=3.0.1b0

Quickstart (Correct Workflow)

The SDK follows a structured Configure -> Mapping -> Template -> Invoicing flow. This process ensures your document data correctly translates to regulatory standards across supported countries.

1) Configure the SDK (once per application)

Connect to the Complyance platform by providing your API key and defining your application source.

from complyance_sdk import GETSUnifySDK, SDKConfig, Source, SourceType, Environment

sources = [
    Source("SourceName", "sourceVersion", SourceType.FIRST_PARTY)
]

config = SDKConfig(
    api_key="YOUR_API_KEY",
    environment=Environment.SANDBOX,  # Change to Environment.PRODUCTION when going live
    sources=sources,
)

GETSUnifySDK.configure(config)

2) Generate API Key

Use this quick flow to create and use your API key.

  1. Sign in to the Complyance portal.
  2. Go to Developer Portal.
  3. Open Integration Engine.
  4. Click Create Mapping.
  5. Select country and document type, then click Next.
  6. On the API/authentication step, click Generate API Key.
  7. Choose the environment:
    • Sandbox for testing
    • Production for live submission
  8. Copy the key and store it securely (secret manager or environment variable).
  9. Use this key in your Python SDK config as YOUR_API_KEY.

3) Purpose Workflow (Payload)

The integration requires a specific logical sequence for the Purpose parameter to ensure data accuracy and compliance.

Step 1: MAPPING (Setup & Template Creation)

Set the Purpose to Purpose.MAPPING to push your raw payload data to the Complyance platform. This stage is used for field discovery and blueprinting.

Note: Before running mapping, update the country code based on your target country:

  • SA - Saudi Arabia
  • AE - UAE
  • BE - Belgium
  • DE - Germany
  • MY - Malaysia
  • In Code: Submit your payload using Purpose.MAPPING.
  • In Portal: Locate the uploaded payload in the Complyance portal, complete the field mapping until validations pass, and save it as a Template.
  • Final Step: Register and bind your unique sourceName and sourceVersion (e.g., pyke / 16) to this saved template.
from typing import Any, Dict

from complyance_sdk import (
    GETSUnifySDK,
    Country,
    GetsDocumentType,
    BASE,
    MODIFIER,
    Operation,
    Mode,
    Purpose,
)

def submit_with_document_type(
    source_name: str,
    source_version: str,
    document_type: GetsDocumentType,
    country: Country,
    operation: Operation,
    mode: Mode,
    purpose: Purpose,
    payload: Dict[str, Any],
):
    return GETSUnifySDK.push_to_unify_v2(
        source_name=source_name,
        source_version=source_version,
        document_type_v2=document_type,
        country=country,
        operation=operation,
        mode=mode,
        purpose=purpose,
        payload=payload,
    )

payload: Dict[str, Any] = create_uae_test_payload()
document_type = GetsDocumentType.builder().base(BASE.TAX_INVOICE).modifiers(
    [MODIFIER.EXPORT]
).build()

try:
    mapping_response = submit_with_document_type(
        source_name="pyke",
        source_version="16",
        document_type=document_type,
        country=Country.AE,
        operation=Operation.SINGLE,
        mode=Mode.DOCUMENTS,
        purpose=Purpose.MAPPING,
        payload=payload,
    )
except Exception as exc:
    message = str(exc)
    if "AUTHENTICATION_FAILED" in message or "Invalid API key" in message or "HTTP 401" in message:
        raise RuntimeError(
            "Authentication failed. Verify COMPLYANCE_API_KEY and environment routing."
        ) from exc
    raise

if mapping_response.status == "success":
    payload_id = getattr(getattr(mapping_response.data, "payload", None), "payloadId", None)
    request_id = getattr(getattr(mapping_response.data, "processing", None), "requestId", None)
    print(f"Mapping succeeded: request_id={request_id}, payload_id={payload_id}")
elif mapping_response.status == "error":
    error_msg = mapping_response.message if hasattr(mapping_response, "message") and mapping_response.message else "Unknown error"
    error_code = mapping_response.error.code if hasattr(mapping_response, "error") and mapping_response.error and hasattr(mapping_response.error, "code") else "N/A"
    print(f"Error: {error_code} - {error_msg}")

Request example (MAPPING)

{
  "source": {
    "name": "pyke",
    "version": "16",
    "type": "FIRST_PARTY",
    "id": "pyke:16",
    "identity": "pyke:16"
  },
  "country": "AE",
  "operation": "SINGLE",
  "mode": "DOCUMENTS",
  "payload": {
    "supporting_documents": [
      {
        "id": "PO-2024-001234",
        "type": "purchaseOrderReference"
      }
    ],
    "invoice_data": {
      "prepaid_amount": 0.0,
      "document_number": "UAE-DBT-20260409185121294",
      "exchange_rate": 1.0,
      "total_allowances": 0.0,
      "due_date": "2026-05-09",
      "invoice_time": "14:30:00Z",
      "period_frequency": "MONTHLY",
      "debit_note_reason": "Additional charges",
      "document_id": "b7620dff-b440-4924-ba8a-aa3abdf5e8ac",
      "original_reference_id": "UAE-INV-ORIG-001",
      "currency_code": "AED",
      "invoice_date": "2026-04-09",
      "total_charges": 0.0,
      "rounding_amount": 0.0,
      "credit_note_reason": "Goods returned",
      "total_amount": 10500.0,
      "period_end_date": "2026-04-09",
      "line_extension_amount": 10000.0,
      "tax_exclusive_amount": 10000.0,
      "period_start_date": "2026-03-10",
      "total_tax_amount": 500.0,
      "amount_due": 10500.0,
      "tax_currency_code": "AED",
      "document_type": "tax_invoice"
    },
    "seller_info": {
      "additional_address": "Building 123",
      "seller_email": "contact@abctrading.ae",
      "seller_contact_name": "Ahmed Al Maktoum",
      "vat_number": "100819867100003",
      "registration_number": "CN-1234567",
      "peppol_id": "0235:1008213264",
      "vat_number_type": "TRN",
      "tax_scheme": "VAT",
      "state_province": "DUBAI",
      "registration_type": "TL",
      "street_name": "Sheikh Zayed Road",
      "country_code": "AE",
      "city_name": "Dubai",
      "seller_name": "ABC Trading LLC",
      "seller_trade_name": "ABC Trading",
      "seller_party_id": "SELLER-UAE-001",
      "seller_phone": "+971-4-1234567",
      "registration_scheme": "AE:TL",
      "authority_name": "Dubai Department of Economic Development",
      "postal_code": "00000",
      "building_number": "123"
    },
    "buyer_info": {
      "buyer_email": "purchasing@xyzcorp.ae",
      "buyer_country": "AE",
      "buyer_vat_type": "TRN",
      "buyer_building_number": "456",
      "buyer_registration_type": "TL",
      "buyer_phone": "+971-2-9876543",
      "buyer_name": "XYZ Corporation LLC",
      "buyer_state_province": "DUBAI",
      "buyer_street_name": "Al Wasl Road",
      "buyer_city": "Dubai",
      "buyer_additional_address": "Tower 2",
      "buyer_tax_scheme": "VAT",
      "buyer_authority_name": "Abu Dhabi Department of Economic Development",
      "buyer_trade_name": "XYZ Corp",
      "buyer_party_id": "BUYER-UAE-001",
      "buyer_registration_scheme": "TL",
      "buyer_peppol_id": "0235:1008213264",
      "buyer_vat_number": "100889867100003",
      "buyer_registration_number": "CN-9876543",
      "buyer_contact_name": "Fatima Al Mansouri",
      "buyer_postal_code": "00000"
    },
    "uae_extensions": {
      "unique_identifier": "b7620dff-b440-4924-ba8a-aa3abdf5e8ac",
      "buyer_authority_name": "Abu Dhabi Department of Economic Development",
      "business_process_type": "urn:peppol:bis:billing",
      "invoiced_object_id": "OBJECT-2024-001",
      "specification_identifier": "urn:peppol:pint:ae:invoice:v1",
      "taxpoint_date": "2026-04-09",
      "authority_name": "Dubai Department of Economic Development",
      "total_amount_including_tax_in_aed": 10500.0
    },
    "line_items": [
      {
        "tax_amount": 250.0,
        "quantity": 10.0,
        "batch_number": "BATCH-2024-001",
        "line_taxable_value": 5000.0,
        "item_type": "GOODS",
        "classification_code": "8471",
        "country_of_origin": "AE",
        "tax_category": "S",
        "item_name": "Office Equipment",
        "net_price": 5000.0,
        "unit_price": 5000.0,
        "line_id": "1",
        "tax_rate": 5.0,
        "line_total": 5250.0,
        "seller_item_code": "SKU-001",
        "unit_code": "EA",
        "gross_price": 5000.0,
        "classification_scheme": "HS",
        "item_description": "Professional office equipment package",
        "buyer_item_code": "BUYER-SKU-001"
      }
    ],
    "payment_info": {
      "account_id": "AE123456789012345678901",
      "payment_means_code": "IN_CASH",
      "payment_id": "PAY-001",
      "bank_id": "AEBN0001",
      "account_name": "ABC Trading LLC",
      "payment_means_text": "Bank Transfer",
      "remittance_info": "Payment for Invoice UAE-DBT-20260409185121294"
    },
    "payment_terms": [
      {
        "note": "Net 30 days",
        "amount": 10500.0,
        "due_date": "2026-05-09",
        "instructions_id": "TERMS-001"
      }
    ]
  },
  "apiKey": "ak_d13b9df3d4d1514ca1430d489a54",
  "requestId": "req_1775740881475_0.2917229556371743",
  "timestamp": "2026-04-09T13:21:21.475977Z",
  "env": "sandbox",
  "destinations": [
    {
      "type": "TAX_AUTHORITY",
      "details": {
        "country": "AE",
        "authority": "FTA",
        "documentType": "tax_invoice"
      }
    }
  ],
  "correlationId": null,
  "purpose": "mapping",
  "sourceOrigin": "SDK",
  "documentType": {
    "base": "tax_invoice",
    "modifiers": [
      "export"
    ]
  }
}

Success response example

{
  "status": "success",
  "message": "Unify request processed successfully",
  "data": {
    "source": {
      "sourceid": "680b1d0b-fc74-474f-a077-55103998f5b3",
      "id": "pyke",
      "created": false
    },
    "payload": {
      "payloadId": "01KNS6F3P5DDA6M2YTGWAFWT7D",
      "analysis": {
        "hasNested": true,
        "keys": [
          "supporting_documents",
          "invoice_data",
          "seller_info",
          "buyer_info",
          "uae_extensions",
          "line_items",
          "payment_info",
          "payment_terms",
          "meta",
          "documentType"
        ],
        "size": 3570
      }
    },
    "destinations": {
      "count": 1,
      "stored": true,
      "types": [
        "TAX_AUTHORITY"
      ],
      "valid": 1
    },
    "processing": {
      "processedAt": "2026-04-09T13:21:22.609Z",
      "requestId": "req_1775740881475_0.2917229556371743",
      "status": "completed"
    }
  },
  "metadata": {
    "requestId": "req_1775740881475_0.2917229556371743",
    "timestamp": "2026-04-09T13:21:22.609Z",
    "processingTime": 39,
    "version": "1.0"
  }
}

Error response

Error Codes: All SDK error codes match the Unify API error codes. See Error Codes Reference for the complete list and troubleshooting guidance.

API authentication error (HTTP 401)

{
  "status": "error",
  "httpStatus": 401,
  "apiResponseBody": "Invalid API key",
  "errorCode": "AUTHENTICATION_FAILED",
  "message": "API request failed with HTTP 401",
  "suggestion": "Check your API key and ensure it is valid for the target environment"
}

Step 2: INVOICING (Production Submission)

After your template is successfully bound to your source identifiers on the portal, switch the Purpose to Purpose.INVOICING.

  • Action: The platform now recognizes your sourceName/sourceVersion and applies the saved template logic to transform and officially submit your payload data.
  • Requirement: You must provide the exact sourceName and sourceVersion that were bound to the template.
from complyance_sdk import (
    Country,
    GetsDocumentType,
    BASE,
    MODIFIER,
    Operation,
    Mode,
    Purpose,
)

payload = create_uae_test_payload()
document_type = GetsDocumentType.builder().base(BASE.TAX_INVOICE).modifiers(
    [MODIFIER.EXPORT]
).build()

invoice_response = submit_with_document_type(
    source_name="pyke",
    source_version="16",
    document_type=document_type,
    country=Country.AE,
    operation=Operation.SINGLE,
    mode=Mode.DOCUMENTS,
    purpose=Purpose.INVOICING,
    payload=payload,
)

if invoice_response.status == "success":
    payload_id = getattr(getattr(invoice_response.data, "payload", None), "payloadId", None)
    request_id = getattr(getattr(invoice_response.data, "processing", None), "requestId", None)
    print(f"Invoicing succeeded: request_id={request_id}, payload_id={payload_id}")
elif invoice_response.status == "error":
    error_msg = invoice_response.message if hasattr(invoice_response, "message") and invoice_response.message else "Unknown error"
    error_code = invoice_response.error.code if hasattr(invoice_response, "error") and invoice_response.error and hasattr(invoice_response.error, "code") else "N/A"
    print(f"Error: {error_code} - {error_msg}")

Invoicing validation error response

{
  "status": "success",
  "message": "Invoicing request processed successfully",
  "data": {
    "source": {
      "sourceId": null,
      "sourceid": "19cf68b2-b1c3-423f-8f0f-11a90a951635",
      "type": null,
      "name": null,
      "version": null,
      "created": false,
      "id": "69a55cbf1908480073745005"
    },
    "payload": {
      "payloadId": "01KMMV73598W76YNYMVASNTDYH",
      "documentType": null,
      "country": null,
      "environment": null,
      "storedAt": null,
      "analysis": {
        "hasNested": true,
        "keys": [
          "additional_data",
          "buyer_info",
          "invoice_data",
          "line_items",
          "meta",
          "payment_info",
          "payment_terms",
          "seller_info",
          "supporting_documents",
          "uae_extensions"
        ],
        "size": 8231
      }
    },
    "template": {
      "templateId": "01KKJZBEG4C6NAX02X8P9P2QVZ",
      "templateName": null,
      "mappingCompleted": false,
      "totalMandatoryFields": null,
      "mappedMandatoryFields": null,
      "aiMappingApplied": null
    },
    "logicalDocumentType": null,
    "conversion": null,
    "document": {
      "documentId": "01KMMV7392T76HRE7X0NFCJZBX",
      "documentType": null,
      "createdAt": null,
      "metadata": null,
      "status": null
    },
    "validation": {
      "overallSuccess": false,
      "methods": null,
      "errors": [
        {
          "method": "gets",
          "message": "Line item price is required",
          "code": "GETS-LINE-005",
          "path": ["lineItems", 0, "price", "amount"]
        },
        {
          "method": "gets",
          "message": "Line item price is required",
          "code": "GETS-LINE-005",
          "path": ["lineItems", 1, "price", "amount"]
        },
        {
          "method": "gets",
          "message": "Document type must be a valid DOCUMENT_TYPES",
          "code": "GETS-GEN-005",
          "path": ["documentType"]
        }
      ],
      "validatedAt": "2026-03-26T10:32:06.517Z",
      "success": false
    },
    "submission": null,
    "processing": {
      "purpose": null,
      "completedSteps": null,
      "totalProcessingTime": null,
      "completedAt": null,
      "processedAt": "2026-03-26T10:32:06.747Z",
      "requestId": "req_1774521123558_c18c92ef6c5d47ed8bafb913ca08d771",
      "status": "completed"
    },
    "destinations": {
      "count": 1,
      "stored": true,
      "types": ["tax_authority"],
      "valid": 1
    }
  },
  "metadata": {
    "processingTime": 732,
    "requestId": "req_1774521123558_c18c92ef6c5d47ed8bafb913ca08d771",
    "timestamp": "2026-03-26T10:32:06.747Z",
    "version": "1.0"
  },
  "error": null
}

Why this structure is important:

  1. MAPPING is the "Discovery" phase where you build the data blueprint.
  2. The Portal is where you finalize the compliance logic and connect it to your application source.
  3. INVOICING is the "Execution" phase where the SDK performs the actual regulatory submission using that blueprint.

4) Field Mapping

For a comprehensive understanding of all available fields, validation rules, and country-specific requirements, refer to our detailed Field Mapping Payload Reference.

This reference provides:

  • Complete field documentation for all supported countries (SA, MY, BE, DE, AE)
  • Country-specific requirements and compliance rules
  • Field descriptions with examples and validation rules
  • Required vs Optional field indicators

Review this reference to ensure your payload structure meets all regulatory requirements for your target country.

5) Test Bed

Use Test Bed to validate your mapping flow before live submission.

How it works:

  1. Keep the SDK in Environment.SANDBOX.
  2. Push your sample payload with Purpose.MAPPING.
  3. The mapping flow passes that payload to the platform for validation and template checks.
  4. Fix any mapping errors shown in portal.
  5. After successful validation, switch to Purpose.INVOICING for submission.

Expected result:

  • Your sample payload gets processed through mapping without validation errors.
  • You are ready for controlled invoicing tests and then production rollout.

Reference (download)

Download the full example file: UAETaxInvoiceTest.py

Error Handling

try:
    response = submit_with_document_type(
        source_name="pyke",
        source_version="16",
        document_type=document_type,
        country=Country.AE,
        operation=Operation.SINGLE,
        mode=Mode.DOCUMENTS,
        purpose=Purpose.INVOICING,
        payload=payload,
    )

    if response.status == "success":
        print("Invoice submitted successfully")
    else:
        print(f"Error: {response.error}")
except Exception as e:
    print(f"Request failed: {e}")

Support

  • Contact: Contact Complyance for E-Invoicing - Complyance has helped over 1000+ organizations simplify global e-invoicing. Let us help you understand how Complyance can work for you.