openapi: 3.1.0
info:
  title: AZDAN Peppol Integration API
  version: 1.0.0
  description: |
    ## Authentication
    Every integration operation authenticates with a tenant API key created in the Tenant Console (API Keys), sent as:

    `Authorization: Bearer azd_test_… | azd_live_…`

    The prefix identifies the key; it does not choose the Peppol network. Routing is decided only by the request's `environment` ("test" | "production", default "test"), and the sender must be registered in that environment.

    Scopes: each operation lists the scopes its route accepts in `x-azdan-scopes` (any one suffices; the first is the one to ask for). A newly issued key carries `transactions:submit` and `transactions:read`, which covers 13 of the 15 operations.
    `peppol:payload:read` — Raw payload access: GET …/{transactionId}/xml and …/tdd/download. Not in a default key; request it when an integration must fetch signed URLs for the raw bytes. The …/files/* routes do not need it.

    ## Idempotency
    Send Idempotency-Key as an HTTP header on submit. The key identifies ONE logical submission, scoped to the tenant: the same key always returns the original transaction (idempotent: true) and never sends twice, so retry a timeout or a 5xx with the SAME key and use a new key for a new document. 1 to 120 characters — a longer key is refused with HTTP 400 IDEMPOTENCY_KEY_INVALID before anything is stored, and the same limit applies to the legacy body field idempotencyKey and to the by-idempotency lookup. The header is authoritative; if the legacy body field is also sent the two must be equal (IDEMPOTENCY_KEY_CONFLICT).

    ## Environment
    The Peppol network a document is routed to. Set per request (environment, default "test"), stored on the transaction and echoed in every webhook payload. The API key prefix does not influence it; the sender participant must be registered in the environment named.

    ## Tax Data Document
    Tax Data Documents are generated automatically by AZDAN. Do not submit a TDD. Use the invoice transaction's TDD endpoint to inspect the generated TDD status and download it when available. On the enriched detail of an invoice, ap.isTdd is always false and ap.tddStatus is always null — they describe the row itself, not the TDD generated for it. The generated TDD's delivery status is tdd.status on the TDD endpoint.

    ## Message Level Status
    MLS values are lower-case, exactly as stored. ap.mlsStatus / ap.mlsReceivedAt / ap.mlsId / ap.mlsType / ap.mlsErrorCode / ap.mlsErrorMessage are metadata on the enriched detail; documents.mlsXml is available only when an MLS XML file is actually stored — for outbound documents it is normally not.

    ## Pagination
    The transactions list endpoint supports two pagination modes:
    - **Cursor** (recommended for sync jobs): Use `limit` + `cursor` params.
    - **Page** (for UI browsing): Use `page` + `pageSize` params.

    ## Webhooks
    Subscribe to real-time lifecycle events via the portal Webhooks settings.
    Events are signed with HMAC-SHA256 for verification. If a tenant enables
    multiple webhook endpoints, each matching event is delivered to all enabled
    endpoints and delivery attempts are tracked per endpoint. Retries are
    isolated per endpoint: one endpoint failure does not re-send successful
    endpoints. Adding a new endpoint does not replay events created before that
    endpoint existed. Webhook signing secrets are endpoint-specific; when a
    tenant configures multiple webhook endpoints, each delivery is signed
    independently with the destination endpoint's configured secret.

    Every delivery is an HTTPS POST with `Content-Type: application/json` and
    the headers `X-Azdan-Signature` (`t=<unix>,v1=<hex>[,v1=<hex>]` — HMAC-SHA256
    of `"<t>.<body>"`; a second `v1=` appears for 24 hours after a secret
    rotation, signed with the previous secret), `X-Azdan-Event-Id` and
    `Idempotency-Key` (the same stable event id on every retry of an event),
    `X-Azdan-Webhook-Id`, `X-Azdan-Payload-Version` (`1` or `2`) and
    `X-Azdan-Timestamp`. Reject a delivery whose `t` is more than 300 seconds
    from your clock. Answer 2xx within 10 seconds; anything else is retried
    8 times with exponential backoff (30 s, 1, 2, 4, 8, 16, 32, 64 minutes,
    ±50 % jitter; `Retry-After` on 429/503 is honoured), then dead-lettered —
    visible and requeue-able in the Tenant Console.

    Payload versions: a webhook created today sends the **v2 envelope**
    (`WebhookDeliveryV2`): flat, self-describing, with the document number,
    kind, amounts, counterparty, company and Peppol identifiers, the MLS /
    TDD outcome where relevant and the document download links. Webhooks
    created before payload versions existed, and any webhook set to
    `payloadVersion: "1"`, keep the original envelope (`WebhookDelivery`).
    Event types are listed under their v2 names with the legacy name each
    one is also known by; a subscription may use either name.
  contact:
    name: AZDAN Platform Team
    email: support@azdanapps.com
  license:
    name: Proprietary
    url: https://azdanapps.com/terms
  x-azdan-generated:
    from: azdan-platform-api/scripts/lib/developerContract.js
    contractDigest: 5e6a11f9aac68369
    specification: PINT-AE 1.0.4
    customizationId: urn:peppol:pint:billing-1@ae-1
    profileId: urn:peppol:bis:billing
    doNotEdit: Rendered by azdan-platform-api/scripts/generate-developer-examples.js from the structural template and the developer contract.
security:
  - ApiKeyBearer: []
tags:
  - name: Peppol Validation
    description: Dry-run document validation against PINT/BIS rules.
  - name: Peppol Submission
    description: Submit invoices and credit notes for Peppol network delivery.
  - name: Peppol Transactions
    description: Query, filter, and retrieve transaction details.
  - name: Transaction Documents
    description: Secure per-document downloads referenced by the unified `documents` object.
  - name: Webhooks
    description: Webhook event schemas and lifecycle documentation.
paths:
  /api/integrations/peppol/validate:
    post:
      operationId: validateDocument
      summary: Validate a Peppol document
      description: |
        Dry-run validation. Checks your document against PINT/BIS Schematron
        rules without creating a transaction or contacting the Peppol network.
        Safe to call repeatedly during development.
      tags:
        - Peppol Validation
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ValidateRequest"
            examples:
              jsonMode:
                summary: JSON mode — Minimal Tax Invoice (380)
                description: The smallest request the API accepts for a UAE tax invoice. Start here and add only what your business case needs.
                value:
                  inputType: json
                  environment: test
                  documentType: invoice
                  senderPeppolId: "0235:1000000001"
                  receiverPeppolId: "0235:1000000002"
                  payload:
                    invoiceKind: tax
                    invoiceNumber: INV-2026-000123
                    uniqueIdentifierNumber: 3f2504e0-4f89-41d3-9a0c-000000000005
                    issueDate: "2026-09-16"
                    dueDate: "2026-10-16"
                    currency: AED
                    transactionTypeCode: "00000000"
                    paymentMeansCode: "30"
                    paymentAccountId: AE070331234567890123456
                    supplier:
                      name: AZDAN Sample Supplier LLC
                      schemeId: "0235"
                      peppolId: "1000000001"
                      taxId: "100000000000103"
                      legalRegistrationId: CN-1234567
                      legalRegistrationType: TL
                      legalRegistrationAuthorityName: Department of Economic Development Dubai
                      address:
                        streetName: Sheikh Zayed Road 12
                        cityName: Dubai
                        countrySubentity: DXB
                        countryCode: AE
                    customer:
                      name: Emirates Buyer Trading LLC
                      schemeId: "0235"
                      peppolId: "1000000002"
                      taxId: "100000000000203"
                      address:
                        streetName: Corniche Road 88
                        cityName: Abu Dhabi
                        countrySubentity: AUH
                        countryCode: AE
                    lines:
                      - id: "1"
                        quantity: "10"
                        unitCode: EA
                        lineExtensionAmount: "1000.00"
                        price:
                          priceAmount: "100.00"
                        item:
                          name: Consulting services
                          description: Professional services for September 2026
                        tax:
                          category: S
                          rate: "5"
                    taxTotal:
                      taxAmount: "50.00"
                      taxSubtotals:
                        - category: S
                          percent: "5.00"
                          taxableAmount: "1000.00"
                          taxAmount: "50.00"
                    legalMonetaryTotal:
                      lineExtensionAmount: "1000.00"
                      taxExclusiveAmount: "1000.00"
                      taxInclusiveAmount: "1050.00"
                      payableAmount: "1050.00"
              xmlMode:
                summary: XML mode — UAE Tax Invoice (380)
                description: The standard VAT invoice. Carries all 51 MoF mandatory Tax Invoice fields. The xml value is the UBL 2.1 document the API builds for the JSON example of the same name; it passes PINT-AE 1.0.4.
                value:
                  inputType: xml
                  environment: test
                  documentType: invoice
                  senderPeppolId: "0235:1000000001"
                  receiverPeppolId: "0235:1000000002"
                  xml: |-
                    <?xml version="1.0" encoding="UTF-8"?>
                    <Invoice
                      xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
                      xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
                      xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">
                      <cbc:CustomizationID>urn:peppol:pint:billing-1@ae-1</cbc:CustomizationID>
                      <cbc:ProfileID>urn:peppol:bis:billing</cbc:ProfileID>
                      <cbc:ProfileExecutionID>00000000</cbc:ProfileExecutionID>
                      <cbc:ID>INV-2026-000123</cbc:ID>
                      <cbc:UUID>3f2504e0-4f89-41d3-9a0c-000000000001</cbc:UUID>
                      <cbc:IssueDate>2026-09-16</cbc:IssueDate>
                      <cbc:DueDate>2026-10-16</cbc:DueDate>
                      <cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>
                      <cbc:Note>Thank you for your business.</cbc:Note>
                      <cbc:DocumentCurrencyCode>AED</cbc:DocumentCurrencyCode>
                      <cac:AccountingSupplierParty>
                        <cac:Party>
                          <cbc:EndpointID schemeID="0235">1000000001</cbc:EndpointID>
                          <cac:PartyName><cbc:Name>AZDAN Sample Supplier LLC</cbc:Name></cac:PartyName>
                          <cac:PostalAddress>
                            <cbc:StreetName>Sheikh Zayed Road 12</cbc:StreetName>
                            <cbc:AdditionalStreetName>Office 401</cbc:AdditionalStreetName>
                            <cbc:CityName>Dubai</cbc:CityName>
                            <cbc:PostalZone>00000</cbc:PostalZone>
                            <cbc:CountrySubentity>DXB</cbc:CountrySubentity>
                            <cac:Country><cbc:IdentificationCode>AE</cbc:IdentificationCode></cac:Country>
                          </cac:PostalAddress>
                          <cac:PartyTaxScheme>
                            <cbc:CompanyID>100000000000103</cbc:CompanyID>
                            <cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme>
                          </cac:PartyTaxScheme>
                          <cac:PartyLegalEntity>
                            <cbc:RegistrationName>AZDAN Sample Supplier LLC</cbc:RegistrationName>
                            <cbc:CompanyID schemeAgencyID="TL" schemeAgencyName="Department of Economic Development Dubai">CN-1234567</cbc:CompanyID>
                          </cac:PartyLegalEntity>
                        </cac:Party></cac:AccountingSupplierParty>
                      <cac:AccountingCustomerParty>
                        <cac:Party>
                          <cbc:EndpointID schemeID="0235">1000000002</cbc:EndpointID>
                          <cac:PartyName><cbc:Name>Emirates Buyer Trading LLC</cbc:Name></cac:PartyName>
                          <cac:PostalAddress>
                            <cbc:StreetName>Corniche Road 88</cbc:StreetName>
                            <cbc:CityName>Abu Dhabi</cbc:CityName>
                            <cbc:PostalZone>11111</cbc:PostalZone>
                            <cbc:CountrySubentity>AUH</cbc:CountrySubentity>
                            <cac:Country><cbc:IdentificationCode>AE</cbc:IdentificationCode></cac:Country>
                          </cac:PostalAddress>
                          <cac:PartyTaxScheme>
                            <cbc:CompanyID>100000000000203</cbc:CompanyID>
                            <cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme>
                          </cac:PartyTaxScheme>
                          <cac:PartyLegalEntity>
                            <cbc:RegistrationName>Emirates Buyer Trading LLC</cbc:RegistrationName>
                          </cac:PartyLegalEntity>
                        </cac:Party></cac:AccountingCustomerParty>
                      <cac:PaymentMeans>
                        <cbc:PaymentMeansCode>30</cbc:PaymentMeansCode>
                        <cac:PayeeFinancialAccount><cbc:ID>AE070331234567890123456</cbc:ID></cac:PayeeFinancialAccount>
                      </cac:PaymentMeans>
                      <cac:PaymentTerms>
                        <cbc:Note>Net 30 days</cbc:Note>
                      </cac:PaymentTerms>
                      <cac:TaxTotal>
                        <cbc:TaxAmount currencyID="AED">50.00</cbc:TaxAmount>
                        <cac:TaxSubtotal>
                          <cbc:TaxableAmount currencyID="AED">1000.00</cbc:TaxableAmount>
                          <cbc:TaxAmount currencyID="AED">50.00</cbc:TaxAmount>
                          <cac:TaxCategory>
                            <cbc:ID>S</cbc:ID>
                            <cbc:Percent>5.00</cbc:Percent>
                            <cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme>
                          </cac:TaxCategory>
                        </cac:TaxSubtotal>
                      </cac:TaxTotal>
                      <cac:LegalMonetaryTotal>
                        <cbc:LineExtensionAmount currencyID="AED">1000.00</cbc:LineExtensionAmount>
                        <cbc:TaxExclusiveAmount currencyID="AED">1000.00</cbc:TaxExclusiveAmount>
                        <cbc:TaxInclusiveAmount currencyID="AED">1050.00</cbc:TaxInclusiveAmount>
                        <cbc:PayableAmount currencyID="AED">1050.00</cbc:PayableAmount>
                      </cac:LegalMonetaryTotal>
                      <cac:InvoiceLine>
                        <cbc:ID>1</cbc:ID>
                        <cbc:InvoicedQuantity unitCode="EA">10</cbc:InvoicedQuantity>
                        <cbc:LineExtensionAmount currencyID="AED">1000.00</cbc:LineExtensionAmount>
                        <cac:Item>
                            <cbc:Description>Professional services for September 2026</cbc:Description>
                          <cbc:Name>Consulting services</cbc:Name>
                          <cac:ClassifiedTaxCategory>
                            <cbc:ID>S</cbc:ID>
                            <cbc:Percent>5.00</cbc:Percent>
                            <cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme>
                          </cac:ClassifiedTaxCategory>
                        </cac:Item>
                        <cac:Price>
                          <cbc:PriceAmount currencyID="AED">100.00</cbc:PriceAmount>
                          <cbc:BaseQuantity unitCode="EA">1</cbc:BaseQuantity>
                          <cac:AllowanceCharge>
                            <cbc:ChargeIndicator>false</cbc:ChargeIndicator>
                            <cbc:Amount currencyID="AED">20.00</cbc:Amount>
                            <cbc:BaseAmount currencyID="AED">120.00</cbc:BaseAmount>
                          </cac:AllowanceCharge>
                        </cac:Price>
                        <cac:ItemPriceExtension>
                          <cbc:Amount currencyID="AED">1000.00</cbc:Amount>
                          <cac:TaxTotal>
                            <cbc:TaxAmount currencyID="AED">50.00</cbc:TaxAmount>
                          </cac:TaxTotal>
                        </cac:ItemPriceExtension>
                      </cac:InvoiceLine>
                    </Invoice>
              creditNoteJsonMode:
                summary: JSON mode — UAE Tax Credit Note (381) (381)
                description: Reverses a tax invoice. Amounts stay POSITIVE; the document type says it is a credit. Needs a reason code and the original invoice reference.
                value:
                  inputType: json
                  environment: test
                  documentType: creditNote
                  senderPeppolId: "0235:1000000001"
                  receiverPeppolId: "0235:1000000002"
                  payload:
                    invoiceKind: tax
                    invoiceNumber: CN-2026-000123
                    uniqueIdentifierNumber: 3f2504e0-4f89-41d3-9a0c-000000000002
                    issueDate: "2026-09-16"
                    currency: AED
                    transactionTypeCode: "00000000"
                    note: Credit for returned services.
                    creditNoteReasonCode: DL8.61.1.D
                    billingReference:
                      invoiceId: INV-2026-000123
                      issueDate: "2026-09-16"
                    supplier:
                      name: AZDAN Sample Supplier LLC
                      schemeId: "0235"
                      peppolId: "1000000001"
                      taxId: "100000000000103"
                      legalRegistrationId: CN-1234567
                      legalRegistrationType: TL
                      legalRegistrationAuthorityName: Department of Economic Development Dubai
                      address:
                        streetName: Sheikh Zayed Road 12
                        additionalStreetName: Office 401
                        cityName: Dubai
                        postalZone: "00000"
                        countrySubentity: DXB
                        countryCode: AE
                    customer:
                      name: Emirates Buyer Trading LLC
                      schemeId: "0235"
                      peppolId: "1000000002"
                      taxId: "100000000000203"
                      address:
                        streetName: Corniche Road 88
                        cityName: Abu Dhabi
                        postalZone: "11111"
                        countrySubentity: AUH
                        countryCode: AE
                    lines:
                      - id: "1"
                        quantity: "10"
                        unitCode: EA
                        lineExtensionAmount: "1000.00"
                        price:
                          priceAmount: "100.00"
                        item:
                          name: Consulting services
                          description: Professional services for September 2026
                        tax:
                          category: S
                          rate: "5"
                    taxTotal:
                      taxAmount: "50.00"
                      taxSubtotals:
                        - category: S
                          percent: "5.00"
                          taxableAmount: "1000.00"
                          taxAmount: "50.00"
                    legalMonetaryTotal:
                      lineExtensionAmount: "1000.00"
                      taxExclusiveAmount: "1000.00"
                      taxInclusiveAmount: "1050.00"
                      payableAmount: "1050.00"
              creditNoteXmlMode:
                summary: XML mode — UAE Tax Credit Note (381)
                description: Reverses a tax invoice. Amounts stay POSITIVE; the document type says it is a credit. Needs a reason code and the original invoice reference. The xml value is the UBL 2.1 document the API builds for the JSON example of the same name; it passes PINT-AE 1.0.4.
                value:
                  inputType: xml
                  environment: test
                  documentType: creditNote
                  senderPeppolId: "0235:1000000001"
                  receiverPeppolId: "0235:1000000002"
                  xml: |-
                    <?xml version="1.0" encoding="UTF-8"?>
                    <CreditNote
                      xmlns="urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2"
                      xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
                      xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">
                      <cbc:CustomizationID>urn:peppol:pint:billing-1@ae-1</cbc:CustomizationID>
                      <cbc:ProfileID>urn:peppol:bis:billing</cbc:ProfileID>
                      <cbc:ProfileExecutionID>00000000</cbc:ProfileExecutionID>
                      <cbc:ID>CN-2026-000123</cbc:ID>
                      <cbc:UUID>3f2504e0-4f89-41d3-9a0c-000000000002</cbc:UUID>
                      <cbc:IssueDate>2026-09-16</cbc:IssueDate>
                      <cbc:CreditNoteTypeCode>381</cbc:CreditNoteTypeCode>
                      <cbc:Note>Credit for returned services.</cbc:Note>
                      <cbc:DocumentCurrencyCode>AED</cbc:DocumentCurrencyCode>
                      <cac:DiscrepancyResponse>
                        <cbc:ResponseCode>DL8.61.1.D</cbc:ResponseCode>
                      </cac:DiscrepancyResponse>
                      <cac:BillingReference>
                        <cac:InvoiceDocumentReference>
                          <cbc:ID>INV-2026-000123</cbc:ID>
                          <cbc:IssueDate>2026-09-16</cbc:IssueDate>
                        </cac:InvoiceDocumentReference>
                      </cac:BillingReference>
                      <cac:AccountingSupplierParty>
                        <cac:Party>
                          <cbc:EndpointID schemeID="0235">1000000001</cbc:EndpointID>
                          <cac:PartyName><cbc:Name>AZDAN Sample Supplier LLC</cbc:Name></cac:PartyName>
                          <cac:PostalAddress>
                            <cbc:StreetName>Sheikh Zayed Road 12</cbc:StreetName>
                            <cbc:AdditionalStreetName>Office 401</cbc:AdditionalStreetName>
                            <cbc:CityName>Dubai</cbc:CityName>
                            <cbc:PostalZone>00000</cbc:PostalZone>
                            <cbc:CountrySubentity>DXB</cbc:CountrySubentity>
                            <cac:Country><cbc:IdentificationCode>AE</cbc:IdentificationCode></cac:Country>
                          </cac:PostalAddress>
                          <cac:PartyTaxScheme>
                            <cbc:CompanyID>100000000000103</cbc:CompanyID>
                            <cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme>
                          </cac:PartyTaxScheme>
                          <cac:PartyLegalEntity>
                            <cbc:RegistrationName>AZDAN Sample Supplier LLC</cbc:RegistrationName>
                            <cbc:CompanyID schemeAgencyID="TL" schemeAgencyName="Department of Economic Development Dubai">CN-1234567</cbc:CompanyID>
                          </cac:PartyLegalEntity>
                        </cac:Party></cac:AccountingSupplierParty>
                      <cac:AccountingCustomerParty>
                        <cac:Party>
                          <cbc:EndpointID schemeID="0235">1000000002</cbc:EndpointID>
                          <cac:PartyName><cbc:Name>Emirates Buyer Trading LLC</cbc:Name></cac:PartyName>
                          <cac:PostalAddress>
                            <cbc:StreetName>Corniche Road 88</cbc:StreetName>
                            <cbc:CityName>Abu Dhabi</cbc:CityName>
                            <cbc:PostalZone>11111</cbc:PostalZone>
                            <cbc:CountrySubentity>AUH</cbc:CountrySubentity>
                            <cac:Country><cbc:IdentificationCode>AE</cbc:IdentificationCode></cac:Country>
                          </cac:PostalAddress>
                          <cac:PartyTaxScheme>
                            <cbc:CompanyID>100000000000203</cbc:CompanyID>
                            <cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme>
                          </cac:PartyTaxScheme>
                          <cac:PartyLegalEntity>
                            <cbc:RegistrationName>Emirates Buyer Trading LLC</cbc:RegistrationName>
                          </cac:PartyLegalEntity>
                        </cac:Party></cac:AccountingCustomerParty>
                      <cac:TaxTotal>
                        <cbc:TaxAmount currencyID="AED">50.00</cbc:TaxAmount>
                        <cac:TaxSubtotal>
                          <cbc:TaxableAmount currencyID="AED">1000.00</cbc:TaxableAmount>
                          <cbc:TaxAmount currencyID="AED">50.00</cbc:TaxAmount>
                          <cac:TaxCategory>
                            <cbc:ID>S</cbc:ID>
                            <cbc:Percent>5.00</cbc:Percent>
                            <cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme>
                          </cac:TaxCategory>
                        </cac:TaxSubtotal>
                      </cac:TaxTotal>
                      <cac:LegalMonetaryTotal>
                        <cbc:LineExtensionAmount currencyID="AED">1000.00</cbc:LineExtensionAmount>
                        <cbc:TaxExclusiveAmount currencyID="AED">1000.00</cbc:TaxExclusiveAmount>
                        <cbc:TaxInclusiveAmount currencyID="AED">1050.00</cbc:TaxInclusiveAmount>
                        <cbc:PayableAmount currencyID="AED">1050.00</cbc:PayableAmount>
                      </cac:LegalMonetaryTotal>
                      <cac:CreditNoteLine>
                        <cbc:ID>1</cbc:ID>
                        <cbc:CreditedQuantity unitCode="EA">10</cbc:CreditedQuantity>
                        <cbc:LineExtensionAmount currencyID="AED">1000.00</cbc:LineExtensionAmount>
                        <cac:Item>
                            <cbc:Description>Professional services for September 2026</cbc:Description>
                          <cbc:Name>Consulting services</cbc:Name>
                          <cac:ClassifiedTaxCategory>
                            <cbc:ID>S</cbc:ID>
                            <cbc:Percent>5.00</cbc:Percent>
                            <cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme>
                          </cac:ClassifiedTaxCategory>
                        </cac:Item>
                        <cac:Price>
                          <cbc:PriceAmount currencyID="AED">100.00</cbc:PriceAmount>
                          <cbc:BaseQuantity unitCode="EA">1</cbc:BaseQuantity>
                          <cac:AllowanceCharge>
                            <cbc:ChargeIndicator>false</cbc:ChargeIndicator>
                            <cbc:Amount currencyID="AED">0.00</cbc:Amount>
                            <cbc:BaseAmount currencyID="AED">100.00</cbc:BaseAmount>
                          </cac:AllowanceCharge>
                        </cac:Price>
                        <cac:ItemPriceExtension>
                          <cbc:Amount currencyID="AED">1000.00</cbc:Amount>
                          <cac:TaxTotal>
                            <cbc:TaxAmount currencyID="AED">50.00</cbc:TaxAmount>
                          </cac:TaxTotal>
                        </cac:ItemPriceExtension>
                      </cac:CreditNoteLine>
                    </CreditNote>
              commercialInvoiceJsonMode:
                summary: JSON mode — UAE Commercial Invoice (480) (480)
                description: "Issued when no VAT is charged. Carries all 49 MoF mandatory Commercial Invoice fields: the seller states its TIN instead of a VAT TRN, the buyer its legal registration, and every tax category is E, O or Z."
                value:
                  inputType: json
                  environment: test
                  documentType: invoice
                  senderPeppolId: "0235:1000000001"
                  receiverPeppolId: "0235:1000000002"
                  payload:
                    invoiceKind: commercial
                    invoiceNumber: CINV-2026-000123
                    uniqueIdentifierNumber: 3f2504e0-4f89-41d3-9a0c-000000000003
                    issueDate: "2026-09-16"
                    dueDate: "2026-10-16"
                    currency: AED
                    transactionTypeCode: "00000000"
                    note: Thank you for your business.
                    paymentMeansCode: "30"
                    paymentAccountId: AE070331234567890123456
                    paymentTerms:
                      note: Net 30 days
                    supplier:
                      name: AZDAN Sample Supplier LLC
                      schemeId: "0235"
                      peppolId: "1000000001"
                      taxRegistrationId: "1000000001"
                      taxSchemeId: TIN
                      legalRegistrationId: CN-1234567
                      legalRegistrationType: TL
                      legalRegistrationAuthorityName: Department of Economic Development Dubai
                      address:
                        streetName: Sheikh Zayed Road 12
                        additionalStreetName: Office 401
                        cityName: Dubai
                        postalZone: "00000"
                        countrySubentity: DXB
                        countryCode: AE
                    customer:
                      name: Emirates Buyer Trading LLC
                      schemeId: "0235"
                      peppolId: "1000000002"
                      legalRegistrationId: CN-7654321
                      legalRegistrationType: CL
                      legalRegistrationAuthorityName: Abu Dhabi Department of Economic Development
                      address:
                        streetName: Corniche Road 88
                        cityName: Abu Dhabi
                        postalZone: "11111"
                        countrySubentity: AUH
                        countryCode: AE
                    lines:
                      - id: "1"
                        quantity: "10"
                        unitCode: EA
                        lineExtensionAmount: "1000.00"
                        price:
                          priceAmount: "100.00"
                          grossPriceAmount: "120.00"
                          baseQuantity: "1"
                        item:
                          name: Consulting services
                          description: Professional services for September 2026
                        tax:
                          category: Z
                          rate: "0"
                    taxTotal:
                      taxAmount: "0.00"
                      taxSubtotals:
                        - category: Z
                          percent: "0.00"
                          taxableAmount: "1000.00"
                          taxAmount: "0.00"
                    legalMonetaryTotal:
                      lineExtensionAmount: "1000.00"
                      taxExclusiveAmount: "1000.00"
                      taxInclusiveAmount: "1000.00"
                      payableAmount: "1000.00"
              commercialInvoiceXmlMode:
                summary: XML mode — UAE Commercial Invoice (480)
                description: "Issued when no VAT is charged. Carries all 49 MoF mandatory Commercial Invoice fields: the seller states its TIN instead of a VAT TRN, the buyer its legal registration, and every tax category is E, O or Z. The xml value is the UBL 2.1 document the API builds for the JSON example of the same name; it passes PINT-AE 1.0.4."
                value:
                  inputType: xml
                  environment: test
                  documentType: invoice
                  senderPeppolId: "0235:1000000001"
                  receiverPeppolId: "0235:1000000002"
                  xml: |-
                    <?xml version="1.0" encoding="UTF-8"?>
                    <Invoice
                      xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
                      xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
                      xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">
                      <cbc:CustomizationID>urn:peppol:pint:billing-1@ae-1</cbc:CustomizationID>
                      <cbc:ProfileID>urn:peppol:bis:billing</cbc:ProfileID>
                      <cbc:ProfileExecutionID>00000000</cbc:ProfileExecutionID>
                      <cbc:ID>CINV-2026-000123</cbc:ID>
                      <cbc:UUID>3f2504e0-4f89-41d3-9a0c-000000000003</cbc:UUID>
                      <cbc:IssueDate>2026-09-16</cbc:IssueDate>
                      <cbc:DueDate>2026-10-16</cbc:DueDate>
                      <cbc:InvoiceTypeCode>480</cbc:InvoiceTypeCode>
                      <cbc:Note>Thank you for your business.</cbc:Note>
                      <cbc:DocumentCurrencyCode>AED</cbc:DocumentCurrencyCode>
                      <cac:AccountingSupplierParty>
                        <cac:Party>
                          <cbc:EndpointID schemeID="0235">1000000001</cbc:EndpointID>
                          <cac:PartyName><cbc:Name>AZDAN Sample Supplier LLC</cbc:Name></cac:PartyName>
                          <cac:PostalAddress>
                            <cbc:StreetName>Sheikh Zayed Road 12</cbc:StreetName>
                            <cbc:AdditionalStreetName>Office 401</cbc:AdditionalStreetName>
                            <cbc:CityName>Dubai</cbc:CityName>
                            <cbc:PostalZone>00000</cbc:PostalZone>
                            <cbc:CountrySubentity>DXB</cbc:CountrySubentity>
                            <cac:Country><cbc:IdentificationCode>AE</cbc:IdentificationCode></cac:Country>
                          </cac:PostalAddress>
                          <cac:PartyTaxScheme>
                            <cbc:CompanyID>1000000001</cbc:CompanyID>
                            <cac:TaxScheme><cbc:ID>TIN</cbc:ID></cac:TaxScheme>
                          </cac:PartyTaxScheme>
                          <cac:PartyLegalEntity>
                            <cbc:RegistrationName>AZDAN Sample Supplier LLC</cbc:RegistrationName>
                            <cbc:CompanyID schemeAgencyID="TL" schemeAgencyName="Department of Economic Development Dubai">CN-1234567</cbc:CompanyID>
                          </cac:PartyLegalEntity>
                        </cac:Party></cac:AccountingSupplierParty>
                      <cac:AccountingCustomerParty>
                        <cac:Party>
                          <cbc:EndpointID schemeID="0235">1000000002</cbc:EndpointID>
                          <cac:PartyName><cbc:Name>Emirates Buyer Trading LLC</cbc:Name></cac:PartyName>
                          <cac:PostalAddress>
                            <cbc:StreetName>Corniche Road 88</cbc:StreetName>
                            <cbc:CityName>Abu Dhabi</cbc:CityName>
                            <cbc:PostalZone>11111</cbc:PostalZone>
                            <cbc:CountrySubentity>AUH</cbc:CountrySubentity>
                            <cac:Country><cbc:IdentificationCode>AE</cbc:IdentificationCode></cac:Country>
                          </cac:PostalAddress>
                          <cac:PartyLegalEntity>
                            <cbc:RegistrationName>Emirates Buyer Trading LLC</cbc:RegistrationName>
                            <cbc:CompanyID schemeAgencyID="CL" schemeAgencyName="Abu Dhabi Department of Economic Development">CN-7654321</cbc:CompanyID>
                          </cac:PartyLegalEntity>
                        </cac:Party></cac:AccountingCustomerParty>
                      <cac:PaymentMeans>
                        <cbc:PaymentMeansCode>30</cbc:PaymentMeansCode>
                        <cac:PayeeFinancialAccount><cbc:ID>AE070331234567890123456</cbc:ID></cac:PayeeFinancialAccount>
                      </cac:PaymentMeans>
                      <cac:PaymentTerms>
                        <cbc:Note>Net 30 days</cbc:Note>
                      </cac:PaymentTerms>
                      <cac:TaxTotal>
                        <cbc:TaxAmount currencyID="AED">0.00</cbc:TaxAmount>
                        <cac:TaxSubtotal>
                          <cbc:TaxableAmount currencyID="AED">1000.00</cbc:TaxableAmount>
                          <cbc:TaxAmount currencyID="AED">0.00</cbc:TaxAmount>
                          <cac:TaxCategory>
                            <cbc:ID>Z</cbc:ID>
                            <cbc:Percent>0.00</cbc:Percent>
                            <cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme>
                          </cac:TaxCategory>
                        </cac:TaxSubtotal>
                      </cac:TaxTotal>
                      <cac:LegalMonetaryTotal>
                        <cbc:LineExtensionAmount currencyID="AED">1000.00</cbc:LineExtensionAmount>
                        <cbc:TaxExclusiveAmount currencyID="AED">1000.00</cbc:TaxExclusiveAmount>
                        <cbc:TaxInclusiveAmount currencyID="AED">1000.00</cbc:TaxInclusiveAmount>
                        <cbc:PayableAmount currencyID="AED">1000.00</cbc:PayableAmount>
                      </cac:LegalMonetaryTotal>
                      <cac:InvoiceLine>
                        <cbc:ID>1</cbc:ID>
                        <cbc:InvoicedQuantity unitCode="EA">10</cbc:InvoicedQuantity>
                        <cbc:LineExtensionAmount currencyID="AED">1000.00</cbc:LineExtensionAmount>
                        <cac:Item>
                            <cbc:Description>Professional services for September 2026</cbc:Description>
                          <cbc:Name>Consulting services</cbc:Name>
                          <cac:ClassifiedTaxCategory>
                            <cbc:ID>Z</cbc:ID>
                            <cbc:Percent>0.00</cbc:Percent>
                            <cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme>
                          </cac:ClassifiedTaxCategory>
                        </cac:Item>
                        <cac:Price>
                          <cbc:PriceAmount currencyID="AED">100.00</cbc:PriceAmount>
                          <cbc:BaseQuantity unitCode="EA">1</cbc:BaseQuantity>
                          <cac:AllowanceCharge>
                            <cbc:ChargeIndicator>false</cbc:ChargeIndicator>
                            <cbc:Amount currencyID="AED">20.00</cbc:Amount>
                            <cbc:BaseAmount currencyID="AED">120.00</cbc:BaseAmount>
                          </cac:AllowanceCharge>
                        </cac:Price>
                        <cac:ItemPriceExtension>
                          <cbc:Amount currencyID="AED">1000.00</cbc:Amount>
                          <cac:TaxTotal>
                            <cbc:TaxAmount currencyID="AED">0.00</cbc:TaxAmount>
                          </cac:TaxTotal>
                        </cac:ItemPriceExtension>
                      </cac:InvoiceLine>
                    </Invoice>
              commercialCreditNoteJsonMode:
                summary: JSON mode — UAE Commercial Credit Note (81) (81)
                description: Reverses a commercial invoice. Same identity rules as 480.
                value:
                  inputType: json
                  environment: test
                  documentType: creditNote
                  senderPeppolId: "0235:1000000001"
                  receiverPeppolId: "0235:1000000002"
                  payload:
                    invoiceKind: commercial
                    invoiceNumber: CCN-2026-000123
                    uniqueIdentifierNumber: 3f2504e0-4f89-41d3-9a0c-000000000004
                    issueDate: "2026-09-16"
                    currency: AED
                    transactionTypeCode: "00000000"
                    note: Credit for returned goods.
                    creditNoteReasonCode: DL8.61.1.D
                    billingReference:
                      invoiceId: CINV-2026-000123
                      issueDate: "2026-09-16"
                    supplier:
                      name: AZDAN Sample Supplier LLC
                      schemeId: "0235"
                      peppolId: "1000000001"
                      taxRegistrationId: "1000000001"
                      taxSchemeId: TIN
                      legalRegistrationId: CN-1234567
                      legalRegistrationType: TL
                      legalRegistrationAuthorityName: Department of Economic Development Dubai
                      address:
                        streetName: Sheikh Zayed Road 12
                        additionalStreetName: Office 401
                        cityName: Dubai
                        postalZone: "00000"
                        countrySubentity: DXB
                        countryCode: AE
                    customer:
                      name: Emirates Buyer Trading LLC
                      schemeId: "0235"
                      peppolId: "1000000002"
                      legalRegistrationId: CN-7654321
                      legalRegistrationType: CL
                      legalRegistrationAuthorityName: Abu Dhabi Department of Economic Development
                      address:
                        streetName: Corniche Road 88
                        cityName: Abu Dhabi
                        postalZone: "11111"
                        countrySubentity: AUH
                        countryCode: AE
                    lines:
                      - id: "1"
                        quantity: "10"
                        unitCode: EA
                        lineExtensionAmount: "1000.00"
                        price:
                          priceAmount: "100.00"
                        item:
                          name: Consulting services
                          description: Professional services for September 2026
                        tax:
                          category: Z
                          rate: "0"
                    taxTotal:
                      taxAmount: "0.00"
                      taxSubtotals:
                        - category: Z
                          percent: "0.00"
                          taxableAmount: "1000.00"
                          taxAmount: "0.00"
                    legalMonetaryTotal:
                      lineExtensionAmount: "1000.00"
                      taxExclusiveAmount: "1000.00"
                      taxInclusiveAmount: "1000.00"
                      payableAmount: "1000.00"
              commercialCreditNoteXmlMode:
                summary: XML mode — UAE Commercial Credit Note (81)
                description: Reverses a commercial invoice. Same identity rules as 480. The xml value is the UBL 2.1 document the API builds for the JSON example of the same name; it passes PINT-AE 1.0.4.
                value:
                  inputType: xml
                  environment: test
                  documentType: creditNote
                  senderPeppolId: "0235:1000000001"
                  receiverPeppolId: "0235:1000000002"
                  xml: |-
                    <?xml version="1.0" encoding="UTF-8"?>
                    <CreditNote
                      xmlns="urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2"
                      xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
                      xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">
                      <cbc:CustomizationID>urn:peppol:pint:billing-1@ae-1</cbc:CustomizationID>
                      <cbc:ProfileID>urn:peppol:bis:billing</cbc:ProfileID>
                      <cbc:ProfileExecutionID>00000000</cbc:ProfileExecutionID>
                      <cbc:ID>CCN-2026-000123</cbc:ID>
                      <cbc:UUID>3f2504e0-4f89-41d3-9a0c-000000000004</cbc:UUID>
                      <cbc:IssueDate>2026-09-16</cbc:IssueDate>
                      <cbc:CreditNoteTypeCode>81</cbc:CreditNoteTypeCode>
                      <cbc:Note>Credit for returned goods.</cbc:Note>
                      <cbc:DocumentCurrencyCode>AED</cbc:DocumentCurrencyCode>
                      <cac:DiscrepancyResponse>
                        <cbc:ResponseCode>DL8.61.1.D</cbc:ResponseCode>
                      </cac:DiscrepancyResponse>
                      <cac:BillingReference>
                        <cac:InvoiceDocumentReference>
                          <cbc:ID>CINV-2026-000123</cbc:ID>
                          <cbc:IssueDate>2026-09-16</cbc:IssueDate>
                        </cac:InvoiceDocumentReference>
                      </cac:BillingReference>
                      <cac:AccountingSupplierParty>
                        <cac:Party>
                          <cbc:EndpointID schemeID="0235">1000000001</cbc:EndpointID>
                          <cac:PartyName><cbc:Name>AZDAN Sample Supplier LLC</cbc:Name></cac:PartyName>
                          <cac:PostalAddress>
                            <cbc:StreetName>Sheikh Zayed Road 12</cbc:StreetName>
                            <cbc:AdditionalStreetName>Office 401</cbc:AdditionalStreetName>
                            <cbc:CityName>Dubai</cbc:CityName>
                            <cbc:PostalZone>00000</cbc:PostalZone>
                            <cbc:CountrySubentity>DXB</cbc:CountrySubentity>
                            <cac:Country><cbc:IdentificationCode>AE</cbc:IdentificationCode></cac:Country>
                          </cac:PostalAddress>
                          <cac:PartyTaxScheme>
                            <cbc:CompanyID>1000000001</cbc:CompanyID>
                            <cac:TaxScheme><cbc:ID>TIN</cbc:ID></cac:TaxScheme>
                          </cac:PartyTaxScheme>
                          <cac:PartyLegalEntity>
                            <cbc:RegistrationName>AZDAN Sample Supplier LLC</cbc:RegistrationName>
                            <cbc:CompanyID schemeAgencyID="TL" schemeAgencyName="Department of Economic Development Dubai">CN-1234567</cbc:CompanyID>
                          </cac:PartyLegalEntity>
                        </cac:Party></cac:AccountingSupplierParty>
                      <cac:AccountingCustomerParty>
                        <cac:Party>
                          <cbc:EndpointID schemeID="0235">1000000002</cbc:EndpointID>
                          <cac:PartyName><cbc:Name>Emirates Buyer Trading LLC</cbc:Name></cac:PartyName>
                          <cac:PostalAddress>
                            <cbc:StreetName>Corniche Road 88</cbc:StreetName>
                            <cbc:CityName>Abu Dhabi</cbc:CityName>
                            <cbc:PostalZone>11111</cbc:PostalZone>
                            <cbc:CountrySubentity>AUH</cbc:CountrySubentity>
                            <cac:Country><cbc:IdentificationCode>AE</cbc:IdentificationCode></cac:Country>
                          </cac:PostalAddress>
                          <cac:PartyLegalEntity>
                            <cbc:RegistrationName>Emirates Buyer Trading LLC</cbc:RegistrationName>
                            <cbc:CompanyID schemeAgencyID="CL" schemeAgencyName="Abu Dhabi Department of Economic Development">CN-7654321</cbc:CompanyID>
                          </cac:PartyLegalEntity>
                        </cac:Party></cac:AccountingCustomerParty>
                      <cac:TaxTotal>
                        <cbc:TaxAmount currencyID="AED">0.00</cbc:TaxAmount>
                        <cac:TaxSubtotal>
                          <cbc:TaxableAmount currencyID="AED">1000.00</cbc:TaxableAmount>
                          <cbc:TaxAmount currencyID="AED">0.00</cbc:TaxAmount>
                          <cac:TaxCategory>
                            <cbc:ID>Z</cbc:ID>
                            <cbc:Percent>0.00</cbc:Percent>
                            <cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme>
                          </cac:TaxCategory>
                        </cac:TaxSubtotal>
                      </cac:TaxTotal>
                      <cac:LegalMonetaryTotal>
                        <cbc:LineExtensionAmount currencyID="AED">1000.00</cbc:LineExtensionAmount>
                        <cbc:TaxExclusiveAmount currencyID="AED">1000.00</cbc:TaxExclusiveAmount>
                        <cbc:TaxInclusiveAmount currencyID="AED">1000.00</cbc:TaxInclusiveAmount>
                        <cbc:PayableAmount currencyID="AED">1000.00</cbc:PayableAmount>
                      </cac:LegalMonetaryTotal>
                      <cac:CreditNoteLine>
                        <cbc:ID>1</cbc:ID>
                        <cbc:CreditedQuantity unitCode="EA">10</cbc:CreditedQuantity>
                        <cbc:LineExtensionAmount currencyID="AED">1000.00</cbc:LineExtensionAmount>
                        <cac:Item>
                            <cbc:Description>Professional services for September 2026</cbc:Description>
                          <cbc:Name>Consulting services</cbc:Name>
                          <cac:ClassifiedTaxCategory>
                            <cbc:ID>Z</cbc:ID>
                            <cbc:Percent>0.00</cbc:Percent>
                            <cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme>
                          </cac:ClassifiedTaxCategory>
                        </cac:Item>
                        <cac:Price>
                          <cbc:PriceAmount currencyID="AED">100.00</cbc:PriceAmount>
                          <cbc:BaseQuantity unitCode="EA">1</cbc:BaseQuantity>
                          <cac:AllowanceCharge>
                            <cbc:ChargeIndicator>false</cbc:ChargeIndicator>
                            <cbc:Amount currencyID="AED">0.00</cbc:Amount>
                            <cbc:BaseAmount currencyID="AED">100.00</cbc:BaseAmount>
                          </cac:AllowanceCharge>
                        </cac:Price>
                        <cac:ItemPriceExtension>
                          <cbc:Amount currencyID="AED">1000.00</cbc:Amount>
                          <cac:TaxTotal>
                            <cbc:TaxAmount currencyID="AED">0.00</cbc:TaxAmount>
                          </cac:TaxTotal>
                        </cac:ItemPriceExtension>
                      </cac:CreditNoteLine>
                    </CreditNote>
              uaeScenarioJsonMode:
                summary: JSON mode — Combined scenarios (380)
                description: "Positions 1, 4, 6 and 8 declared together (mask 10010101): the free-zone beneficiary (BTAE-01), the invoice period (IBG-14), the disclosed-agent principal (BTAE-14) and a deliver-to address abroad (IBG-13). Scenarios combine, and each companion element stays mandatory under its own rule — none is derived from a value the invoice already carries."
                value:
                  inputType: json
                  environment: test
                  documentType: invoice
                  senderPeppolId: "0235:1000000001"
                  receiverPeppolId: "0235:1000000002"
                  payload:
                    invoiceKind: tax
                    invoiceNumber: INV-2026-000123
                    uniqueIdentifierNumber: 3f2504e0-4f89-41d3-9a0c-000000000018
                    issueDate: "2026-09-16"
                    dueDate: "2026-10-16"
                    currency: AED
                    transactionType:
                      freeTradeZone: true
                      summaryInvoice: true
                      disclosedAgentBilling: true
                      export: true
                    invoicePeriod:
                      startDate: "2026-09-01"
                      endDate: "2026-09-30"
                      frequencyCode: MTH
                    paymentMeansCode: "30"
                    paymentAccountId: AE070331234567890123456
                    supplier:
                      name: AZDAN Sample Supplier LLC
                      schemeId: "0235"
                      peppolId: "1000000001"
                      taxId: "100000000000103"
                      legalRegistrationId: CN-1234567
                      legalRegistrationType: TL
                      legalRegistrationAuthorityName: Department of Economic Development Dubai
                      address:
                        streetName: Sheikh Zayed Road 12
                        additionalStreetName: Office 401
                        cityName: Dubai
                        postalZone: "00000"
                        countrySubentity: DXB
                        countryCode: AE
                    customer:
                      name: Emirates Buyer Trading LLC
                      schemeId: "0235"
                      peppolId: "1000000002"
                      taxId: "100000000000203"
                      address:
                        streetName: Corniche Road 88
                        cityName: Abu Dhabi
                        postalZone: "11111"
                        countrySubentity: AUH
                        countryCode: AE
                      beneficiaryId: FZ-BEN-778901
                    agent:
                      principalId: PRINCIPAL-4471
                    delivery:
                      date: "2026-09-25"
                      address:
                        streetName: Hamngatan 4
                        additionalStreetName: Warehouse B
                        cityName: Goteborg
                        postalZone: "41106"
                        countrySubentity: Vastra Gotaland
                        countryCode: SE
                    lines:
                      - id: "1"
                        quantity: "10"
                        unitCode: EA
                        lineExtensionAmount: "1000.00"
                        price:
                          priceAmount: "100.00"
                        item:
                          name: Consulting services
                          description: Professional services for September 2026
                        tax:
                          category: S
                          rate: "5"
                    taxTotal:
                      taxAmount: "50.00"
                      taxSubtotals:
                        - category: S
                          percent: "5.00"
                          taxableAmount: "1000.00"
                          taxAmount: "50.00"
                    legalMonetaryTotal:
                      lineExtensionAmount: "1000.00"
                      taxExclusiveAmount: "1000.00"
                      taxInclusiveAmount: "1050.00"
                      payableAmount: "1050.00"
              exemptionReasonJsonMode:
                summary: JSON mode — Mixed VAT categories (380)
                description: Standard rated (S), zero rated (Z) and exempt (E) lines on one invoice. The VAT breakdown has one entry per category; the exempt line carries a VAT exemption reason code and no rate.
                value:
                  inputType: json
                  environment: test
                  documentType: invoice
                  senderPeppolId: "0235:1000000001"
                  receiverPeppolId: "0235:1000000002"
                  payload:
                    invoiceKind: tax
                    invoiceNumber: INV-2026-000123
                    uniqueIdentifierNumber: 3f2504e0-4f89-41d3-9a0c-000000000017
                    issueDate: "2026-09-16"
                    dueDate: "2026-10-16"
                    currency: AED
                    transactionTypeCode: "00000000"
                    paymentMeansCode: "30"
                    paymentAccountId: AE070331234567890123456
                    supplier:
                      name: AZDAN Sample Supplier LLC
                      schemeId: "0235"
                      peppolId: "1000000001"
                      taxId: "100000000000103"
                      legalRegistrationId: CN-1234567
                      legalRegistrationType: TL
                      legalRegistrationAuthorityName: Department of Economic Development Dubai
                      address:
                        streetName: Sheikh Zayed Road 12
                        additionalStreetName: Office 401
                        cityName: Dubai
                        postalZone: "00000"
                        countrySubentity: DXB
                        countryCode: AE
                    customer:
                      name: Emirates Buyer Trading LLC
                      schemeId: "0235"
                      peppolId: "1000000002"
                      taxId: "100000000000203"
                      address:
                        streetName: Corniche Road 88
                        cityName: Abu Dhabi
                        postalZone: "11111"
                        countrySubentity: AUH
                        countryCode: AE
                    lines:
                      - id: "1"
                        quantity: "10"
                        unitCode: EA
                        lineExtensionAmount: "1000.00"
                        price:
                          priceAmount: "100.00"
                        item:
                          name: Consulting services
                          description: Professional services for September 2026
                        tax:
                          category: S
                          rate: "5"
                      - id: "2"
                        quantity: "10"
                        unitCode: EA
                        lineExtensionAmount: "1000.00"
                        price:
                          priceAmount: "100.00"
                        item:
                          name: International freight
                          description: Zero-rated international transport of goods
                        tax:
                          category: Z
                          rate: "0"
                      - id: "3"
                        quantity: "10"
                        unitCode: EA
                        lineExtensionAmount: "1000.00"
                        price:
                          priceAmount: "100.00"
                        item:
                          name: Financial service fee
                          description: Exempt financial service
                        tax:
                          category: E
                          exemptionReasonCode: VATEX-AE-EXEMPT-FINANCIAL
                    taxTotal:
                      taxAmount: "50.00"
                      taxSubtotals:
                        - category: S
                          percent: "5.00"
                          taxableAmount: "1000.00"
                          taxAmount: "50.00"
                        - category: Z
                          percent: "0.00"
                          taxableAmount: "1000.00"
                          taxAmount: "0.00"
                        - category: E
                          taxableAmount: "1000.00"
                          taxAmount: "0.00"
                    legalMonetaryTotal:
                      lineExtensionAmount: "3000.00"
                      taxExclusiveAmount: "3000.00"
                      taxInclusiveAmount: "3050.00"
                      payableAmount: "3050.00"
      responses:
        "200":
          description: Validation result
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ValidateResponse"
              examples:
                valid:
                  summary: Valid document
                  value:
                    valid: true
                    documentTypeId: urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:peppol:pint:billing-1@ae-1::2.1
                    processId: urn:peppol:bis:billing
                    warnings: []
                    phormSkipped: false
                    normalized:
                      sender: "0235:1000000001"
                      receiver: "0235:1000000002"
                      invoiceNumber: INV-2026-000123
                      issueDate: "2026-09-16"
                      currency: AED
                      payableAmount: 1050
                      invoiceTypeCode: "380"
                      dueDate: "2026-10-16"
                      supplierName: AZDAN Sample Supplier LLC
                      customerName: Emirates Buyer Trading LLC
                      netAmount: 1000
                      taxAmount: 50
        "400":
          $ref: "#/components/responses/ValidationError"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
      x-azdan-scopes:
        - peppol:validate
        - peppol:submit
        - transactions:submit
        - transactions:read
      x-azdan-default-key: true
      x-azdan-contract-key: validate
      x-azdan-access: safe
      x-azdan-expected:
        - "200 valid: true"
        - "400 validation failure (valid: false, error.code)"
        - 401 invalid key
        - 403 insufficient scope
  /api/integrations/peppol/invoices:
    post:
      operationId: submitInvoice
      summary: Submit a Peppol invoice or credit note
      description: |
        Submit a document for Peppol delivery. Validates, creates a transaction,
        and hands off to the access point for AS4 delivery.

        Returns **202 Accepted** — delivery is asynchronous. Subscribe to webhooks
        for real-time status updates.

        Send `Idempotency-Key` as an HTTP header. The key must uniquely identify
        one logical submission. Reuse the same key only when retrying the exact
        same request. Use a new key for a new invoice or credit note.

        The header is authoritative. The legacy request-body field
        `idempotencyKey` is deprecated and supported only for backward
        compatibility; if both are present they must match.
      tags:
        - Peppol Submission
      parameters:
        - $ref: "#/components/parameters/IdempotencyKey"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SubmitRequest"
            examples:
              jsonMode:
                summary: JSON mode — Minimal Tax Invoice (380)
                description: The smallest request the API accepts for a UAE tax invoice. Start here and add only what your business case needs.
                value:
                  inputType: json
                  environment: test
                  documentType: invoice
                  senderPeppolId: "0235:1000000001"
                  receiverPeppolId: "0235:1000000002"
                  payload:
                    invoiceKind: tax
                    invoiceNumber: INV-2026-000123
                    uniqueIdentifierNumber: 3f2504e0-4f89-41d3-9a0c-000000000005
                    issueDate: "2026-09-16"
                    dueDate: "2026-10-16"
                    currency: AED
                    transactionTypeCode: "00000000"
                    paymentMeansCode: "30"
                    paymentAccountId: AE070331234567890123456
                    supplier:
                      name: AZDAN Sample Supplier LLC
                      schemeId: "0235"
                      peppolId: "1000000001"
                      taxId: "100000000000103"
                      legalRegistrationId: CN-1234567
                      legalRegistrationType: TL
                      legalRegistrationAuthorityName: Department of Economic Development Dubai
                      address:
                        streetName: Sheikh Zayed Road 12
                        cityName: Dubai
                        countrySubentity: DXB
                        countryCode: AE
                    customer:
                      name: Emirates Buyer Trading LLC
                      schemeId: "0235"
                      peppolId: "1000000002"
                      taxId: "100000000000203"
                      address:
                        streetName: Corniche Road 88
                        cityName: Abu Dhabi
                        countrySubentity: AUH
                        countryCode: AE
                    lines:
                      - id: "1"
                        quantity: "10"
                        unitCode: EA
                        lineExtensionAmount: "1000.00"
                        price:
                          priceAmount: "100.00"
                        item:
                          name: Consulting services
                          description: Professional services for September 2026
                        tax:
                          category: S
                          rate: "5"
                    taxTotal:
                      taxAmount: "50.00"
                      taxSubtotals:
                        - category: S
                          percent: "5.00"
                          taxableAmount: "1000.00"
                          taxAmount: "50.00"
                    legalMonetaryTotal:
                      lineExtensionAmount: "1000.00"
                      taxExclusiveAmount: "1000.00"
                      taxInclusiveAmount: "1050.00"
                      payableAmount: "1050.00"
              xmlMode:
                summary: XML mode — UAE Tax Invoice (380)
                description: The standard VAT invoice. Carries all 51 MoF mandatory Tax Invoice fields. The xml value is the UBL 2.1 document the API builds for the JSON example of the same name; it passes PINT-AE 1.0.4.
                value:
                  inputType: xml
                  environment: test
                  documentType: invoice
                  senderPeppolId: "0235:1000000001"
                  receiverPeppolId: "0235:1000000002"
                  xml: |-
                    <?xml version="1.0" encoding="UTF-8"?>
                    <Invoice
                      xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
                      xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
                      xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">
                      <cbc:CustomizationID>urn:peppol:pint:billing-1@ae-1</cbc:CustomizationID>
                      <cbc:ProfileID>urn:peppol:bis:billing</cbc:ProfileID>
                      <cbc:ProfileExecutionID>00000000</cbc:ProfileExecutionID>
                      <cbc:ID>INV-2026-000123</cbc:ID>
                      <cbc:UUID>3f2504e0-4f89-41d3-9a0c-000000000001</cbc:UUID>
                      <cbc:IssueDate>2026-09-16</cbc:IssueDate>
                      <cbc:DueDate>2026-10-16</cbc:DueDate>
                      <cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>
                      <cbc:Note>Thank you for your business.</cbc:Note>
                      <cbc:DocumentCurrencyCode>AED</cbc:DocumentCurrencyCode>
                      <cac:AccountingSupplierParty>
                        <cac:Party>
                          <cbc:EndpointID schemeID="0235">1000000001</cbc:EndpointID>
                          <cac:PartyName><cbc:Name>AZDAN Sample Supplier LLC</cbc:Name></cac:PartyName>
                          <cac:PostalAddress>
                            <cbc:StreetName>Sheikh Zayed Road 12</cbc:StreetName>
                            <cbc:AdditionalStreetName>Office 401</cbc:AdditionalStreetName>
                            <cbc:CityName>Dubai</cbc:CityName>
                            <cbc:PostalZone>00000</cbc:PostalZone>
                            <cbc:CountrySubentity>DXB</cbc:CountrySubentity>
                            <cac:Country><cbc:IdentificationCode>AE</cbc:IdentificationCode></cac:Country>
                          </cac:PostalAddress>
                          <cac:PartyTaxScheme>
                            <cbc:CompanyID>100000000000103</cbc:CompanyID>
                            <cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme>
                          </cac:PartyTaxScheme>
                          <cac:PartyLegalEntity>
                            <cbc:RegistrationName>AZDAN Sample Supplier LLC</cbc:RegistrationName>
                            <cbc:CompanyID schemeAgencyID="TL" schemeAgencyName="Department of Economic Development Dubai">CN-1234567</cbc:CompanyID>
                          </cac:PartyLegalEntity>
                        </cac:Party></cac:AccountingSupplierParty>
                      <cac:AccountingCustomerParty>
                        <cac:Party>
                          <cbc:EndpointID schemeID="0235">1000000002</cbc:EndpointID>
                          <cac:PartyName><cbc:Name>Emirates Buyer Trading LLC</cbc:Name></cac:PartyName>
                          <cac:PostalAddress>
                            <cbc:StreetName>Corniche Road 88</cbc:StreetName>
                            <cbc:CityName>Abu Dhabi</cbc:CityName>
                            <cbc:PostalZone>11111</cbc:PostalZone>
                            <cbc:CountrySubentity>AUH</cbc:CountrySubentity>
                            <cac:Country><cbc:IdentificationCode>AE</cbc:IdentificationCode></cac:Country>
                          </cac:PostalAddress>
                          <cac:PartyTaxScheme>
                            <cbc:CompanyID>100000000000203</cbc:CompanyID>
                            <cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme>
                          </cac:PartyTaxScheme>
                          <cac:PartyLegalEntity>
                            <cbc:RegistrationName>Emirates Buyer Trading LLC</cbc:RegistrationName>
                          </cac:PartyLegalEntity>
                        </cac:Party></cac:AccountingCustomerParty>
                      <cac:PaymentMeans>
                        <cbc:PaymentMeansCode>30</cbc:PaymentMeansCode>
                        <cac:PayeeFinancialAccount><cbc:ID>AE070331234567890123456</cbc:ID></cac:PayeeFinancialAccount>
                      </cac:PaymentMeans>
                      <cac:PaymentTerms>
                        <cbc:Note>Net 30 days</cbc:Note>
                      </cac:PaymentTerms>
                      <cac:TaxTotal>
                        <cbc:TaxAmount currencyID="AED">50.00</cbc:TaxAmount>
                        <cac:TaxSubtotal>
                          <cbc:TaxableAmount currencyID="AED">1000.00</cbc:TaxableAmount>
                          <cbc:TaxAmount currencyID="AED">50.00</cbc:TaxAmount>
                          <cac:TaxCategory>
                            <cbc:ID>S</cbc:ID>
                            <cbc:Percent>5.00</cbc:Percent>
                            <cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme>
                          </cac:TaxCategory>
                        </cac:TaxSubtotal>
                      </cac:TaxTotal>
                      <cac:LegalMonetaryTotal>
                        <cbc:LineExtensionAmount currencyID="AED">1000.00</cbc:LineExtensionAmount>
                        <cbc:TaxExclusiveAmount currencyID="AED">1000.00</cbc:TaxExclusiveAmount>
                        <cbc:TaxInclusiveAmount currencyID="AED">1050.00</cbc:TaxInclusiveAmount>
                        <cbc:PayableAmount currencyID="AED">1050.00</cbc:PayableAmount>
                      </cac:LegalMonetaryTotal>
                      <cac:InvoiceLine>
                        <cbc:ID>1</cbc:ID>
                        <cbc:InvoicedQuantity unitCode="EA">10</cbc:InvoicedQuantity>
                        <cbc:LineExtensionAmount currencyID="AED">1000.00</cbc:LineExtensionAmount>
                        <cac:Item>
                            <cbc:Description>Professional services for September 2026</cbc:Description>
                          <cbc:Name>Consulting services</cbc:Name>
                          <cac:ClassifiedTaxCategory>
                            <cbc:ID>S</cbc:ID>
                            <cbc:Percent>5.00</cbc:Percent>
                            <cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme>
                          </cac:ClassifiedTaxCategory>
                        </cac:Item>
                        <cac:Price>
                          <cbc:PriceAmount currencyID="AED">100.00</cbc:PriceAmount>
                          <cbc:BaseQuantity unitCode="EA">1</cbc:BaseQuantity>
                          <cac:AllowanceCharge>
                            <cbc:ChargeIndicator>false</cbc:ChargeIndicator>
                            <cbc:Amount currencyID="AED">20.00</cbc:Amount>
                            <cbc:BaseAmount currencyID="AED">120.00</cbc:BaseAmount>
                          </cac:AllowanceCharge>
                        </cac:Price>
                        <cac:ItemPriceExtension>
                          <cbc:Amount currencyID="AED">1000.00</cbc:Amount>
                          <cac:TaxTotal>
                            <cbc:TaxAmount currencyID="AED">50.00</cbc:TaxAmount>
                          </cac:TaxTotal>
                        </cac:ItemPriceExtension>
                      </cac:InvoiceLine>
                    </Invoice>
              creditNoteJsonMode:
                summary: JSON mode — UAE Tax Credit Note (381) (381)
                description: Reverses a tax invoice. Amounts stay POSITIVE; the document type says it is a credit. Needs a reason code and the original invoice reference.
                value:
                  inputType: json
                  environment: test
                  documentType: creditNote
                  senderPeppolId: "0235:1000000001"
                  receiverPeppolId: "0235:1000000002"
                  payload:
                    invoiceKind: tax
                    invoiceNumber: CN-2026-000123
                    uniqueIdentifierNumber: 3f2504e0-4f89-41d3-9a0c-000000000002
                    issueDate: "2026-09-16"
                    currency: AED
                    transactionTypeCode: "00000000"
                    note: Credit for returned services.
                    creditNoteReasonCode: DL8.61.1.D
                    billingReference:
                      invoiceId: INV-2026-000123
                      issueDate: "2026-09-16"
                    supplier:
                      name: AZDAN Sample Supplier LLC
                      schemeId: "0235"
                      peppolId: "1000000001"
                      taxId: "100000000000103"
                      legalRegistrationId: CN-1234567
                      legalRegistrationType: TL
                      legalRegistrationAuthorityName: Department of Economic Development Dubai
                      address:
                        streetName: Sheikh Zayed Road 12
                        additionalStreetName: Office 401
                        cityName: Dubai
                        postalZone: "00000"
                        countrySubentity: DXB
                        countryCode: AE
                    customer:
                      name: Emirates Buyer Trading LLC
                      schemeId: "0235"
                      peppolId: "1000000002"
                      taxId: "100000000000203"
                      address:
                        streetName: Corniche Road 88
                        cityName: Abu Dhabi
                        postalZone: "11111"
                        countrySubentity: AUH
                        countryCode: AE
                    lines:
                      - id: "1"
                        quantity: "10"
                        unitCode: EA
                        lineExtensionAmount: "1000.00"
                        price:
                          priceAmount: "100.00"
                        item:
                          name: Consulting services
                          description: Professional services for September 2026
                        tax:
                          category: S
                          rate: "5"
                    taxTotal:
                      taxAmount: "50.00"
                      taxSubtotals:
                        - category: S
                          percent: "5.00"
                          taxableAmount: "1000.00"
                          taxAmount: "50.00"
                    legalMonetaryTotal:
                      lineExtensionAmount: "1000.00"
                      taxExclusiveAmount: "1000.00"
                      taxInclusiveAmount: "1050.00"
                      payableAmount: "1050.00"
              creditNoteXmlMode:
                summary: XML mode — UAE Tax Credit Note (381)
                description: Reverses a tax invoice. Amounts stay POSITIVE; the document type says it is a credit. Needs a reason code and the original invoice reference. The xml value is the UBL 2.1 document the API builds for the JSON example of the same name; it passes PINT-AE 1.0.4.
                value:
                  inputType: xml
                  environment: test
                  documentType: creditNote
                  senderPeppolId: "0235:1000000001"
                  receiverPeppolId: "0235:1000000002"
                  xml: |-
                    <?xml version="1.0" encoding="UTF-8"?>
                    <CreditNote
                      xmlns="urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2"
                      xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
                      xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">
                      <cbc:CustomizationID>urn:peppol:pint:billing-1@ae-1</cbc:CustomizationID>
                      <cbc:ProfileID>urn:peppol:bis:billing</cbc:ProfileID>
                      <cbc:ProfileExecutionID>00000000</cbc:ProfileExecutionID>
                      <cbc:ID>CN-2026-000123</cbc:ID>
                      <cbc:UUID>3f2504e0-4f89-41d3-9a0c-000000000002</cbc:UUID>
                      <cbc:IssueDate>2026-09-16</cbc:IssueDate>
                      <cbc:CreditNoteTypeCode>381</cbc:CreditNoteTypeCode>
                      <cbc:Note>Credit for returned services.</cbc:Note>
                      <cbc:DocumentCurrencyCode>AED</cbc:DocumentCurrencyCode>
                      <cac:DiscrepancyResponse>
                        <cbc:ResponseCode>DL8.61.1.D</cbc:ResponseCode>
                      </cac:DiscrepancyResponse>
                      <cac:BillingReference>
                        <cac:InvoiceDocumentReference>
                          <cbc:ID>INV-2026-000123</cbc:ID>
                          <cbc:IssueDate>2026-09-16</cbc:IssueDate>
                        </cac:InvoiceDocumentReference>
                      </cac:BillingReference>
                      <cac:AccountingSupplierParty>
                        <cac:Party>
                          <cbc:EndpointID schemeID="0235">1000000001</cbc:EndpointID>
                          <cac:PartyName><cbc:Name>AZDAN Sample Supplier LLC</cbc:Name></cac:PartyName>
                          <cac:PostalAddress>
                            <cbc:StreetName>Sheikh Zayed Road 12</cbc:StreetName>
                            <cbc:AdditionalStreetName>Office 401</cbc:AdditionalStreetName>
                            <cbc:CityName>Dubai</cbc:CityName>
                            <cbc:PostalZone>00000</cbc:PostalZone>
                            <cbc:CountrySubentity>DXB</cbc:CountrySubentity>
                            <cac:Country><cbc:IdentificationCode>AE</cbc:IdentificationCode></cac:Country>
                          </cac:PostalAddress>
                          <cac:PartyTaxScheme>
                            <cbc:CompanyID>100000000000103</cbc:CompanyID>
                            <cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme>
                          </cac:PartyTaxScheme>
                          <cac:PartyLegalEntity>
                            <cbc:RegistrationName>AZDAN Sample Supplier LLC</cbc:RegistrationName>
                            <cbc:CompanyID schemeAgencyID="TL" schemeAgencyName="Department of Economic Development Dubai">CN-1234567</cbc:CompanyID>
                          </cac:PartyLegalEntity>
                        </cac:Party></cac:AccountingSupplierParty>
                      <cac:AccountingCustomerParty>
                        <cac:Party>
                          <cbc:EndpointID schemeID="0235">1000000002</cbc:EndpointID>
                          <cac:PartyName><cbc:Name>Emirates Buyer Trading LLC</cbc:Name></cac:PartyName>
                          <cac:PostalAddress>
                            <cbc:StreetName>Corniche Road 88</cbc:StreetName>
                            <cbc:CityName>Abu Dhabi</cbc:CityName>
                            <cbc:PostalZone>11111</cbc:PostalZone>
                            <cbc:CountrySubentity>AUH</cbc:CountrySubentity>
                            <cac:Country><cbc:IdentificationCode>AE</cbc:IdentificationCode></cac:Country>
                          </cac:PostalAddress>
                          <cac:PartyTaxScheme>
                            <cbc:CompanyID>100000000000203</cbc:CompanyID>
                            <cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme>
                          </cac:PartyTaxScheme>
                          <cac:PartyLegalEntity>
                            <cbc:RegistrationName>Emirates Buyer Trading LLC</cbc:RegistrationName>
                          </cac:PartyLegalEntity>
                        </cac:Party></cac:AccountingCustomerParty>
                      <cac:TaxTotal>
                        <cbc:TaxAmount currencyID="AED">50.00</cbc:TaxAmount>
                        <cac:TaxSubtotal>
                          <cbc:TaxableAmount currencyID="AED">1000.00</cbc:TaxableAmount>
                          <cbc:TaxAmount currencyID="AED">50.00</cbc:TaxAmount>
                          <cac:TaxCategory>
                            <cbc:ID>S</cbc:ID>
                            <cbc:Percent>5.00</cbc:Percent>
                            <cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme>
                          </cac:TaxCategory>
                        </cac:TaxSubtotal>
                      </cac:TaxTotal>
                      <cac:LegalMonetaryTotal>
                        <cbc:LineExtensionAmount currencyID="AED">1000.00</cbc:LineExtensionAmount>
                        <cbc:TaxExclusiveAmount currencyID="AED">1000.00</cbc:TaxExclusiveAmount>
                        <cbc:TaxInclusiveAmount currencyID="AED">1050.00</cbc:TaxInclusiveAmount>
                        <cbc:PayableAmount currencyID="AED">1050.00</cbc:PayableAmount>
                      </cac:LegalMonetaryTotal>
                      <cac:CreditNoteLine>
                        <cbc:ID>1</cbc:ID>
                        <cbc:CreditedQuantity unitCode="EA">10</cbc:CreditedQuantity>
                        <cbc:LineExtensionAmount currencyID="AED">1000.00</cbc:LineExtensionAmount>
                        <cac:Item>
                            <cbc:Description>Professional services for September 2026</cbc:Description>
                          <cbc:Name>Consulting services</cbc:Name>
                          <cac:ClassifiedTaxCategory>
                            <cbc:ID>S</cbc:ID>
                            <cbc:Percent>5.00</cbc:Percent>
                            <cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme>
                          </cac:ClassifiedTaxCategory>
                        </cac:Item>
                        <cac:Price>
                          <cbc:PriceAmount currencyID="AED">100.00</cbc:PriceAmount>
                          <cbc:BaseQuantity unitCode="EA">1</cbc:BaseQuantity>
                          <cac:AllowanceCharge>
                            <cbc:ChargeIndicator>false</cbc:ChargeIndicator>
                            <cbc:Amount currencyID="AED">0.00</cbc:Amount>
                            <cbc:BaseAmount currencyID="AED">100.00</cbc:BaseAmount>
                          </cac:AllowanceCharge>
                        </cac:Price>
                        <cac:ItemPriceExtension>
                          <cbc:Amount currencyID="AED">1000.00</cbc:Amount>
                          <cac:TaxTotal>
                            <cbc:TaxAmount currencyID="AED">50.00</cbc:TaxAmount>
                          </cac:TaxTotal>
                        </cac:ItemPriceExtension>
                      </cac:CreditNoteLine>
                    </CreditNote>
              commercialInvoiceJsonMode:
                summary: JSON mode — UAE Commercial Invoice (480) (480)
                description: "Issued when no VAT is charged. Carries all 49 MoF mandatory Commercial Invoice fields: the seller states its TIN instead of a VAT TRN, the buyer its legal registration, and every tax category is E, O or Z."
                value:
                  inputType: json
                  environment: test
                  documentType: invoice
                  senderPeppolId: "0235:1000000001"
                  receiverPeppolId: "0235:1000000002"
                  payload:
                    invoiceKind: commercial
                    invoiceNumber: CINV-2026-000123
                    uniqueIdentifierNumber: 3f2504e0-4f89-41d3-9a0c-000000000003
                    issueDate: "2026-09-16"
                    dueDate: "2026-10-16"
                    currency: AED
                    transactionTypeCode: "00000000"
                    note: Thank you for your business.
                    paymentMeansCode: "30"
                    paymentAccountId: AE070331234567890123456
                    paymentTerms:
                      note: Net 30 days
                    supplier:
                      name: AZDAN Sample Supplier LLC
                      schemeId: "0235"
                      peppolId: "1000000001"
                      taxRegistrationId: "1000000001"
                      taxSchemeId: TIN
                      legalRegistrationId: CN-1234567
                      legalRegistrationType: TL
                      legalRegistrationAuthorityName: Department of Economic Development Dubai
                      address:
                        streetName: Sheikh Zayed Road 12
                        additionalStreetName: Office 401
                        cityName: Dubai
                        postalZone: "00000"
                        countrySubentity: DXB
                        countryCode: AE
                    customer:
                      name: Emirates Buyer Trading LLC
                      schemeId: "0235"
                      peppolId: "1000000002"
                      legalRegistrationId: CN-7654321
                      legalRegistrationType: CL
                      legalRegistrationAuthorityName: Abu Dhabi Department of Economic Development
                      address:
                        streetName: Corniche Road 88
                        cityName: Abu Dhabi
                        postalZone: "11111"
                        countrySubentity: AUH
                        countryCode: AE
                    lines:
                      - id: "1"
                        quantity: "10"
                        unitCode: EA
                        lineExtensionAmount: "1000.00"
                        price:
                          priceAmount: "100.00"
                          grossPriceAmount: "120.00"
                          baseQuantity: "1"
                        item:
                          name: Consulting services
                          description: Professional services for September 2026
                        tax:
                          category: Z
                          rate: "0"
                    taxTotal:
                      taxAmount: "0.00"
                      taxSubtotals:
                        - category: Z
                          percent: "0.00"
                          taxableAmount: "1000.00"
                          taxAmount: "0.00"
                    legalMonetaryTotal:
                      lineExtensionAmount: "1000.00"
                      taxExclusiveAmount: "1000.00"
                      taxInclusiveAmount: "1000.00"
                      payableAmount: "1000.00"
              commercialInvoiceXmlMode:
                summary: XML mode — UAE Commercial Invoice (480)
                description: "Issued when no VAT is charged. Carries all 49 MoF mandatory Commercial Invoice fields: the seller states its TIN instead of a VAT TRN, the buyer its legal registration, and every tax category is E, O or Z. The xml value is the UBL 2.1 document the API builds for the JSON example of the same name; it passes PINT-AE 1.0.4."
                value:
                  inputType: xml
                  environment: test
                  documentType: invoice
                  senderPeppolId: "0235:1000000001"
                  receiverPeppolId: "0235:1000000002"
                  xml: |-
                    <?xml version="1.0" encoding="UTF-8"?>
                    <Invoice
                      xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
                      xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
                      xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">
                      <cbc:CustomizationID>urn:peppol:pint:billing-1@ae-1</cbc:CustomizationID>
                      <cbc:ProfileID>urn:peppol:bis:billing</cbc:ProfileID>
                      <cbc:ProfileExecutionID>00000000</cbc:ProfileExecutionID>
                      <cbc:ID>CINV-2026-000123</cbc:ID>
                      <cbc:UUID>3f2504e0-4f89-41d3-9a0c-000000000003</cbc:UUID>
                      <cbc:IssueDate>2026-09-16</cbc:IssueDate>
                      <cbc:DueDate>2026-10-16</cbc:DueDate>
                      <cbc:InvoiceTypeCode>480</cbc:InvoiceTypeCode>
                      <cbc:Note>Thank you for your business.</cbc:Note>
                      <cbc:DocumentCurrencyCode>AED</cbc:DocumentCurrencyCode>
                      <cac:AccountingSupplierParty>
                        <cac:Party>
                          <cbc:EndpointID schemeID="0235">1000000001</cbc:EndpointID>
                          <cac:PartyName><cbc:Name>AZDAN Sample Supplier LLC</cbc:Name></cac:PartyName>
                          <cac:PostalAddress>
                            <cbc:StreetName>Sheikh Zayed Road 12</cbc:StreetName>
                            <cbc:AdditionalStreetName>Office 401</cbc:AdditionalStreetName>
                            <cbc:CityName>Dubai</cbc:CityName>
                            <cbc:PostalZone>00000</cbc:PostalZone>
                            <cbc:CountrySubentity>DXB</cbc:CountrySubentity>
                            <cac:Country><cbc:IdentificationCode>AE</cbc:IdentificationCode></cac:Country>
                          </cac:PostalAddress>
                          <cac:PartyTaxScheme>
                            <cbc:CompanyID>1000000001</cbc:CompanyID>
                            <cac:TaxScheme><cbc:ID>TIN</cbc:ID></cac:TaxScheme>
                          </cac:PartyTaxScheme>
                          <cac:PartyLegalEntity>
                            <cbc:RegistrationName>AZDAN Sample Supplier LLC</cbc:RegistrationName>
                            <cbc:CompanyID schemeAgencyID="TL" schemeAgencyName="Department of Economic Development Dubai">CN-1234567</cbc:CompanyID>
                          </cac:PartyLegalEntity>
                        </cac:Party></cac:AccountingSupplierParty>
                      <cac:AccountingCustomerParty>
                        <cac:Party>
                          <cbc:EndpointID schemeID="0235">1000000002</cbc:EndpointID>
                          <cac:PartyName><cbc:Name>Emirates Buyer Trading LLC</cbc:Name></cac:PartyName>
                          <cac:PostalAddress>
                            <cbc:StreetName>Corniche Road 88</cbc:StreetName>
                            <cbc:CityName>Abu Dhabi</cbc:CityName>
                            <cbc:PostalZone>11111</cbc:PostalZone>
                            <cbc:CountrySubentity>AUH</cbc:CountrySubentity>
                            <cac:Country><cbc:IdentificationCode>AE</cbc:IdentificationCode></cac:Country>
                          </cac:PostalAddress>
                          <cac:PartyLegalEntity>
                            <cbc:RegistrationName>Emirates Buyer Trading LLC</cbc:RegistrationName>
                            <cbc:CompanyID schemeAgencyID="CL" schemeAgencyName="Abu Dhabi Department of Economic Development">CN-7654321</cbc:CompanyID>
                          </cac:PartyLegalEntity>
                        </cac:Party></cac:AccountingCustomerParty>
                      <cac:PaymentMeans>
                        <cbc:PaymentMeansCode>30</cbc:PaymentMeansCode>
                        <cac:PayeeFinancialAccount><cbc:ID>AE070331234567890123456</cbc:ID></cac:PayeeFinancialAccount>
                      </cac:PaymentMeans>
                      <cac:PaymentTerms>
                        <cbc:Note>Net 30 days</cbc:Note>
                      </cac:PaymentTerms>
                      <cac:TaxTotal>
                        <cbc:TaxAmount currencyID="AED">0.00</cbc:TaxAmount>
                        <cac:TaxSubtotal>
                          <cbc:TaxableAmount currencyID="AED">1000.00</cbc:TaxableAmount>
                          <cbc:TaxAmount currencyID="AED">0.00</cbc:TaxAmount>
                          <cac:TaxCategory>
                            <cbc:ID>Z</cbc:ID>
                            <cbc:Percent>0.00</cbc:Percent>
                            <cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme>
                          </cac:TaxCategory>
                        </cac:TaxSubtotal>
                      </cac:TaxTotal>
                      <cac:LegalMonetaryTotal>
                        <cbc:LineExtensionAmount currencyID="AED">1000.00</cbc:LineExtensionAmount>
                        <cbc:TaxExclusiveAmount currencyID="AED">1000.00</cbc:TaxExclusiveAmount>
                        <cbc:TaxInclusiveAmount currencyID="AED">1000.00</cbc:TaxInclusiveAmount>
                        <cbc:PayableAmount currencyID="AED">1000.00</cbc:PayableAmount>
                      </cac:LegalMonetaryTotal>
                      <cac:InvoiceLine>
                        <cbc:ID>1</cbc:ID>
                        <cbc:InvoicedQuantity unitCode="EA">10</cbc:InvoicedQuantity>
                        <cbc:LineExtensionAmount currencyID="AED">1000.00</cbc:LineExtensionAmount>
                        <cac:Item>
                            <cbc:Description>Professional services for September 2026</cbc:Description>
                          <cbc:Name>Consulting services</cbc:Name>
                          <cac:ClassifiedTaxCategory>
                            <cbc:ID>Z</cbc:ID>
                            <cbc:Percent>0.00</cbc:Percent>
                            <cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme>
                          </cac:ClassifiedTaxCategory>
                        </cac:Item>
                        <cac:Price>
                          <cbc:PriceAmount currencyID="AED">100.00</cbc:PriceAmount>
                          <cbc:BaseQuantity unitCode="EA">1</cbc:BaseQuantity>
                          <cac:AllowanceCharge>
                            <cbc:ChargeIndicator>false</cbc:ChargeIndicator>
                            <cbc:Amount currencyID="AED">20.00</cbc:Amount>
                            <cbc:BaseAmount currencyID="AED">120.00</cbc:BaseAmount>
                          </cac:AllowanceCharge>
                        </cac:Price>
                        <cac:ItemPriceExtension>
                          <cbc:Amount currencyID="AED">1000.00</cbc:Amount>
                          <cac:TaxTotal>
                            <cbc:TaxAmount currencyID="AED">0.00</cbc:TaxAmount>
                          </cac:TaxTotal>
                        </cac:ItemPriceExtension>
                      </cac:InvoiceLine>
                    </Invoice>
              commercialCreditNoteJsonMode:
                summary: JSON mode — UAE Commercial Credit Note (81) (81)
                description: Reverses a commercial invoice. Same identity rules as 480.
                value:
                  inputType: json
                  environment: test
                  documentType: creditNote
                  senderPeppolId: "0235:1000000001"
                  receiverPeppolId: "0235:1000000002"
                  payload:
                    invoiceKind: commercial
                    invoiceNumber: CCN-2026-000123
                    uniqueIdentifierNumber: 3f2504e0-4f89-41d3-9a0c-000000000004
                    issueDate: "2026-09-16"
                    currency: AED
                    transactionTypeCode: "00000000"
                    note: Credit for returned goods.
                    creditNoteReasonCode: DL8.61.1.D
                    billingReference:
                      invoiceId: CINV-2026-000123
                      issueDate: "2026-09-16"
                    supplier:
                      name: AZDAN Sample Supplier LLC
                      schemeId: "0235"
                      peppolId: "1000000001"
                      taxRegistrationId: "1000000001"
                      taxSchemeId: TIN
                      legalRegistrationId: CN-1234567
                      legalRegistrationType: TL
                      legalRegistrationAuthorityName: Department of Economic Development Dubai
                      address:
                        streetName: Sheikh Zayed Road 12
                        additionalStreetName: Office 401
                        cityName: Dubai
                        postalZone: "00000"
                        countrySubentity: DXB
                        countryCode: AE
                    customer:
                      name: Emirates Buyer Trading LLC
                      schemeId: "0235"
                      peppolId: "1000000002"
                      legalRegistrationId: CN-7654321
                      legalRegistrationType: CL
                      legalRegistrationAuthorityName: Abu Dhabi Department of Economic Development
                      address:
                        streetName: Corniche Road 88
                        cityName: Abu Dhabi
                        postalZone: "11111"
                        countrySubentity: AUH
                        countryCode: AE
                    lines:
                      - id: "1"
                        quantity: "10"
                        unitCode: EA
                        lineExtensionAmount: "1000.00"
                        price:
                          priceAmount: "100.00"
                        item:
                          name: Consulting services
                          description: Professional services for September 2026
                        tax:
                          category: Z
                          rate: "0"
                    taxTotal:
                      taxAmount: "0.00"
                      taxSubtotals:
                        - category: Z
                          percent: "0.00"
                          taxableAmount: "1000.00"
                          taxAmount: "0.00"
                    legalMonetaryTotal:
                      lineExtensionAmount: "1000.00"
                      taxExclusiveAmount: "1000.00"
                      taxInclusiveAmount: "1000.00"
                      payableAmount: "1000.00"
              commercialCreditNoteXmlMode:
                summary: XML mode — UAE Commercial Credit Note (81)
                description: Reverses a commercial invoice. Same identity rules as 480. The xml value is the UBL 2.1 document the API builds for the JSON example of the same name; it passes PINT-AE 1.0.4.
                value:
                  inputType: xml
                  environment: test
                  documentType: creditNote
                  senderPeppolId: "0235:1000000001"
                  receiverPeppolId: "0235:1000000002"
                  xml: |-
                    <?xml version="1.0" encoding="UTF-8"?>
                    <CreditNote
                      xmlns="urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2"
                      xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
                      xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">
                      <cbc:CustomizationID>urn:peppol:pint:billing-1@ae-1</cbc:CustomizationID>
                      <cbc:ProfileID>urn:peppol:bis:billing</cbc:ProfileID>
                      <cbc:ProfileExecutionID>00000000</cbc:ProfileExecutionID>
                      <cbc:ID>CCN-2026-000123</cbc:ID>
                      <cbc:UUID>3f2504e0-4f89-41d3-9a0c-000000000004</cbc:UUID>
                      <cbc:IssueDate>2026-09-16</cbc:IssueDate>
                      <cbc:CreditNoteTypeCode>81</cbc:CreditNoteTypeCode>
                      <cbc:Note>Credit for returned goods.</cbc:Note>
                      <cbc:DocumentCurrencyCode>AED</cbc:DocumentCurrencyCode>
                      <cac:DiscrepancyResponse>
                        <cbc:ResponseCode>DL8.61.1.D</cbc:ResponseCode>
                      </cac:DiscrepancyResponse>
                      <cac:BillingReference>
                        <cac:InvoiceDocumentReference>
                          <cbc:ID>CINV-2026-000123</cbc:ID>
                          <cbc:IssueDate>2026-09-16</cbc:IssueDate>
                        </cac:InvoiceDocumentReference>
                      </cac:BillingReference>
                      <cac:AccountingSupplierParty>
                        <cac:Party>
                          <cbc:EndpointID schemeID="0235">1000000001</cbc:EndpointID>
                          <cac:PartyName><cbc:Name>AZDAN Sample Supplier LLC</cbc:Name></cac:PartyName>
                          <cac:PostalAddress>
                            <cbc:StreetName>Sheikh Zayed Road 12</cbc:StreetName>
                            <cbc:AdditionalStreetName>Office 401</cbc:AdditionalStreetName>
                            <cbc:CityName>Dubai</cbc:CityName>
                            <cbc:PostalZone>00000</cbc:PostalZone>
                            <cbc:CountrySubentity>DXB</cbc:CountrySubentity>
                            <cac:Country><cbc:IdentificationCode>AE</cbc:IdentificationCode></cac:Country>
                          </cac:PostalAddress>
                          <cac:PartyTaxScheme>
                            <cbc:CompanyID>1000000001</cbc:CompanyID>
                            <cac:TaxScheme><cbc:ID>TIN</cbc:ID></cac:TaxScheme>
                          </cac:PartyTaxScheme>
                          <cac:PartyLegalEntity>
                            <cbc:RegistrationName>AZDAN Sample Supplier LLC</cbc:RegistrationName>
                            <cbc:CompanyID schemeAgencyID="TL" schemeAgencyName="Department of Economic Development Dubai">CN-1234567</cbc:CompanyID>
                          </cac:PartyLegalEntity>
                        </cac:Party></cac:AccountingSupplierParty>
                      <cac:AccountingCustomerParty>
                        <cac:Party>
                          <cbc:EndpointID schemeID="0235">1000000002</cbc:EndpointID>
                          <cac:PartyName><cbc:Name>Emirates Buyer Trading LLC</cbc:Name></cac:PartyName>
                          <cac:PostalAddress>
                            <cbc:StreetName>Corniche Road 88</cbc:StreetName>
                            <cbc:CityName>Abu Dhabi</cbc:CityName>
                            <cbc:PostalZone>11111</cbc:PostalZone>
                            <cbc:CountrySubentity>AUH</cbc:CountrySubentity>
                            <cac:Country><cbc:IdentificationCode>AE</cbc:IdentificationCode></cac:Country>
                          </cac:PostalAddress>
                          <cac:PartyLegalEntity>
                            <cbc:RegistrationName>Emirates Buyer Trading LLC</cbc:RegistrationName>
                            <cbc:CompanyID schemeAgencyID="CL" schemeAgencyName="Abu Dhabi Department of Economic Development">CN-7654321</cbc:CompanyID>
                          </cac:PartyLegalEntity>
                        </cac:Party></cac:AccountingCustomerParty>
                      <cac:TaxTotal>
                        <cbc:TaxAmount currencyID="AED">0.00</cbc:TaxAmount>
                        <cac:TaxSubtotal>
                          <cbc:TaxableAmount currencyID="AED">1000.00</cbc:TaxableAmount>
                          <cbc:TaxAmount currencyID="AED">0.00</cbc:TaxAmount>
                          <cac:TaxCategory>
                            <cbc:ID>Z</cbc:ID>
                            <cbc:Percent>0.00</cbc:Percent>
                            <cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme>
                          </cac:TaxCategory>
                        </cac:TaxSubtotal>
                      </cac:TaxTotal>
                      <cac:LegalMonetaryTotal>
                        <cbc:LineExtensionAmount currencyID="AED">1000.00</cbc:LineExtensionAmount>
                        <cbc:TaxExclusiveAmount currencyID="AED">1000.00</cbc:TaxExclusiveAmount>
                        <cbc:TaxInclusiveAmount currencyID="AED">1000.00</cbc:TaxInclusiveAmount>
                        <cbc:PayableAmount currencyID="AED">1000.00</cbc:PayableAmount>
                      </cac:LegalMonetaryTotal>
                      <cac:CreditNoteLine>
                        <cbc:ID>1</cbc:ID>
                        <cbc:CreditedQuantity unitCode="EA">10</cbc:CreditedQuantity>
                        <cbc:LineExtensionAmount currencyID="AED">1000.00</cbc:LineExtensionAmount>
                        <cac:Item>
                            <cbc:Description>Professional services for September 2026</cbc:Description>
                          <cbc:Name>Consulting services</cbc:Name>
                          <cac:ClassifiedTaxCategory>
                            <cbc:ID>Z</cbc:ID>
                            <cbc:Percent>0.00</cbc:Percent>
                            <cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme>
                          </cac:ClassifiedTaxCategory>
                        </cac:Item>
                        <cac:Price>
                          <cbc:PriceAmount currencyID="AED">100.00</cbc:PriceAmount>
                          <cbc:BaseQuantity unitCode="EA">1</cbc:BaseQuantity>
                          <cac:AllowanceCharge>
                            <cbc:ChargeIndicator>false</cbc:ChargeIndicator>
                            <cbc:Amount currencyID="AED">0.00</cbc:Amount>
                            <cbc:BaseAmount currencyID="AED">100.00</cbc:BaseAmount>
                          </cac:AllowanceCharge>
                        </cac:Price>
                        <cac:ItemPriceExtension>
                          <cbc:Amount currencyID="AED">1000.00</cbc:Amount>
                          <cac:TaxTotal>
                            <cbc:TaxAmount currencyID="AED">0.00</cbc:TaxAmount>
                          </cac:TaxTotal>
                        </cac:ItemPriceExtension>
                      </cac:CreditNoteLine>
                    </CreditNote>
              uaeScenarioJsonMode:
                summary: JSON mode — Combined scenarios (380)
                description: "Positions 1, 4, 6 and 8 declared together (mask 10010101): the free-zone beneficiary (BTAE-01), the invoice period (IBG-14), the disclosed-agent principal (BTAE-14) and a deliver-to address abroad (IBG-13). Scenarios combine, and each companion element stays mandatory under its own rule — none is derived from a value the invoice already carries."
                value:
                  inputType: json
                  environment: test
                  documentType: invoice
                  senderPeppolId: "0235:1000000001"
                  receiverPeppolId: "0235:1000000002"
                  payload:
                    invoiceKind: tax
                    invoiceNumber: INV-2026-000123
                    uniqueIdentifierNumber: 3f2504e0-4f89-41d3-9a0c-000000000018
                    issueDate: "2026-09-16"
                    dueDate: "2026-10-16"
                    currency: AED
                    transactionType:
                      freeTradeZone: true
                      summaryInvoice: true
                      disclosedAgentBilling: true
                      export: true
                    invoicePeriod:
                      startDate: "2026-09-01"
                      endDate: "2026-09-30"
                      frequencyCode: MTH
                    paymentMeansCode: "30"
                    paymentAccountId: AE070331234567890123456
                    supplier:
                      name: AZDAN Sample Supplier LLC
                      schemeId: "0235"
                      peppolId: "1000000001"
                      taxId: "100000000000103"
                      legalRegistrationId: CN-1234567
                      legalRegistrationType: TL
                      legalRegistrationAuthorityName: Department of Economic Development Dubai
                      address:
                        streetName: Sheikh Zayed Road 12
                        additionalStreetName: Office 401
                        cityName: Dubai
                        postalZone: "00000"
                        countrySubentity: DXB
                        countryCode: AE
                    customer:
                      name: Emirates Buyer Trading LLC
                      schemeId: "0235"
                      peppolId: "1000000002"
                      taxId: "100000000000203"
                      address:
                        streetName: Corniche Road 88
                        cityName: Abu Dhabi
                        postalZone: "11111"
                        countrySubentity: AUH
                        countryCode: AE
                      beneficiaryId: FZ-BEN-778901
                    agent:
                      principalId: PRINCIPAL-4471
                    delivery:
                      date: "2026-09-25"
                      address:
                        streetName: Hamngatan 4
                        additionalStreetName: Warehouse B
                        cityName: Goteborg
                        postalZone: "41106"
                        countrySubentity: Vastra Gotaland
                        countryCode: SE
                    lines:
                      - id: "1"
                        quantity: "10"
                        unitCode: EA
                        lineExtensionAmount: "1000.00"
                        price:
                          priceAmount: "100.00"
                        item:
                          name: Consulting services
                          description: Professional services for September 2026
                        tax:
                          category: S
                          rate: "5"
                    taxTotal:
                      taxAmount: "50.00"
                      taxSubtotals:
                        - category: S
                          percent: "5.00"
                          taxableAmount: "1000.00"
                          taxAmount: "50.00"
                    legalMonetaryTotal:
                      lineExtensionAmount: "1000.00"
                      taxExclusiveAmount: "1000.00"
                      taxInclusiveAmount: "1050.00"
                      payableAmount: "1050.00"
              exemptionReasonJsonMode:
                summary: JSON mode — Mixed VAT categories (380)
                description: Standard rated (S), zero rated (Z) and exempt (E) lines on one invoice. The VAT breakdown has one entry per category; the exempt line carries a VAT exemption reason code and no rate.
                value:
                  inputType: json
                  environment: test
                  documentType: invoice
                  senderPeppolId: "0235:1000000001"
                  receiverPeppolId: "0235:1000000002"
                  payload:
                    invoiceKind: tax
                    invoiceNumber: INV-2026-000123
                    uniqueIdentifierNumber: 3f2504e0-4f89-41d3-9a0c-000000000017
                    issueDate: "2026-09-16"
                    dueDate: "2026-10-16"
                    currency: AED
                    transactionTypeCode: "00000000"
                    paymentMeansCode: "30"
                    paymentAccountId: AE070331234567890123456
                    supplier:
                      name: AZDAN Sample Supplier LLC
                      schemeId: "0235"
                      peppolId: "1000000001"
                      taxId: "100000000000103"
                      legalRegistrationId: CN-1234567
                      legalRegistrationType: TL
                      legalRegistrationAuthorityName: Department of Economic Development Dubai
                      address:
                        streetName: Sheikh Zayed Road 12
                        additionalStreetName: Office 401
                        cityName: Dubai
                        postalZone: "00000"
                        countrySubentity: DXB
                        countryCode: AE
                    customer:
                      name: Emirates Buyer Trading LLC
                      schemeId: "0235"
                      peppolId: "1000000002"
                      taxId: "100000000000203"
                      address:
                        streetName: Corniche Road 88
                        cityName: Abu Dhabi
                        postalZone: "11111"
                        countrySubentity: AUH
                        countryCode: AE
                    lines:
                      - id: "1"
                        quantity: "10"
                        unitCode: EA
                        lineExtensionAmount: "1000.00"
                        price:
                          priceAmount: "100.00"
                        item:
                          name: Consulting services
                          description: Professional services for September 2026
                        tax:
                          category: S
                          rate: "5"
                      - id: "2"
                        quantity: "10"
                        unitCode: EA
                        lineExtensionAmount: "1000.00"
                        price:
                          priceAmount: "100.00"
                        item:
                          name: International freight
                          description: Zero-rated international transport of goods
                        tax:
                          category: Z
                          rate: "0"
                      - id: "3"
                        quantity: "10"
                        unitCode: EA
                        lineExtensionAmount: "1000.00"
                        price:
                          priceAmount: "100.00"
                        item:
                          name: Financial service fee
                          description: Exempt financial service
                        tax:
                          category: E
                          exemptionReasonCode: VATEX-AE-EXEMPT-FINANCIAL
                    taxTotal:
                      taxAmount: "50.00"
                      taxSubtotals:
                        - category: S
                          percent: "5.00"
                          taxableAmount: "1000.00"
                          taxAmount: "50.00"
                        - category: Z
                          percent: "0.00"
                          taxableAmount: "1000.00"
                          taxAmount: "0.00"
                        - category: E
                          taxableAmount: "1000.00"
                          taxAmount: "0.00"
                    legalMonetaryTotal:
                      lineExtensionAmount: "3000.00"
                      taxExclusiveAmount: "3000.00"
                      taxInclusiveAmount: "3050.00"
                      payableAmount: "3050.00"
      responses:
        "202":
          description: Accepted for delivery
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SubmitResponse"
              examples:
                accepted:
                  summary: Accepted for delivery
                  value:
                    transactionId: txn_1789562400000_9f3a1c2b
                    status: queued
                    valid: true
                    documentTypeId: urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:peppol:pint:billing-1@ae-1::2.1
                    processId: urn:peppol:bis:billing
                    correlationId: cor_1789562400000_4d5e6f70
                    as4MessageId: f0debc61-215c-4e0a-9d1b-2a7c3e4f5a6b@peppol.azdanapps.com
                    sbdhInstanceId: 6c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f
                    idempotent: false
                    warnings: []
                    validatorPhormSkipped: false
                    message: Invoice accepted for Peppol delivery.
                    documents:
                      invoiceXml:
                        available: true
                        fileId: file_01J9Z3Q7M8K2N4P6R8T0V2X4Y6
                        fileName: txn_1789562400000_9f3a1c2b.xml
                        contentType: application/xml
                        downloadUrl: /api/integrations/peppol/transactions/txn_1789562400000_9f3a1c2b/files/invoice-xml
                      invoicePdf:
                        available: false
                        fileId: null
                        fileName: null
                        contentType: application/pdf
                        downloadUrl: null
                        reason: not_generated
                      sbdXml:
                        available: false
                        fileId: null
                        fileName: null
                        contentType: application/xml
                        downloadUrl: null
                        reason: not_stored
                      tddXml:
                        available: false
                        fileId: null
                        fileName: null
                        contentType: application/xml
                        downloadUrl: null
                        reason: not_generated
                      mlsXml:
                        available: false
                        fileId: null
                        fileName: null
                        contentType: application/xml
                        downloadUrl: null
                        reason: not_received
                      payloadXml:
                        available: false
                        privileged: true
                        requiredScope: peppol:payload:read
                        contentType: application/xml
                        downloadUrl: null
                        reason: not_in_object_storage
                idempotentReplay:
                  summary: Same Idempotency-Key again — the original transaction, nothing sent twice
                  value:
                    transactionId: txn_1789562400000_9f3a1c2b
                    status: sending
                    valid: true
                    documentTypeId: urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:peppol:pint:billing-1@ae-1::2.1
                    processId: urn:peppol:bis:billing
                    correlationId: cor_1789562400000_4d5e6f70
                    as4MessageId: f0debc61-215c-4e0a-9d1b-2a7c3e4f5a6b@peppol.azdanapps.com
                    sbdhInstanceId: 6c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f
                    idempotent: true
                    warnings: []
                    validatorPhormSkipped: false
                    message: Existing transaction returned (idempotent replay).
        "400":
          $ref: "#/components/responses/ValidationError"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "502":
          $ref: "#/components/responses/UpstreamError"
      x-azdan-scopes:
        - peppol:submit
        - transactions:submit
      x-azdan-default-key: true
      x-azdan-contract-key: submit
      x-azdan-access: send
      x-azdan-expected:
        - 202 accepted (asynchronous delivery)
        - 400 validation failure
        - 401 invalid key
        - 403 insufficient scope
        - 403 SENDER_NOT_OWNED
        - 502 access point rejected
  /api/integrations/peppol/transactions:
    get:
      operationId: listTransactions
      summary: List transactions
      description: |
        Paginated list of the tenant's transactions. Supports two pagination modes:

        - **Cursor mode** (default): Pass `limit` and optionally `cursor`.
          Recommended for sync jobs and large datasets.
        - **Page mode**: Pass `page` and `pageSize`. Backward compatible for
          UI browsing.

        If both `page`/`pageSize` and `limit`/`cursor` are absent, cursor mode
        is used with default limit=50.
      tags:
        - Peppol Transactions
      parameters:
        - $ref: "#/components/parameters/CursorLimit"
        - $ref: "#/components/parameters/Cursor"
        - $ref: "#/components/parameters/Sort"
        - $ref: "#/components/parameters/Page"
        - $ref: "#/components/parameters/PageSize"
        - $ref: "#/components/parameters/IncludeParam"
        - $ref: "#/components/parameters/FilterDirection"
        - $ref: "#/components/parameters/FilterStatus"
        - $ref: "#/components/parameters/FilterEnvironment"
        - $ref: "#/components/parameters/FilterDocumentType"
        - $ref: "#/components/parameters/FilterSenderPeppolId"
        - $ref: "#/components/parameters/FilterReceiverPeppolId"
        - $ref: "#/components/parameters/FilterPeppolParticipantId"
        - $ref: "#/components/parameters/FilterSubsidiaryId"
        - $ref: "#/components/parameters/FilterCorrelationId"
        - $ref: "#/components/parameters/FilterAs4MessageId"
        - $ref: "#/components/parameters/FilterApCoreMessageId"
        - $ref: "#/components/parameters/FilterSbdhInstanceId"
        - $ref: "#/components/parameters/FilterIdempotencyKey"
        - $ref: "#/components/parameters/FilterDateFrom"
        - $ref: "#/components/parameters/FilterDateTo"
        - $ref: "#/components/parameters/FilterMessageId"
        - $ref: "#/components/parameters/FilterSearch"
      responses:
        "200":
          description: Transaction list
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: "#/components/schemas/CursorListResponse"
                  - $ref: "#/components/schemas/PageListResponse"
              examples:
                cursorMode:
                  summary: Cursor pagination
                  value:
                    items:
                      - transactionId: txn_1715690640123_a1b2c3d4
                        direction: outbound
                        status: delivered
                        documentType: invoice
                        sender:
                          participantId: "0235:1000000001"
                          name: Acme Trading LLC
                        receiver:
                          participantId: "0235:1000000002"
                          name: BuyerCo
                        environment: production
                        createdAt: "2026-05-14T10:00:00.000Z"
                    pagination:
                      mode: cursor
                      limit: 50
                      nextCursor: eyJzIjoiY3JlYXRlZEF0Iiw...
                      prevCursor: null
                      hasNext: true
                pageMode:
                  summary: Page pagination (backward compatible)
                  value:
                    transactions:
                      - transactionId: txn_1715690640123_a1b2c3d4
                        direction: outbound
                        status: delivered
                    pagination:
                      page: 1
                      pageSize: 25
                      total: 142
                      totalPages: 6
                      hasMore: true
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
      x-azdan-scopes:
        - transactions:read
        - peppol:read
        - peppol:submit
      x-azdan-default-key: true
      x-azdan-contract-key: list
      x-azdan-access: read
      x-azdan-expected:
        - 200 page of transactions
        - 400 invalid cursor / filter
        - 401 invalid key
        - 403 insufficient scope
  /api/integrations/peppol/transactions/{transactionId}:
    get:
      operationId: getTransaction
      summary: Get enriched transaction detail
      description: |
        Returns a full enriched view of a single transaction including:
        - `transaction` — platform transaction fields
        - `platform` — correlation/idempotency/webhook summary
        - `ap` — AP Core link status, AS4/SBDH IDs, timestamps, errors
        - `storage` — primary storage info (S3 key, content type, size)
        - `files` — list of associated files (payload, SBDH, MLR, etc.)
        - `links` — HATEOAS links to related endpoints (self, events, xml)

        AP matching uses a prioritized strategy:
        1. Exact match on `sbdhInstanceId`
        2. Exact match on `apCoreMessageId` (AS4 message ID)
        3. Fuzzy match on sender+receiver+docType+process+createdAt±5min
        4. If multiple fuzzy matches, returns `ap.linkAmbiguous: true`
      tags:
        - Peppol Transactions
      parameters:
        - name: transactionId
          in: path
          required: true
          schema:
            type: string
          example: txn_1715690640123_a1b2c3d4
      responses:
        "200":
          description: Enriched transaction detail
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EnrichedTransactionDetail"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
      x-azdan-scopes:
        - transactions:read
        - peppol:read
        - peppol:submit
      x-azdan-default-key: true
      x-azdan-contract-key: transaction
      x-azdan-access: read
      x-azdan-expected:
        - 200 detail with documents.<kind>.available and reason
        - 401 invalid key
        - 403 insufficient scope
        - 404 unknown transaction
  /api/integrations/peppol/transactions/{transactionId}/xml:
    get:
      operationId: getTransactionXml
      summary: Download XML business payload
      description: |
        Generates a time-limited presigned S3 URL for the XML business payload
        and redirects (303) to it. The `Content-Type` header is set to
        `application/xml`. The presigned URL expires after 60 seconds.

        Requires scope: `peppol:payload:read`.

        Returns 409 if the payload is not available in S3 (e.g., only exists
        in a legacy local filesystem path).
      tags:
        - Peppol Transactions
      security:
        - ApiKeyBearer: []
      parameters:
        - name: transactionId
          in: path
          required: true
          schema:
            type: string
      responses:
        "303":
          description: Redirect to presigned S3 URL
          headers:
            Location:
              description: Presigned S3 download URL (expires in 60s)
              schema:
                type: string
                format: uri
            Content-Type:
              schema:
                type: string
                example: application/xml
            Cache-Control:
              schema:
                type: string
                example: no-store
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "409":
          description: Payload not available in object storage yet.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: PAYLOAD_NOT_IN_OBJECT_STORAGE
                  message: XML payload is not available in object storage.
      x-azdan-scopes:
        - peppol:payload:read
      x-azdan-default-key: false
      x-azdan-contract-key: xml
      x-azdan-access: privileged
      x-azdan-required-scope: peppol:payload:read
      x-azdan-expected:
        - 303 signed URL
        - 401 invalid key
        - 403 key lacks peppol:payload:read
        - 404 unknown transaction
        - 409 payload not in object storage
      x-azdan-availability:
        present: 303 redirect to a signed URL when the payload is in object storage.
        absent: 409 PAYLOAD_NOT_IN_OBJECT_STORAGE when the payload exists only outside object storage; 404 when the transaction is unknown.
        source: The stored business payload, served as a short-lived signed object-storage URL (303). Same bytes as Invoice XML; a different route with a privileged scope.
  /api/integrations/peppol/transactions/{transactionId}/files/invoice-xml:
    get:
      operationId: downloadIntegrationInvoiceXml
      summary: Download invoice XML using an integration API key
      description: |
        Secure per-document download for `documents.invoiceXml` returned by
        integration API responses and webhooks. Uses the same AZDAN API key
        family as invoice submission.

        Required scope: `peppol:read` or `transactions:read`. For backward
        compatibility, existing submit keys with `peppol:submit` are also
        accepted so ERP clients can retrieve documents for invoices they submit.

        The Platform API verifies tenant ownership, returns `404` when the
        document is unavailable or belongs to another tenant, and never exposes
        raw object-storage coordinates. Object-storage files redirect to a
        short-lived signed URL; local/test files stream through the API.
      tags:
        - Transaction Documents
      security:
        - ApiKeyBearer: []
      parameters:
        - $ref: "#/components/parameters/TransactionIdPath"
      responses:
        "200":
          description: File streamed through the Platform API.
          headers:
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename="INV-10001.xml"
            Cache-Control:
              schema:
                type: string
                example: no-store
          content:
            application/xml:
              schema:
                type: string
                format: binary
        "302":
          description: Redirect to a short-lived signed download URL.
          headers:
            Location:
              description: Short-lived signed download URL.
              schema:
                type: string
                format: uri
            Cache-Control:
              schema:
                type: string
                example: no-store
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
      x-azdan-scopes:
        - peppol:read
        - transactions:read
        - peppol:submit
      x-azdan-default-key: true
      x-azdan-contract-key: invoiceXml
      x-azdan-access: read
      x-azdan-expected:
        - 200 file (302 to a short-lived signed URL on object storage)
        - 401 invalid key
        - 403 insufficient scope
        - 404 not stored
      x-azdan-availability:
        present: 200 when stored.
        absent: 404 only when no file was stored — for a document the platform itself submitted that is a storage or mapping defect, not an expected state.
        source: The UBL invoice / credit note the platform stored when the document was submitted (outbound) or received (inbound).
  /api/integrations/peppol/transactions/{transactionId}/files/invoice-pdf:
    get:
      operationId: downloadIntegrationInvoicePdf
      summary: Download invoice PDF using an integration API key
      description: |
        Secure per-document download for `documents.invoicePdf`. Same API-key
        authorization, tenant isolation, streaming/redirect, and `404`
        semantics as `downloadIntegrationInvoiceXml`.
      tags:
        - Transaction Documents
      security:
        - ApiKeyBearer: []
      parameters:
        - $ref: "#/components/parameters/TransactionIdPath"
      responses:
        "200":
          description: File streamed through the Platform API.
          headers:
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename="INV-10001.pdf"
            Cache-Control:
              schema:
                type: string
                example: no-store
          content:
            application/pdf:
              schema:
                type: string
                format: binary
        "302":
          description: Redirect to a short-lived signed download URL.
          headers:
            Location:
              description: Short-lived signed download URL.
              schema:
                type: string
                format: uri
            Cache-Control:
              schema:
                type: string
                example: no-store
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
      x-azdan-scopes:
        - peppol:read
        - transactions:read
        - peppol:submit
      x-azdan-default-key: true
      x-azdan-contract-key: invoicePdf
      x-azdan-access: optional
      x-azdan-expected:
        - 200 file
        - 401 invalid key
        - 403 insufficient scope
        - 404 no PDF generated (expected)
      x-azdan-availability:
        present: 200 when a PDF exists.
        absent: 404 when no PDF was generated — expected for most transactions.
        source: A PDF rendering, only when one was generated or attached.
  /api/integrations/peppol/transactions/{transactionId}/files/sbd-xml:
    get:
      operationId: downloadIntegrationSbdXml
      summary: Download SBD XML using an integration API key
      description: |
        Secure per-document download for `documents.sbdXml` — the SBDH wrapper
        around the invoice and Peppol header. Same API-key authorization,
        tenant isolation, streaming/redirect, and `404` semantics as
        `downloadIntegrationInvoiceXml`.
      tags:
        - Transaction Documents
      security:
        - ApiKeyBearer: []
      parameters:
        - $ref: "#/components/parameters/TransactionIdPath"
      responses:
        "200":
          description: File streamed through the Platform API.
          headers:
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename="INV-10001.sbd.xml"
            Cache-Control:
              schema:
                type: string
                example: no-store
          content:
            application/xml:
              schema:
                type: string
                format: binary
        "302":
          description: Redirect to a short-lived signed download URL.
          headers:
            Location:
              description: Short-lived signed download URL.
              schema:
                type: string
                format: uri
            Cache-Control:
              schema:
                type: string
                example: no-store
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
      x-azdan-scopes:
        - peppol:read
        - transactions:read
        - peppol:submit
      x-azdan-default-key: true
      x-azdan-contract-key: sbdXml
      x-azdan-access: optional
      x-azdan-expected:
        - 200 file
        - 401 invalid key
        - 403 insufficient scope
        - 404 no SBD stored (expected for outbound)
      x-azdan-availability:
        present: 200 only when a real SBD is stored; the outbound payload is never returned under this name.
        absent: 404 for outbound transactions is expected; 404 on inbound means no SBD was stored.
        source: A real StandardBusinessDocument (SBDH envelope) that was stored. An outbound submission is payload-only — the access point builds the SBDH inside the AS4 message and does not persist it — so this is normally an inbound document.
  /api/integrations/peppol/transactions/{transactionId}/files/tdd-xml:
    get:
      operationId: downloadIntegrationTddXml
      summary: Download TDD XML using an integration API key
      description: |
        Secure per-document download for `documents.tddXml` — the UAE FTA Tax
        Data Document. Same API-key authorization, tenant isolation,
        streaming/redirect, and `404` semantics as
        `downloadIntegrationInvoiceXml`.
      tags:
        - Transaction Documents
      security:
        - ApiKeyBearer: []
      parameters:
        - $ref: "#/components/parameters/TransactionIdPath"
      responses:
        "200":
          description: File streamed through the Platform API.
          headers:
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename="INV-10001.tdd.xml"
            Cache-Control:
              schema:
                type: string
                example: no-store
          content:
            application/xml:
              schema:
                type: string
                format: binary
        "302":
          description: Redirect to a short-lived signed download URL.
          headers:
            Location:
              description: Short-lived signed download URL.
              schema:
                type: string
                format: uri
            Cache-Control:
              schema:
                type: string
                example: no-store
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
      x-azdan-scopes:
        - peppol:read
        - transactions:read
        - peppol:submit
      x-azdan-default-key: true
      x-azdan-contract-key: tddXml
      x-azdan-access: optional
      x-azdan-expected:
        - 200 file
        - 401 invalid key
        - 403 insufficient scope
        - 404 not generated yet (expected until the TDD exists)
      x-azdan-availability:
        present: 200 once the TDD was generated and stored.
        absent: 404 before generation or when no TDD applies to the document.
        source: The Tax Data Document AZDAN generated for this transaction, linked by explicit parent id. It is never submitted by the caller.
  /api/integrations/peppol/transactions/{transactionId}/files/mls-xml:
    get:
      operationId: downloadIntegrationMlsXml
      summary: Download MLS XML using an integration API key
      description: |
        Secure per-document download for `documents.mlsXml` — the Peppol
        ApplicationResponse Message Level Status. Same API-key authorization,
        tenant isolation, streaming/redirect, and `404` semantics as
        `downloadIntegrationInvoiceXml`.
      tags:
        - Transaction Documents
      security:
        - ApiKeyBearer: []
      parameters:
        - $ref: "#/components/parameters/TransactionIdPath"
      responses:
        "200":
          description: File streamed through the Platform API.
          headers:
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename="INV-10001.mls.xml"
            Cache-Control:
              schema:
                type: string
                example: no-store
          content:
            application/xml:
              schema:
                type: string
                format: binary
        "302":
          description: Redirect to a short-lived signed download URL.
          headers:
            Location:
              description: Short-lived signed download URL.
              schema:
                type: string
                format: uri
            Cache-Control:
              schema:
                type: string
                example: no-store
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
      x-azdan-scopes:
        - peppol:read
        - transactions:read
        - peppol:submit
      x-azdan-default-key: true
      x-azdan-contract-key: mlsXml
      x-azdan-access: optional
      x-azdan-expected:
        - 200 file
        - 401 invalid key
        - 403 insufficient scope
        - 404 metadata only or no MLS (expected)
      x-azdan-availability:
        present: 200 only when the XML file itself is stored.
        absent: 404 when the MLS is known only as metadata (reason metadata_only) or was not received at all.
        source: A stored Message Level Status (ApplicationResponse) file. MLS METADATA (ap.mlsStatus, ap.mlsReceivedAt, ap.mlsId, ap.mlsType, ap.mlsErrorCode, ap.mlsErrorMessage) can exist on the transaction without a stored XML file.
  /api/tenant/transactions/{transactionId}/files/invoice-xml:
    get:
      operationId: downloadInvoiceXml
      x-azdan-scopes:
        - peppol:read
        - transactions:read
        - peppol:submit
      summary: Download the invoice XML for a transaction
      description: |
        Secure per-document download for `documents.invoiceXml`. Authorizes the
        caller (tenant session, or `super_admin`), verifies the file belongs to
        BOTH the transaction AND the caller's tenant, then either streams the
        bytes through the Platform API or `302`-redirects to a short-lived signed
        URL it mints. Object-storage coordinates (bucket / namespace / object
        key) are never exposed. Returns `404` when the document is unavailable or
        owned by another tenant.
      tags:
        - Transaction Documents
      security:
        - ApiKeyBearer: []
        - TenantSession: []
      parameters:
        - $ref: "#/components/parameters/TransactionIdPath"
      responses:
        "200":
          description: File streamed through the Platform API.
          headers:
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename="INV-10001.xml"
            Cache-Control:
              schema:
                type: string
                example: no-store
          content:
            application/xml:
              schema:
                type: string
                format: binary
        "302":
          description: Redirect to a short-lived signed download URL (never a public bucket URL).
          headers:
            Location:
              description: Short-lived signed download URL.
              schema:
                type: string
                format: uri
            Cache-Control:
              schema:
                type: string
                example: no-store
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
  /api/tenant/transactions/{transactionId}/files/invoice-pdf:
    get:
      operationId: downloadInvoicePdf
      x-azdan-scopes:
        - peppol:read
        - transactions:read
        - peppol:submit
      summary: Download the invoice PDF for a transaction
      description: |
        Secure per-document download for `documents.invoicePdf`. Same
        authorization, streaming/redirect and `404` semantics as
        `downloadInvoiceXml`. Returns `404` when no PDF rendering exists.
      tags:
        - Transaction Documents
      security:
        - ApiKeyBearer: []
        - TenantSession: []
      parameters:
        - $ref: "#/components/parameters/TransactionIdPath"
      responses:
        "200":
          description: File streamed through the Platform API.
          headers:
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename="INV-10001.pdf"
            Cache-Control:
              schema:
                type: string
                example: no-store
          content:
            application/pdf:
              schema:
                type: string
                format: binary
        "302":
          description: Redirect to a short-lived signed download URL (never a public bucket URL).
          headers:
            Location:
              description: Short-lived signed download URL.
              schema:
                type: string
                format: uri
            Cache-Control:
              schema:
                type: string
                example: no-store
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
  /api/tenant/transactions/{transactionId}/files/sbd-xml:
    get:
      operationId: downloadSbdXml
      x-azdan-scopes:
        - peppol:read
        - transactions:read
        - peppol:submit
      summary: Download the Standard Business Document (SBD) XML
      description: |
        Secure per-document download for `documents.sbdXml` — the SBDH wrapper
        around the invoice and Peppol header. Same authorization,
        streaming/redirect and `404` semantics as `downloadInvoiceXml`.
      tags:
        - Transaction Documents
      security:
        - ApiKeyBearer: []
        - TenantSession: []
      parameters:
        - $ref: "#/components/parameters/TransactionIdPath"
      responses:
        "200":
          description: File streamed through the Platform API.
          headers:
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename="INV-10001.sbd.xml"
            Cache-Control:
              schema:
                type: string
                example: no-store
          content:
            application/xml:
              schema:
                type: string
                format: binary
        "302":
          description: Redirect to a short-lived signed download URL (never a public bucket URL).
          headers:
            Location:
              description: Short-lived signed download URL.
              schema:
                type: string
                format: uri
            Cache-Control:
              schema:
                type: string
                example: no-store
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
  /api/tenant/transactions/{transactionId}/files/tdd-xml:
    get:
      operationId: downloadTddXml
      x-azdan-scopes:
        - peppol:read
        - transactions:read
        - peppol:submit
      summary: Download the Tax Data Document (TDD) XML
      description: |
        Secure per-document download for `documents.tddXml` — the UAE FTA Tax
        Data Document. Same authorization, streaming/redirect and `404`
        semantics as `downloadInvoiceXml`.
      tags:
        - Transaction Documents
      security:
        - ApiKeyBearer: []
        - TenantSession: []
      parameters:
        - $ref: "#/components/parameters/TransactionIdPath"
      responses:
        "200":
          description: File streamed through the Platform API.
          headers:
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename="INV-10001.tdd.xml"
            Cache-Control:
              schema:
                type: string
                example: no-store
          content:
            application/xml:
              schema:
                type: string
                format: binary
        "302":
          description: Redirect to a short-lived signed download URL (never a public bucket URL).
          headers:
            Location:
              description: Short-lived signed download URL.
              schema:
                type: string
                format: uri
            Cache-Control:
              schema:
                type: string
                example: no-store
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
  /api/tenant/transactions/{transactionId}/files/mls-xml:
    get:
      operationId: downloadMlsXml
      x-azdan-scopes:
        - peppol:read
        - transactions:read
        - peppol:submit
      summary: Download the Message Level Status (MLS) XML
      description: |
        Secure per-document download for `documents.mlsXml` — the Peppol
        ApplicationResponse Message Level Status. Same authorization,
        streaming/redirect and `404` semantics as `downloadInvoiceXml`.
      tags:
        - Transaction Documents
      security:
        - ApiKeyBearer: []
        - TenantSession: []
      parameters:
        - $ref: "#/components/parameters/TransactionIdPath"
      responses:
        "200":
          description: File streamed through the Platform API.
          headers:
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename="INV-10001.mls.xml"
            Cache-Control:
              schema:
                type: string
                example: no-store
          content:
            application/xml:
              schema:
                type: string
                format: binary
        "302":
          description: Redirect to a short-lived signed download URL (never a public bucket URL).
          headers:
            Location:
              description: Short-lived signed download URL.
              schema:
                type: string
                format: uri
            Cache-Control:
              schema:
                type: string
                example: no-store
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
  /api/integrations/peppol/transactions/by-message/{messageId}:
    get:
      operationId: getTransactionByMessageId
      summary: Look up transaction by AS4 message ID
      description: |
        Find a transaction by its AS4/AP Core message ID. Useful for correlating
        transport-level IDs from AP logs or network receipts.
      tags:
        - Peppol Transactions
      parameters:
        - name: messageId
          in: path
          required: true
          schema:
            type: string
          example: f0debc61-215c-4d16-9d33-ca5d126ccbb3@peppol.azdanapps.com
      responses:
        "200":
          description: Transaction detail
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Transaction"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
      x-azdan-scopes:
        - transactions:read
        - peppol:read
        - peppol:submit
      x-azdan-default-key: true
      x-azdan-contract-key: byMessage
      x-azdan-access: read
      x-azdan-expected:
        - 200 transaction
        - 401 invalid key
        - 403 insufficient scope
        - 404 unknown message id
  /api/integrations/peppol/transactions/by-idempotency/{idempotencyKey}:
    get:
      operationId: getTransactionByIdempotencyKey
      summary: Look up transaction by Idempotency-Key
      description: |
        Return the transaction that was originally created with the given
        `Idempotency-Key`. Keys are scoped per tenant, so this is a deterministic
        single-row lookup. Use this to confirm whether a previous submit attempt
        succeeded without retrying it.
      tags:
        - Peppol Transactions
      parameters:
        - name: idempotencyKey
          in: path
          required: true
          schema:
            type: string
            minLength: 1
            maxLength: 120
          example: erp-invoice-2026-0001
      responses:
        "200":
          description: Transaction summary
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Transaction"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
      x-azdan-scopes:
        - transactions:read
        - peppol:read
        - peppol:submit
      x-azdan-default-key: true
      x-azdan-contract-key: byIdempotency
      x-azdan-access: read
      x-azdan-expected:
        - 200 transaction
        - 400 key over the limit
        - 401 invalid key
        - 403 insufficient scope
        - 404 unknown key
  /api/integrations/peppol/transactions/{transactionId}/tdd:
    get:
      operationId: getTransactionTdd
      summary: Tax Data Document generated for a transaction
      tags:
        - Peppol Transactions
      parameters:
        - $ref: "#/components/parameters/TransactionIdPath"
      responses:
        "200":
          description: TDD metadata
          content:
            application/json:
              schema:
                type: object
                required:
                  - tdd
                properties:
                  tdd:
                    $ref: "#/components/schemas/TddMetadata"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
      x-azdan-scopes:
        - transactions:read
        - peppol:read
        - peppol:submit
      x-azdan-default-key: true
      x-azdan-contract-key: tdd
      x-azdan-access: optional
      x-azdan-expected:
        - 200 TDD metadata
        - 401 invalid key
        - 403 insufficient scope
        - 404 TDD not generated (expected until it exists)
      description: |-
        Tax Data Documents are generated automatically by AZDAN. Do not submit a TDD. Use the invoice transaction's TDD endpoint to inspect the generated TDD status and download it when available.

        Resolution follows the explicit parent linkage recorded by the access point (never a time or sender guess), so on a self-send the TDD returned is the one generated for THIS outbound document. The download route returns JSON with a short-lived signed URL and needs the privileged peppol:payload:read scope; documents.tddXml / …/files/tdd-xml offer the same file under the ordinary document-read scopes.

        On the enriched detail of an invoice, ap.isTdd is always false and ap.tddStatus is always null — they describe the row itself, not the TDD generated for it. The generated TDD's delivery status is tdd.status on the TDD endpoint.

        Required scope: any of x-azdan-scopes (a default key qualifies).
  /api/integrations/peppol/transactions/{transactionId}/tdd/download:
    get:
      operationId: getTransactionTddDownload
      summary: Signed download link for the generated Tax Data Document
      tags:
        - Peppol Transactions
      parameters:
        - $ref: "#/components/parameters/TransactionIdPath"
        - name: ttlSeconds
          in: query
          required: false
          schema:
            type: integer
            minimum: 1
          description: Requested link lifetime; the server may cap it.
      responses:
        "200":
          description: TDD metadata with a signed download URL
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/TddMetadata"
                  - type: object
                    properties:
                      downloadUrl:
                        type: string
                        format: uri
                      ttlSeconds:
                        type: integer
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
      x-azdan-scopes:
        - peppol:payload:read
      x-azdan-default-key: false
      x-azdan-contract-key: tddDownload
      x-azdan-access: privileged
      x-azdan-required-scope: peppol:payload:read
      x-azdan-expected:
        - 200 JSON with signed downloadUrl
        - 401 invalid key
        - 403 key lacks peppol:payload:read
        - 404 TDD not generated (expected until it exists)
      x-azdan-availability:
        present: 200 JSON with downloadUrl when the TDD exists.
        absent: 404 when no TDD was generated for the transaction.
        source: The generated TDD as JSON metadata plus a short-lived signed URL. The same file is available under the ordinary document scopes as TDD XML.
      description: Same resolution as …/tdd, plus a short-lived signed downloadUrl for the TDD XML. Returns JSON (not a redirect). Resolution follows the explicit parent linkage recorded by the access point (never a time or sender guess), so on a self-send the TDD returned is the one generated for THIS outbound document. The download route returns JSON with a short-lived signed URL and needs the privileged peppol:payload:read scope; documents.tddXml / …/files/tdd-xml offer the same file under the ordinary document-read scopes.
  /api/integrations/peppol/transactions/{transactionId}/events:
    get:
      operationId: getTransactionEvents
      summary: Get webhook events for a transaction
      description: |
        Retrieve the webhook event timeline for a transaction. Shows every
        lifecycle event emitted, delivery status, and any errors. Events are
        sorted chronologically (oldest first).
      tags:
        - Peppol Transactions
      parameters:
        - name: transactionId
          in: path
          required: true
          schema:
            type: string
      responses:
        "200":
          description: Event timeline
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EventsResponse"
              examples:
                timeline:
                  summary: Full outbound lifecycle
                  value:
                    events:
                      - eventId: evt_txn_submitted_abc123
                        type: transaction.submitted
                        deliveryStatus: delivered
                        payload:
                          event: transaction.submitted
                          transactionId: txn_1715690640123_a1b2c3d4
                          status: queued
                          direction: outbound
                          environment: production
                          sender: "0235:1000000001"
                          receiver: "0235:1000000002"
                        createdAt: "2026-05-14T10:00:00.000Z"
                        deliveredAt: "2026-05-14T10:00:01.000Z"
                        attempts: 1
                        lastError: null
                      - eventId: evt_ap_a1b2c3d4e5f6g7h8
                        type: ap.outbound.delivered
                        deliveryStatus: delivered
                        payload:
                          event: ap.outbound.delivered
                          status: delivered
                          direction: outbound
                        createdAt: "2026-05-14T10:00:04.000Z"
                        deliveredAt: "2026-05-14T10:00:05.000Z"
                        attempts: 1
                        lastError: null
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
      x-azdan-scopes:
        - transactions:read
        - peppol:read
        - peppol:submit
      x-azdan-default-key: true
      x-azdan-contract-key: events
      x-azdan-access: read
      x-azdan-expected:
        - 200 events (may be empty)
        - 401 invalid key
        - 403 insufficient scope
components:
  securitySchemes:
    ApiKeyBearer:
      type: http
      scheme: bearer
      bearerFormat: AZDAN API Key
      description: |-
        Integration API key created in the Tenant Console (API Keys): `azd_test_…` or `azd_live_…`. Pass it as `Authorization: Bearer <key>`; it is not a JWT.

        The prefix identifies the key; it does not choose the Peppol network. Routing is decided only by the request's `environment` ("test" | "production", default "test"), and the sender must be registered in that environment.

        Scopes: every operation lists the scopes its route accepts in x-azdan-scopes (any one suffices; the first is the one to ask for). A newly issued key carries transactions:submit and transactions:read.
        peppol:payload:read: Raw payload access: GET …/{transactionId}/xml and …/tdd/download. Not in a default key; request it when an integration must fetch signed URLs for the raw bytes. The …/files/* routes do not need it.
    TenantSession:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: |
        Tenant portal session token (JWT) or the HTTP-only session cookie.
        Used by the tenant-scoped document download endpoints under
        `/api/tenant/*`. A `super_admin` token may access any tenant's
        documents; a tenant token is restricted to its own transactions.
  parameters:
    IdempotencyKey:
      name: Idempotency-Key
      in: header
      required: false
      schema:
        type: string
        minLength: 1
        maxLength: 120
      description: "Send Idempotency-Key as an HTTP header on submit. The key identifies ONE logical submission, scoped to the tenant: the same key always returns the original transaction (idempotent: true) and never sends twice, so retry a timeout or a 5xx with the SAME key and use a new key for a new document. 1 to 120 characters — a longer key is refused with HTTP 400 IDEMPOTENCY_KEY_INVALID before anything is stored, and the same limit applies to the legacy body field idempotencyKey and to the by-idempotency lookup. The header is authoritative; if the legacy body field is also sent the two must be equal (IDEMPOTENCY_KEY_CONFLICT)."
      example: invoice-INV-2026-000123
    TransactionIdPath:
      name: transactionId
      in: path
      required: true
      schema:
        type: string
      description: Platform transaction id (`txn_*`) or AP transaction id.
      example: txn_1715690640123_a1b2c3d4
    CursorLimit:
      name: limit
      in: query
      required: false
      schema:
        type: integer
        minimum: 1
        maximum: 1000
        default: 50
      description: Maximum items to return (cursor mode).
    Cursor:
      name: cursor
      in: query
      required: false
      schema:
        type: string
      description: Opaque cursor from a previous response's `nextCursor`.
    Sort:
      name: sort
      in: query
      required: false
      schema:
        type: string
        enum:
          - createdAt:desc
          - createdAt:asc
          - updatedAt:desc
        default: createdAt:desc
      description: Sort order for cursor pagination.
    Page:
      name: page
      in: query
      required: false
      schema:
        type: integer
        minimum: 1
        default: 1
      description: Page number (page mode only).
    PageSize:
      name: pageSize
      in: query
      required: false
      schema:
        type: integer
        minimum: 1
        maximum: 1000
        default: 25
      description: Items per page (page mode only).
    FilterDirection:
      name: direction
      in: query
      required: false
      schema:
        $ref: "#/components/schemas/Direction"
    FilterStatus:
      name: status
      in: query
      required: false
      schema:
        $ref: "#/components/schemas/TransactionStatus"
    FilterEnvironment:
      name: environment
      in: query
      required: false
      schema:
        $ref: "#/components/schemas/Environment"
    FilterDocumentType:
      name: documentType
      in: query
      required: false
      schema:
        $ref: "#/components/schemas/DocumentType"
    FilterSenderPeppolId:
      name: senderPeppolId
      in: query
      required: false
      schema:
        type: string
      example: "0235:1000000001"
    FilterReceiverPeppolId:
      name: receiverPeppolId
      in: query
      required: false
      schema:
        type: string
      example: "0235:1000000002"
    FilterPeppolParticipantId:
      name: peppolParticipantId
      in: query
      required: false
      schema:
        type: string
      description: Match transactions where sender OR receiver matches.
    FilterSubsidiaryId:
      name: subsidiaryId
      in: query
      required: false
      schema:
        type: string
    FilterCorrelationId:
      name: correlationId
      in: query
      required: false
      schema:
        type: string
    FilterAs4MessageId:
      name: as4MessageId
      in: query
      required: false
      schema:
        type: string
    FilterApCoreMessageId:
      name: apCoreMessageId
      in: query
      required: false
      schema:
        type: string
    FilterSbdhInstanceId:
      name: sbdhInstanceId
      in: query
      required: false
      schema:
        type: string
    FilterIdempotencyKey:
      name: idempotencyKey
      in: query
      required: false
      schema:
        type: string
        maxLength: 120
    FilterDateFrom:
      name: dateFrom
      in: query
      required: false
      schema:
        type: string
        format: date-time
      description: Only transactions created on or after this date.
    FilterDateTo:
      name: dateTo
      in: query
      required: false
      schema:
        type: string
        format: date-time
      description: Only transactions created on or before this date.
    FilterMessageId:
      name: messageId
      in: query
      required: false
      schema:
        type: string
      description: Alias for apCoreMessageId filter.
    FilterSearch:
      name: search
      in: query
      required: false
      schema:
        type: string
      description: Free-text search across transactionId, correlationId, message IDs, and participant IDs.
    IncludeParam:
      name: include
      in: query
      required: false
      schema:
        type: string
        enum:
          - storage
      description: |
        Opt-in to include additional data in list items.
        - `storage`: Attach a lightweight storage summary (driver, fileType, sizeBytes) to each item.
          No S3 keys or filesystem paths are exposed.
  schemas:
    Direction:
      type: string
      enum:
        - inbound
        - outbound
    TransactionStatus:
      type: string
      enum:
        - queued
        - sending
        - delivered
        - failed
        - received
        - quarantined
      x-azdan-notes: |
        queued → sending → delivered (happy path)
        queued → sending → failed (delivery error)
        received (inbound from network)
        quarantined (inbound held for review)
    Environment:
      type: string
      enum:
        - test
        - production
      description: The Peppol network a document is routed to. Set per request (environment, default "test"), stored on the transaction and echoed in every webhook payload. The API key prefix does not influence it; the sender participant must be registered in the environment named.
    SubmittableDocumentType:
      type: string
      enum:
        - invoice
        - creditNote
      description: |
        Document types accepted by validate and submit endpoints.
        - `invoice` — AE PINT Invoice
        - `creditNote` — AE PINT Credit Note
    DocumentType:
      type: string
      enum:
        - invoice
        - creditNote
        - tdd
      description: |-
        All Peppol document types that can appear in transaction responses and list filters.
        - `invoice` and `creditNote` are submittable via the API.
        - `tdd` (UAE Tax Data Document) is **read-only**: Tax Data Documents are generated automatically by AZDAN. Do not submit a TDD. Use the invoice transaction's TDD endpoint to inspect the generated TDD status and download it when available. Inspect it with GET /api/integrations/peppol/transactions/{transactionId}/tdd. Submitting `tdd` via validate or submit is rejected with HTTP 400 (invalid enum value).

        Use `SubmittableDocumentType` for request schemas; use `DocumentType` for response/filter schemas.
    WebhookEventType:
      type: string
      enum:
        - transaction.submitted
        - ap.outbound.created
        - ap.outbound.delivered
        - ap.outbound.failed
        - ap.inbound.received
        - ap.mls.updated
        - transaction.tdd_generated
        - mls.sent
        - mls.received
        - mls.accepted
        - mls.rejected
        - tdd.reported
        - transaction.status_changed
        - document.validated
        - document.rejected
        - webhook.test
      x-azdan-notes: |
        Legacy (v1) names, as stored and as a v1 delivery's `type`:
        transaction.submitted: Emitted immediately when POST /invoices succeeds (v2 name document.submitted).
        ap.outbound.created: AP Core created the outbound row (v2 name document.sent).
        ap.outbound.delivered: AS4 delivery confirmed (v2 name document.delivered).
        ap.outbound.failed: Delivery failed permanently (v2 name document.failed).
        ap.inbound.received: Inbound document received from network (v2 name document.received).
        ap.mls.updated: Message Level Status receipt update (v2 name mls.updated).
        transaction.tdd_generated: A UAE Tax Data Document was generated for a transaction (v2 name tdd.generated).
        mls.sent: This AP sent an MLS ApplicationResponse (linked to the originating transaction where known).
        mls.received: An MLS was received from a peer AP for one of the tenant's outbound transactions.
        Topics introduced with payload v2 (one name only):
        mls.accepted: The receiver's access point accepted or acknowledged the document (MLS AP / AB).
        mls.rejected: The receiver's access point rejected the document (MLS RE), with the reason.
        tdd.reported: The FTA's access point answered a Tax Data Document — outcome accepted or rejected, with the reason.
        transaction.status_changed: The platform transaction moved to another status (previous and new status in the payload).
        document.validated: A document submitted through this API passed validation and was recorded.
        document.rejected: A document submitted through this API failed validation and was not sent (validation issues in the payload; no transaction).
        webhook.test: A test event sent from the console.
    InputType:
      type: string
      enum:
        - json
        - xml
    ParticipantRef:
      type: object
      properties:
        participantId:
          type: string
          description: Peppol participant ID (scheme:id format)
          example: "0235:1000000001"
        name:
          type: string
          nullable: true
          example: Acme Trading LLC
    DocumentLink:
      type: object
      required:
        - available
        - fileName
        - contentType
        - downloadUrl
      description: |
        A single document reference inside the unified `documents` object. When
        `available` is false the file has not been generated/indexed yet:
        `fileName` and `downloadUrl` are null and consumers must treat it as
        not-yet-present.
      properties:
        available:
          type: boolean
          description: Whether the file exists and can be downloaded.
        fileName:
          type: string
          nullable: true
          example: INV-10001.xml
        contentType:
          type: string
          description: Expected MIME type (present even when unavailable).
          example: application/xml
        downloadUrl:
          type: string
          nullable: true
          description: |
            Authenticated Platform API download URL — NEVER a raw object-storage
            (OCI/S3) URL. Relative in API/portal responses; absolute in webhook
            payloads when `PUBLIC_API_BASE_URL` is configured. May resolve to a
            short-lived signed URL, so do not cache it.
          example: /api/integrations/peppol/transactions/txn_1715690640123_a1b2c3d4/files/invoice-xml
        reason:
          type: string
          nullable: true
          enum:
            - metadata_only
            - not_generated
            - not_in_object_storage
            - not_received
            - not_stored
            - not_stored_for_outbound
            - transaction_not_found
            - null
          description: "Present only when available is false: why the document is absent. documents.<kind>.available on the transaction detail is computed from what is actually stored, and the download route resolves the same rows — the two never disagree. An unavailable entry carries reason: not_generated (PDF, TDD), metadata_only (MLS known from the access point without a stored file), not_received (no MLS), not_stored_for_outbound (an outbound submission is payload-only, the SBDH exists only inside the AS4 message) or not_stored. Optional documents answer 404 with the same reason in error.details; that is an expected state, not a failure. Privileged routes (raw payload, TDD signed download) answer 403 without the peppol:payload:read scope."
    TddMetadata:
      type: object
      properties:
        fileId:
          type: string
        transactionId:
          type: string
          description: The invoice / credit note transaction the TDD reports on.
        parentTransactionId:
          type: string
        apTddTransactionId:
          type: string
          description: Access-point transaction id of the TDD transport itself.
        status:
          type: string
          nullable: true
          description: Delivery status of the TDD transport (pending, sending, sent, failed, permanently_failed, …).
        documentTypeId:
          type: string
          nullable: true
        processId:
          type: string
          nullable: true
        generatedAt:
          type: string
          format: date-time
          nullable: true
        sha256:
          type: string
        sizeBytes:
          type: integer
        contentType:
          type: string
        source:
          type: string
          example: ap_core_generated_tdd
        sbdhInstanceId:
          type: string
          nullable: true
        apCoreMessageId:
          type: string
          nullable: true
        tddDownloadUrl:
          type: string
          description: Platform API route for the signed download (peppol:payload:read).
      description: Tax Data Documents are generated automatically by AZDAN. Do not submit a TDD. Use the invoice transaction's TDD endpoint to inspect the generated TDD status and download it when available.
    TransactionDocuments:
      type: object
      description: "documents.<kind>.available on the transaction detail is computed from what is actually stored, and the download route resolves the same rows — the two never disagree. An unavailable entry carries reason: not_generated (PDF, TDD), metadata_only (MLS known from the access point without a stored file), not_received (no MLS), not_stored_for_outbound (an outbound submission is payload-only, the SBDH exists only inside the AS4 message) or not_stored. Optional documents answer 404 with the same reason in error.details; that is an expected state, not a failure. Privileged routes (raw payload, TDD signed download) answer 403 without the peppol:payload:read scope."
      required:
        - invoiceXml
        - invoicePdf
        - sbdXml
        - tddXml
        - mlsXml
      properties:
        invoiceXml:
          $ref: "#/components/schemas/DocumentLink"
        invoicePdf:
          $ref: "#/components/schemas/DocumentLink"
        sbdXml:
          $ref: "#/components/schemas/DocumentLink"
        tddXml:
          $ref: "#/components/schemas/DocumentLink"
        mlsXml:
          $ref: "#/components/schemas/DocumentLink"
        payloadXml:
          type: object
          description: The stored business payload, served as a short-lived signed object-storage URL (303). Same bytes as Invoice XML; a different route with a privileged scope. Integration surface only.
          properties:
            available:
              type: boolean
            privileged:
              type: boolean
              enum:
                - true
            requiredScope:
              type: string
              enum:
                - peppol:payload:read
            contentType:
              type: string
            downloadUrl:
              type: string
              nullable: true
            reason:
              type: string
              nullable: true
    Transaction:
      type: object
      properties:
        transactionId:
          type: string
          example: txn_1715690640123_a1b2c3d4
        direction:
          $ref: "#/components/schemas/Direction"
        status:
          $ref: "#/components/schemas/TransactionStatus"
        documentType:
          type: string
          nullable: true
        documentTypeId:
          type: string
          nullable: true
          description: Full Peppol document type URN.
        processId:
          type: string
          nullable: true
          example: urn:peppol:bis:billing
        sender:
          $ref: "#/components/schemas/ParticipantRef"
        receiver:
          $ref: "#/components/schemas/ParticipantRef"
        correlationId:
          type: string
          nullable: true
        apCoreMessageId:
          type: string
          nullable: true
          description: AP Core / AS4 message ID.
        as4MessageId:
          type: string
          nullable: true
          description: Alias of apCoreMessageId for convenience.
        sbdhInstanceId:
          type: string
          nullable: true
        environment:
          $ref: "#/components/schemas/Environment"
        sizeBytes:
          type: integer
          nullable: true
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
          nullable: true
        deliveredAt:
          type: string
          format: date-time
          nullable: true
        failedAt:
          type: string
          format: date-time
          nullable: true
        failureReason:
          type: string
          nullable: true
        idempotencyKey:
          type: string
          nullable: true
        documents:
          $ref: "#/components/schemas/TransactionDocuments"
    CursorPagination:
      type: object
      required:
        - mode
        - limit
        - hasNext
      properties:
        mode:
          type: string
          const: cursor
        limit:
          type: integer
        nextCursor:
          type: string
          nullable: true
          description: Opaque token for the next page. Pass as `cursor` param.
        prevCursor:
          type: string
          nullable: true
          description: Reserved for future bidirectional cursors.
        hasNext:
          type: boolean
    PagePagination:
      type: object
      required:
        - page
        - pageSize
        - total
        - totalPages
        - hasMore
      properties:
        page:
          type: integer
        pageSize:
          type: integer
        total:
          type: integer
        totalPages:
          type: integer
        hasMore:
          type: boolean
    CursorListResponse:
      type: object
      required:
        - items
        - pagination
      properties:
        items:
          type: array
          items:
            $ref: "#/components/schemas/Transaction"
        pagination:
          $ref: "#/components/schemas/CursorPagination"
    PageListResponse:
      type: object
      required:
        - transactions
        - pagination
      properties:
        transactions:
          type: array
          items:
            $ref: "#/components/schemas/Transaction"
        pagination:
          $ref: "#/components/schemas/PagePagination"
    WebhookEvent:
      type: object
      properties:
        eventId:
          type: string
          example: evt_ap_a1b2c3d4e5f6g7h8
        type:
          $ref: "#/components/schemas/WebhookEventType"
        deliveryStatus:
          type: string
          enum:
            - pending
            - in_flight
            - delivered
            - failed
            - dead
        payload:
          type: object
          description: |
            Event-specific payload. All webhook payloads include the additive
            `documents` object when document lookup succeeds. For
            `transaction.tdd_generated`, the legacy `tddDownloadUrl` field is
            retained and `documents.tddXml` points at the same TDD through the
            unified secure document-download contract.
          properties:
            event:
              type: string
            transactionId:
              type: string
            status:
              type: string
            direction:
              type: string
            environment:
              type: string
            sender:
              type: string
              description: Sender Peppol ID.
            receiver:
              type: string
              description: Receiver Peppol ID.
            documentType:
              type: string
            processId:
              type: string
            correlationId:
              type: string
            apMessageId:
              type: string
            sbdhInstanceId:
              type: string
            tddDownloadUrl:
              type: string
              nullable: true
              description: Legacy TDD download URL retained for backward compatibility on `transaction.tdd_generated`.
              example: /api/integrations/peppol/transactions/txn_1715690640123_a1b2c3d4/tdd/download
            documents:
              $ref: "#/components/schemas/TransactionDocuments"
        createdAt:
          type: string
          format: date-time
        deliveredAt:
          type: string
          format: date-time
          nullable: true
        attempts:
          type: integer
        lastError:
          type: string
          nullable: true
    EventsResponse:
      type: object
      required:
        - events
      properties:
        events:
          type: array
          items:
            $ref: "#/components/schemas/WebhookEvent"
    ApEnrichment:
      type: object
      description: |
        AP Core link status. If `linked: true`, additional AP metadata is available.
        If `linkAmbiguous: true`, multiple AP records match and the system cannot auto-link.
      required:
        - linked
      properties:
        linked:
          type: boolean
          description: Whether this transaction is linked to an AP Core record.
        linkAmbiguous:
          type: boolean
          description: True if multiple AP candidates exist (no auto-link).
        candidateCount:
          type: integer
          description: Number of ambiguous AP candidates (only when linkAmbiguous).
        direction:
          $ref: "#/components/schemas/Direction"
        apTransactionId:
          type: string
          description: AP Core's internal transaction ID.
        status:
          type: string
          description: AP Core status (delivered, permanently_failed, sending, etc.)
        as4MessageId:
          type: string
          nullable: true
          description: AS4 transport message ID.
        sbdhInstanceId:
          type: string
          nullable: true
        messageId:
          type: string
          nullable: true
          description: Same as as4MessageId (legacy alias).
        documentType:
          type: string
          nullable: true
        processId:
          type: string
          nullable: true
        sender:
          type: string
          nullable: true
          description: Normalised sender participant ID (without URI prefix).
        receiver:
          type: string
          nullable: true
          description: Normalised receiver participant ID (without URI prefix).
        createdAt:
          type: string
          format: date-time
          nullable: true
        completedAt:
          type: string
          format: date-time
          nullable: true
        errorDetails:
          type: string
          nullable: true
          description: AP error description (when status is permanently_failed).
        mlsStatus:
          type: string
          nullable: true
          enum:
            - pending
            - received_ap
            - received_ab
            - received_re
            - not_applicable
            - null
          description: MLS values are lower-case, exactly as stored. ap.mlsStatus / ap.mlsReceivedAt / ap.mlsId / ap.mlsType / ap.mlsErrorCode / ap.mlsErrorMessage are metadata on the enriched detail; documents.mlsXml is available only when an MLS XML file is actually stored — for outbound documents it is normally not. Outbound only.
          example: received_ap
        mlsReceivedAt:
          type: string
          format: date-time
          nullable: true
          description: When the MLS was received. Outbound only.
        mlsId:
          type: string
          nullable: true
          description: Identifier of the MLS document. Outbound only.
        mlsType:
          type: string
          nullable: true
          description: MLS document type recorded by the access point (either direction).
        mlsErrorCode:
          type: string
          nullable: true
          description: Error code carried by a negative MLS (received_re). Outbound only.
        mlsErrorMessage:
          type: string
          nullable: true
          description: Error message carried by a negative MLS (received_re). Outbound only.
        isTdd:
          type: boolean
          description: |
            True only when THIS access-point row is itself a UAE Tax Data Document
            transport. For an invoice or credit note it is always false — it does not
            say whether a TDD was generated for the document (use GET
            …/transactions/{transactionId}/tdd for that).
        tddStatus:
          type: string
          nullable: true
          description: |
            Status of this row when it is itself a TDD transport; always null for an
            invoice or credit note. The generated TDD's delivery status is tdd.status
            on GET …/transactions/{transactionId}/tdd.
    StorageInfo:
      type: object
      nullable: true
      description: |
        Primary file storage metadata. The `s3Key` field is included in
        authenticated detail responses but must not be logged or displayed
        in end-user UIs. Use the `/transactions/{id}/xml` endpoint
        to obtain a short-lived presigned download URL instead.
      properties:
        driver:
          type: string
          enum:
            - s3
            - local
        s3Key:
          type: string
          nullable: true
          description: |
            S3 object key (detail view only, not in list storage summary).
            **Do not expose to end-users or store in client-side logs.**
            Use the `/transactions/{id}/xml` endpoint for downloads.
          x-internal: true
        contentType:
          type: string
          example: application/xml
        fileType:
          type: string
          enum:
            - payload
            - sbdh
            - mlr
            - mdn
            - envelope
            - attachment
            - receipt
        sizeBytes:
          type: integer
        cleanupStatus:
          type: string
          enum:
            - clean
            - pending_cleanup
          description: Whether a legacy local path still exists alongside S3.
    StorageSummary:
      type: object
      description: Lightweight storage info returned when `include=storage` is used on the list endpoint.
      properties:
        driver:
          type: string
          enum:
            - s3
            - local
        fileType:
          type: string
        sizeBytes:
          type: integer
    FileInfo:
      type: object
      properties:
        name:
          type: string
          description: Original filename or generated name.
        contentType:
          type: string
          example: application/xml
        sizeBytes:
          type: integer
        storage:
          type: string
          enum:
            - s3
            - local
        s3Key:
          type: string
          nullable: true
          description: S3 object key (null for local-only files).
    PlatformMeta:
      type: object
      description: Platform-specific metadata for the transaction.
      properties:
        transactionId:
          type: string
        status:
          $ref: "#/components/schemas/TransactionStatus"
        correlationId:
          type: string
          nullable: true
        idempotencyKey:
          type: string
          nullable: true
        validation:
          type: object
          properties:
            engine:
              type: string
              nullable: true
        webhookSummary:
          type: object
          nullable: true
          properties:
            totalEvents:
              type: integer
            lastEventType:
              type: string
              nullable: true
            lastEventStatus:
              type: string
              nullable: true
            lastEventAt:
              type: string
              format: date-time
              nullable: true
    TransactionLinks:
      type: object
      description: HATEOAS links to related resources.
      properties:
        self:
          type: string
        events:
          type: string
        xml:
          type: string
    EnrichedTransactionDetail:
      type: object
      required:
        - transaction
        - platform
        - ap
        - storage
        - files
        - documents
        - links
      properties:
        transaction:
          $ref: "#/components/schemas/Transaction"
        platform:
          $ref: "#/components/schemas/PlatformMeta"
        ap:
          $ref: "#/components/schemas/ApEnrichment"
        storage:
          $ref: "#/components/schemas/StorageInfo"
        files:
          type: array
          items:
            $ref: "#/components/schemas/FileInfo"
        documents:
          $ref: "#/components/schemas/TransactionDocuments"
        links:
          $ref: "#/components/schemas/TransactionLinks"
    WebhookDeliveryV2:
      type: object
      description: |
        Shape of the HTTP POST body sent to a webhook whose `payloadVersion` is
        `"2"` (the default for new webhooks). Facts come from the platform
        ledger row of the transaction where it is known; otherwise from the
        event itself and `null` where unknown. `data` is the v1 `payload`
        object unchanged, so nothing a v1 receiver saw is lost.
      required:
        - version
        - eventId
        - eventType
        - occurredAt
        - tenantId
      properties:
        version:
          type: string
          enum:
            - "2"
        eventId:
          type: string
          description: Stable, unique id of the event; the same on every retry (also sent as X-Azdan-Event-Id and Idempotency-Key).
        eventType:
          type: string
          description: The topic's v2 name (e.g. document.delivered).
        legacyType:
          type: string
          nullable: true
          description: The v1 name of the topic when it has one (e.g. ap.outbound.delivered).
        occurredAt:
          type: string
          format: date-time
        webhookId:
          type: string
        tenantId:
          type: string
        companyId:
          type: string
          nullable: true
          description: The subsidiary (company) of the tenant the transaction belongs to.
        transactionId:
          type: string
          nullable: true
          description: The platform transaction id (txn_…) when known.
        apTransactionId:
          type: string
          nullable: true
          description: The access point's own id of the document when the event came from the AP.
        environment:
          $ref: "#/components/schemas/Environment"
        document:
          type: object
          properties:
            kind:
              type: string
              description: invoice, credit_note, self_billing_invoice, self_billing_credit_note, tdd, mls, report or other.
            number:
              type: string
              nullable: true
            typeCode:
              type: string
              nullable: true
            issueDate:
              type: string
              nullable: true
            dueDate:
              type: string
              nullable: true
            direction:
              $ref: "#/components/schemas/Direction"
            documentTypeId:
              type: string
              nullable: true
            processId:
              type: string
              nullable: true
            currency:
              type: string
              nullable: true
            amount:
              type: number
              nullable: true
              description: Payable amount.
            taxAmount:
              type: number
              nullable: true
            netAmount:
              type: number
              nullable: true
            supplierName:
              type: string
              nullable: true
            customerName:
              type: string
              nullable: true
        counterparty:
          type: object
          description: The other party from the tenant's point of view.
          properties:
            role:
              type: string
              enum:
                - sender
                - receiver
            participantId:
              type: string
              nullable: true
            name:
              type: string
              nullable: true
        sender:
          $ref: "#/components/schemas/ParticipantRef"
        receiver:
          $ref: "#/components/schemas/ParticipantRef"
        status:
          type: object
          properties:
            transaction:
              type: string
              nullable: true
              description: The platform status (queued
              sending: null
              delivered: null
              failed: null
              received: null
              quarantined).: null
            previous:
              type: string
              nullable: true
            accessPoint:
              type: string
              nullable: true
            failureReason:
              type: string
              nullable: true
            failureStage:
              type: string
              nullable: true
            deliveredAt:
              type: string
              nullable: true
            failedAt:
              type: string
              nullable: true
        identifiers:
          type: object
          properties:
            correlationId:
              type: string
              nullable: true
            as4MessageId:
              type: string
              nullable: true
            sbdhInstanceId:
              type: string
              nullable: true
        mls:
          type: object
          description: Present on MLS topics.
          properties:
            status:
              type: string
              nullable: true
              description: received_ap
              received_ab: null
              received_re or pending.: null
            outcome:
              type: string
              nullable: true
              enum:
                - accepted
                - acknowledged
                - rejected
            type:
              type: string
              nullable: true
            reasonCode:
              type: string
              nullable: true
            reason:
              type: string
              nullable: true
            receivedAt:
              type: string
              nullable: true
            mlsId:
              type: string
              nullable: true
        tdd:
          type: object
          description: Present on Tax Data Document topics.
          properties:
            apTddTransactionId:
              type: string
              nullable: true
            outcome:
              type: string
              nullable: true
              enum:
                - accepted
                - rejected
            reasonCode:
              type: string
              nullable: true
            reason:
              type: string
              nullable: true
            generatedAt:
              type: string
              nullable: true
            reportedAt:
              type: string
              nullable: true
            sha256:
              type: string
              nullable: true
            sizeBytes:
              type: integer
              nullable: true
            downloadUrl:
              type: string
              nullable: true
        issues:
          type: array
          description: Present on document.rejected — the validation issues.
          items:
            type: object
            properties:
              code:
                type: string
              message:
                type: string
              xpath:
                type: string
              severity:
                type: string
        documents:
          $ref: "#/components/schemas/TransactionDocuments"
        data:
          type: object
          description: The v1 `payload` object, unchanged.
      example:
        version: "2"
        eventId: evt_ap_a1b2c3d4e5f6g7h8
        eventType: document.delivered
        legacyType: ap.outbound.delivered
        occurredAt: "2026-05-14T10:00:03.000Z"
        webhookId: whk_1715690000000_k3j9a1
        tenantId: tnt_acme
        companyId: sub_1715690000000_a1b2
        transactionId: txn_1715690640123_a1b2c3d4
        apTransactionId: 683a1f2e4b0c9d7e1f2a3b4c
        environment: production
        document:
          kind: invoice
          number: INV-10001
          typeCode: "380"
          issueDate: "2026-05-14"
          dueDate: "2026-06-13"
          direction: outbound
          documentTypeId: urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:peppol:pint:billing-1@ae-1::2.1
          processId: urn:peppol:bis:billing
          currency: AED
          amount: 1050
          taxAmount: 50
          netAmount: 1000
          supplierName: Acme Trading LLC
          customerName: Gulf Buyer LLC
        counterparty:
          role: receiver
          participantId: "0235:1000000002"
          name: Gulf Buyer LLC
        sender:
          participantId: "0235:1000000001"
          name: Acme Trading LLC
        receiver:
          participantId: "0235:1000000002"
          name: Gulf Buyer LLC
        status:
          transaction: delivered
          previous: null
          accessPoint: sent
          failureReason: null
          failureStage: null
          deliveredAt: "2026-05-14T10:00:03.000Z"
          failedAt: null
        identifiers:
          correlationId: cor_1715690640123_e5f6a7b8
          as4MessageId: f0debc61-215c-4d16-9d33-ca5d126ccbb3@peppol.azdanapps.com
          sbdhInstanceId: i-1715690640123
        documents:
          invoiceXml:
            available: true
            fileName: INV-10001.xml
            contentType: application/xml
            downloadUrl: https://api.example.com/api/integrations/peppol/transactions/txn_1715690640123_a1b2c3d4/files/invoice-xml
        data:
          event: ap.outbound.delivered
          direction: outbound
          status: sent
    WebhookDelivery:
      type: object
      description: Shape of the HTTP POST body sent to your webhook URL (payload version 1).
      properties:
        eventId:
          type: string
        type:
          $ref: "#/components/schemas/WebhookEventType"
        transactionId:
          type: string
        tenantId:
          type: string
        payload:
          type: object
          properties:
            event:
              type: string
            direction:
              $ref: "#/components/schemas/Direction"
            transactionId:
              type: string
            status:
              type: string
            environment:
              $ref: "#/components/schemas/Environment"
            sender:
              type: string
            receiver:
              type: string
            documentType:
              type: string
            processId:
              type: string
            correlationId:
              type: string
            apMessageId:
              type: string
            sbdhInstanceId:
              type: string
            documents:
              $ref: "#/components/schemas/TransactionDocuments"
            createdAt:
              type: string
              format: date-time
        status:
          type: string
          enum:
            - pending
        attempts:
          type: integer
        createdAt:
          type: string
          format: date-time
      x-azdan-notes: |
        Every delivery includes an X-AZDAN-Signature header for HMAC-SHA256 verification.
        Format: t=<unix_timestamp>,v1=<hex_hmac>[,v1=<hex_hmac of the previous secret>]
        This is the payload-v1 envelope; webhooks with payloadVersion "2" receive WebhookDeliveryV2.
      examples:
        - eventId: evt_ap_a1b2c3d4e5f6g7h8
          type: ap.outbound.delivered
          transactionId: 683a1f2e...
          tenantId: tnt_acme
          payload:
            event: ap.outbound.delivered
            direction: outbound
            transactionId: 683a1f2e...
            status: delivered
            environment: production
            sender: "0235:1000000001"
            receiver: "0235:1000000002"
            documentType: urn:oasis:...:Invoice-2::Invoice##...
            processId: urn:peppol:bis:billing
            correlationId: cor_1715690640123_e5f6a7b8
            apMessageId: f0debc61-215c@peppol.azdanapps.com
            sbdhInstanceId: i-1715690640123
            documents:
              invoiceXml:
                available: true
                fileName: INV-10001.xml
                contentType: application/xml
                downloadUrl: https://peppol.example.com/api/integrations/peppol/transactions/683a1f2e.../files/invoice-xml
              invoicePdf:
                available: false
                fileName: null
                contentType: application/pdf
                downloadUrl: null
              sbdXml:
                available: true
                fileName: INV-10001.sbd.xml
                contentType: application/xml
                downloadUrl: https://peppol.example.com/api/integrations/peppol/transactions/683a1f2e.../files/sbd-xml
              tddXml:
                available: false
                fileName: null
                contentType: application/xml
                downloadUrl: null
              mlsXml:
                available: false
                fileName: null
                contentType: application/xml
                downloadUrl: null
            createdAt: "2026-05-14T10:00:00.000Z"
          status: pending
          attempts: 0
          createdAt: "2026-05-14T10:00:00.000Z"
    ValidateRequest:
      type: object
      required:
        - inputType
        - environment
        - documentType
        - senderPeppolId
        - receiverPeppolId
      properties:
        inputType:
          $ref: "#/components/schemas/InputType"
        environment:
          $ref: "#/components/schemas/Environment"
        documentType:
          $ref: "#/components/schemas/SubmittableDocumentType"
        senderPeppolId:
          type: string
          description: Sender Peppol ID in scheme:id format.
          example: "0235:1000000001"
        receiverPeppolId:
          type: string
          description: Receiver Peppol ID in scheme:id format.
          example: "0235:1000000002"
        payload:
          type: object
          description: Invoice/credit note data (JSON mode only).
        xml:
          type: string
          description: Complete UBL XML document (XML mode only).
    SubmitRequest:
      type: object
      required:
        - inputType
        - environment
        - documentType
        - senderPeppolId
        - receiverPeppolId
      properties:
        inputType:
          $ref: "#/components/schemas/InputType"
        environment:
          $ref: "#/components/schemas/Environment"
        documentType:
          $ref: "#/components/schemas/SubmittableDocumentType"
        senderPeppolId:
          type: string
          example: "0235:1000000001"
        receiverPeppolId:
          type: string
          example: "0235:1000000002"
        idempotencyKey:
          type: string
          minLength: 1
          deprecated: true
          maxLength: 120
          description: Deprecated legacy alternative to the Idempotency-Key header. Prefer the HTTP header. If both are sent they must have the same value or the API returns IDEMPOTENCY_KEY_CONFLICT. Same 1 to 120 character limit as the header (IDEMPOTENCY_KEY_INVALID).
        payload:
          type: object
          description: Invoice/credit note data (JSON mode only).
        xml:
          type: string
          description: Complete UBL XML document (XML mode only).
    ValidateResponse:
      type: object
      properties:
        valid:
          type: boolean
        documentTypeId:
          type: string
        processId:
          type: string
        warnings:
          type: array
          items:
            type: object
        phormSkipped:
          type: boolean
          description: True if only local structural checks ran (Phorm unavailable).
        normalized:
          type: object
          description: Normalized sender/receiver and document metadata.
    SubmitResponse:
      type: object
      properties:
        transactionId:
          type: string
        status:
          $ref: "#/components/schemas/TransactionStatus"
        valid:
          type: boolean
        documentTypeId:
          type: string
        processId:
          type: string
        correlationId:
          type: string
        as4MessageId:
          type: string
          nullable: true
        sbdhInstanceId:
          type: string
          nullable: true
        idempotent:
          type: boolean
          description: True if this is a replay of a previous submission with the same idempotency key.
        warnings:
          type: array
          items:
            type: object
        validatorPhormSkipped:
          type: boolean
        documents:
          $ref: "#/components/schemas/TransactionDocuments"
        message:
          type: string
    ErrorResponse:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
              description: Machine-readable error code. See the ErrorCatalog schema for every value.
              example: PINT_VALIDATION_FAILED
            message:
              type: string
              description: Human-readable error description.
            details:
              type: array
              items:
                type: object
                properties:
                  code:
                    type: string
                  message:
                    type: string
                  path:
                    type: string
    ErrorCatalogEntry:
      type: object
      required:
        - code
        - httpStatus
        - category
        - title
        - message
      description: |
        One row in the public error catalog. The full catalog is documented
        on the Developer Docs page and mirrored at runtime by the
        `peppol.errorCatalog` module in the Platform API.
      properties:
        code:
          type: string
          description: Stable error code returned in `error.code`.
        httpStatus:
          type: integer
          description: HTTP status this code pairs with on the wire.
        category:
          type: string
          enum:
            - validation
            - document
            - xml
            - participant
            - idempotency
            - submission
            - network
            - platform
        title:
          type: string
        message:
          type: string
        hint:
          type: string
          description: Actionable guidance for integrators.
    ErrorCatalog:
      type: object
      description: |
        Authoritative list of the error.code values the integration API
        emits — generated from the runtime catalog and held to it by tests.
        Codes inside error.details[] (PINT-AE rule ids, UNIT_CODE_REQUIRED,
        SELLER_TIN_MISMATCH, …) are documented by the developer contract's
        worked examples. HTTP 429 from the per-key rate limiter carries no
        error.code (plain body, RateLimit-* / Retry-After headers).
      required:
        - entries
      properties:
        entries:
          type: array
          items:
            $ref: "#/components/schemas/ErrorCatalogEntry"
      example:
        entries:
          - code: VALIDATION
            httpStatus: 400
            category: validation
            title: The request envelope failed schema validation
            message: Invalid request
            hint: Read error.issues[] — each entry names the path. A missing or mistyped envelope property, an unknown top-level property (the envelope is strict), a documentType other than invoice / creditNote, or an EAS scheme outside the active OpenPeppol code list all arrive here. Problems INSIDE payload come back as PINT_VALIDATION_FAILED.
          - code: BAD_REQUEST
            httpStatus: 400
            category: validation
            title: The request could not be processed as sent
            message: Bad request
            hint: The message names the problem (for example an unknown document kind on a download route). Correct the request.
          - code: INVALID_JSON
            httpStatus: 400
            category: validation
            title: The request body is not valid JSON
            message: The request body is not valid JSON.
            hint: "Send Content-Type: application/json with a complete, well-formed JSON body — check quotes, commas and closing braces. Nothing was processed."
          - code: PAYLOAD_TOO_LARGE
            httpStatus: 413
            category: validation
            title: The request body is too large
            message: The request body is too large.
            hint: JSON request bodies are limited to 1 MB. Send a smaller request. Nothing was processed.
          - code: UNSUPPORTED_ENCODING
            httpStatus: 415
            category: validation
            title: The request body's encoding is not supported
            message: The request body's encoding is not supported.
            hint: "Send the JSON body as UTF-8, either uncompressed or with Content-Encoding: gzip or deflate."
          - code: PINT_VALIDATION_FAILED
            httpStatus: 400
            category: document
            title: The document failed validation
            message: Document failed Peppol/PINT validation.
            hint: Inspect error.details[] — each finding carries a code, a message and (for XML) an xpath. Fix the document and validate again; nothing was sent.
          - code: UNSUPPORTED_DOC_TYPE
            httpStatus: 400
            category: document
            title: Document type is not supported
            message: Only invoice and creditNote can be validated or submitted.
            hint: Use documentType invoice or creditNote. Tax Data Documents are system-generated by AZDAN and appear on the invoice transaction; they are never submitted.
          - code: UNSUPPORTED_CUSTOMIZATION
            httpStatus: 400
            category: document
            title: The document is not PINT-AE
            message: The document's CustomizationID is not supported on this route.
            hint: cbc:CustomizationID must be urn:peppol:pint:billing-1@ae-1. Produce a PINT-AE document, or use JSON mode and let AZDAN build it.
          - code: UNSUPPORTED_PROFILE
            httpStatus: 400
            category: document
            title: The document's ProfileID is not the Peppol billing process
            message: The document's ProfileID is not supported on this route.
            hint: cbc:ProfileID must be urn:peppol:bis:billing.
          - code: DOCUMENT_TYPE_MISMATCH
            httpStatus: 400
            category: document
            title: The document is not the declared document type
            message: The document is not the document type declared for this submission.
            hint: documentType invoice needs an <Invoice> root, creditNote a <CreditNote> root, both in the UBL 2.1 namespace.
          - code: ROOT_MISMATCH
            httpStatus: 400
            category: document
            title: XML root element does not match documentType
            message: Document root element does not match the declared documentType.
            hint: invoice → <Invoice>, creditNote → <CreditNote>.
          - code: XML_NOT_WELL_FORMED
            httpStatus: 400
            category: xml
            title: XML is not well-formed
            message: Submitted document is not well-formed XML.
            hint: Unclosed tags, wrong encoding or invalid characters. Validate locally with any XML parser before submitting. UTF-8 only; no BOM.
          - code: XML_DTD_FORBIDDEN
            httpStatus: 400
            category: xml
            title: XML contains a prohibited declaration
            message: DOCTYPE / ENTITY declarations are not permitted in Peppol UBL submissions.
            hint: Remove every <!DOCTYPE>, <!ENTITY>, <!ATTLIST>, <!NOTATION> and <!ELEMENT> declaration and every reference to a non-predefined entity.
          - code: INVALID_UAE_TIN
            httpStatus: 400
            category: participant
            title: A UAE participant id is not a ten-digit TIN
            message: A UAE participant identifier (scheme 0235) is not a ten-digit TIN.
            hint: "Under scheme 0235 the participant value is the UAE TIN: exactly ten digits, starting with 1 (e.g. 0235:1002663183). The 15-digit VAT TRN belongs in supplier.taxId / customer.taxId (cac:PartyTaxScheme), never in senderPeppolId, receiverPeppolId, peppolId or cbc:EndpointID."
          - code: UNSUPPORTED_ENDPOINT_SCHEME
            httpStatus: 400
            category: participant
            title: A participant identifier is malformed
            message: A Peppol participant identifier uses an unsupported scheme.
            hint: Use the form NNNN:value with a four-digit EAS code, e.g. 0235:1000000001, and the same scheme in cbc:EndpointID/@schemeID.
          - code: SENDER_ENDPOINT_MISMATCH
            httpStatus: 403
            category: participant
            title: The seller in the document is not the sender
            message: The seller named in the document is not the sender of this submission.
            hint: senderPeppolId must equal the seller's scheme:value (payload.supplier.schemeId:peppolId, or the AccountingSupplierParty EndpointID in XML mode).
          - code: RECEIVER_ENDPOINT_MISMATCH
            httpStatus: 400
            category: participant
            title: The buyer in the document is not the receiver
            message: The buyer named in the document is not the receiver of this submission.
            hint: receiverPeppolId must equal the buyer's scheme:value (payload.customer.schemeId:peppolId, or the AccountingCustomerParty EndpointID in XML mode).
          - code: SENDER_NOT_OWNED
            httpStatus: 403
            category: participant
            title: Sender participant is not configured for this tenant
            message: The sender id is not registered as an active sending participant of your tenant in this environment.
            hint: Check Participants in the portal. The sender must be active, outbound or both, and registered in the environment the request names (test | production).
          - code: PARTICIPANT_C1_COUNTRY_MISSING
            httpStatus: 400
            category: participant
            title: Sender participant has no country code
            message: The sender participant is missing a valid c1CountryCode.
            hint: Ask your AZDAN administrator to set an ISO-3166 alpha-2 country (e.g. AE) on the participant. It is server-owned and cannot be sent in the request.
          - code: PINT_VALIDATION_ENGINE_ERROR
            httpStatus: 503
            validate: 400
            category: validation
            title: The validation engine could not run
            message: The PINT-AE validation engine could not run. The document was not validated and was not sent.
            hint: Not a defect in your document. Retry with the same Idempotency-Key; contact AZDAN support if it persists.
          - code: VALIDATOR_UPSTREAM_ERROR
            httpStatus: 503
            validate: 400
            category: validation
            title: The validation engine could not be reached
            message: Validation service unavailable.
            hint: Not a defect in your document. Retry with the same Idempotency-Key; contact AZDAN support if it persists.
          - code: VALIDATOR_UNAVAILABLE
            httpStatus: 503
            category: validation
            title: Submit refused because validation did not run
            message: PINT-AE validation did not run. Submit refused to avoid forwarding an unvalidated document.
            hint: Not a defect in your document. Retry with the same Idempotency-Key; contact AZDAN support if it persists.
          - code: IDEMPOTENCY_KEY_INVALID
            httpStatus: 400
            category: idempotency
            title: Idempotency key is out of contract
            message: The Idempotency-Key (header, legacy body field, or lookup path) must be 1 to 120 characters.
            hint: "Shorten the key. Nothing was persisted: retry the same submission with a key of at most 120 characters."
          - code: IDEMPOTENCY_KEY_CONFLICT
            httpStatus: 400
            category: idempotency
            title: Header and body idempotency keys disagree
            message: Idempotency-Key header and body.idempotencyKey must have the same value when both are provided.
            hint: "Send the Idempotency-Key header only; body.idempotencyKey is a legacy property. Note: reusing a key never conflicts on body differences — the original transaction is returned with idempotent: true."
          - code: AP_CORE_REJECTED
            httpStatus: 422
            category: submission
            title: The access point could not send the document
            message: AP Core rejected submission
            hint: The document was valid. Read error.details — it carries the transactionId, the lookup / sending error and any AS4 error code. Confirm the receiver is registered on the Peppol network for PINT-AE.
          - code: UPSTREAM
            httpStatus: 502
            category: network
            title: The access point is unreachable
            message: The access point did not answer or returned an error.
            hint: Retry with the same Idempotency-Key. A transaction may have been created in the failed state; look it up with GET /transactions/by-idempotency/{key} before resubmitting.
          - code: INVALID_CURSOR
            httpStatus: 400
            category: platform
            title: Cursor token is malformed
            message: Invalid cursor format
            hint: Pass only a nextCursor value returned by a previous page. Start a new query without a cursor.
          - code: CURSOR_FILTER_MISMATCH
            httpStatus: 400
            category: platform
            title: Cursor was created with different filters
            message: Cursor was generated with different filters. Start a new query without a cursor.
            hint: Keep the filters identical for every page of one query.
          - code: NOT_FOUND
            httpStatus: 404
            category: platform
            title: Resource not found
            message: The requested resource does not exist or is not visible to this tenant.
            hint: Check the id. Documents belonging to another tenant, and documents that do not exist for a transaction (for example an SBD for an outbound payload-only submission), also answer 404.
          - code: PAYLOAD_NOT_IN_OBJECT_STORAGE
            httpStatus: 409
            category: platform
            title: Document file is not available for download
            message: The XML file for this transaction is not retrievable.
            hint: Try again later. If the issue persists, contact AZDAN support with the transactionId.
          - code: UNAUTHORIZED
            httpStatus: 401
            category: platform
            title: Missing or invalid credentials
            message: The Authorization header was missing, malformed, or rejected.
            hint: "Use `Authorization: Bearer azd_…` with an active key issued in the Tenant Console. A revoked key is also refused with 401."
          - code: FORBIDDEN
            httpStatus: 403
            category: platform
            title: API key does not have the required scope
            message: "Missing one of scopes: …"
            hint: The message lists the scopes accepted by the endpoint. Issue a key with one of them (for example peppol:submit, or peppol:payload:read for raw payload downloads).
          - code: INTERNAL
            httpStatus: 500
            category: platform
            title: Unexpected error
            message: An unexpected condition prevented the request from completing.
            hint: Retry shortly. If the issue persists, contact AZDAN support with the correlationId.
  responses:
    ValidationError:
      description: Request validation failed.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
          examples:
            pintFailed:
              summary: The document failed validation
              value:
                valid: false
                documentTypeId: urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:peppol:pint:billing-1@ae-1::2.1
                processId: urn:peppol:bis:billing
                error:
                  code: PINT_VALIDATION_FAILED
                  message: Document failed Peppol/PINT validation.
                  details:
                    - code: PINT_BR_AE_20
                      severity: fatal
                      message: dueDate (IBT-009) is required when the amount due for payment is greater than zero [ibr-127-ae]
                      xpath: /dueDate
    BadRequest:
      description: Invalid request parameters.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
          examples:
            cursorMismatch:
              summary: Cursor filter mismatch
              value:
                error:
                  code: CURSOR_FILTER_MISMATCH
                  message: Cursor was generated with different filters. Start a new query without a cursor.
            invalidCursor:
              summary: Invalid cursor format
              value:
                error:
                  code: INVALID_CURSOR
                  message: Invalid cursor format
    Unauthorized:
      description: Missing or invalid API key.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
          example:
            error:
              code: UNAUTHORIZED
              message: Invalid API key
    Forbidden:
      description: API key lacks required scope.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
          example:
            error:
              code: FORBIDDEN
              message: "Missing scope: transactions:read"
    NotFound:
      description: Resource not found.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
          example:
            error:
              code: NOT_FOUND
              message: Transaction not found
    UpstreamError:
      description: Access point rejected the submission.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
          examples:
            apRejected:
              summary: AP Core rejected submission
              value:
                error:
                  code: UPSTREAM
                  message: AP Core rejected submission
                  details:
                    transactionId: txn_1715690640123_a1b2c3d4
                    upstreamStatus: 400
servers:
  - url: /
    description: "Current domain — resolved against whichever host serves this document. Preferred: it always matches the environment you fetched the spec from."
  - url: https://peppol.azdanapps.com
    description: Production
