Skip to main content

Greece Fiscalization Guide

What is Greek fiscalization?

Greece operates myDATA (My Digital Accounting and Tax Application), run by AADE (Independent Authority for Public Revenue). Every B2B and B2C invoice must be transmitted to AADE; AADE returns a MARK (Unique Registration Number) which becomes the legal identifier of the invoice.

In plain English: Greece transmits invoices to AADE in JSON or XML and gets back a MARK. There's no client certificate — authentication uses an AADE-issued user id plus an Azure APIM subscription key. Some merchants use a single-leg flow (Type A), others need a second classification leg (Type B).

You don't need to worry about this

Zyntem builds the myDATA invoice envelope, transmits over HTTPS to mydatapi.aade.gr, parses the response, and surfaces the MARK as fiscal_id_upstream. Type A vs Type B is configured per location.

How it works

Greece's flow is synchronous-MARK with asynchronous classification:

  1. Your POS creates a transaction via POST /v1/transactions.
  2. Zyntem assembles the myDATA <invoice> envelope (UBL-derived AADE schema).
  3. Zyntem sends it to /SendInvoices with the aade-user-id and subscription-key headers.
  4. AADE responds synchronously with the MARK.
  5. The transaction returns with fiscal_id = series-number (issuer-side) and fiscal_id_upstream = MARK.
  6. Type B only: Zyntem follows up with /SendIncomeClassification (the issuer's classification leg). The counterpart's expense classification arrives passively from their accounting software.

Type A vs Type B (configured per location):

  • Type A — single-leg sync MARK. Classification is embedded in the invoice envelope. Common for B2C retail and simple B2B services.
  • Type B — two-leg flow: SendInvoices → MARK, then SendIncomeClassification. Common for B2B with itemized expense classifications.

A single AFM may issue both kinds against different series, so document_class is configured per location.

Country config fields

The country_config object for Greek locations:

FieldTypeRequiredDescription
afmstringYes9-digit Greek tax id (Αριθμός Φορολογικού Μητρώου).
branchintegerYesAADE branch id (0 = primary establishment).
legal_namestringYesLegal name (printed on the invoice and used in counterpart matching).
aade_user_idstringYesPer-merchant aade-user-id header value (issued by AADE at onboarding).
subscription_keystringYesAzure APIM subscription key (sealed at registration).
envstringYessandbox, production, provider_sandbox, or provider_production.
document_classstringYesTypeA (single-leg) or TypeB (two-leg).
default_seriesstringYesDefault series (must be unique per (afm, year, branch)).

Configuration example

curl -X POST https://api.zyntem.dev/v1/locations \
-H "Content-Type: application/json" \
-H "Authorization: Bearer zyn_test_abc123def456..." \
-d '{
"name": "Athens Store",
"country": "GR",
"address": "Ermou 1, 105 63 Athens",
"country_config": {
"afm": "094149139",
"branch": 0,
"legal_name": "Zyntem Hellas Ι.Κ.Ε.",
"aade_user_id": "zyntem-hellas",
"subscription_key": "<sealed>",
"env": "production",
"document_class": "TypeA",
"default_series": "A"
}
}'

Creating a transaction

Example: A EUR 50 retail sale at an Athens store.

curl -X POST https://api.zyntem.dev/v1/transactions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer zyn_test_abc123def456..." \
-d '{
"location_id": "loc_abc123",
"type": "sale",
"amount": 5000,
"currency": "EUR",
"line_items": [
{
"description": "Souvenir scarf",
"quantity": 1,
"unit_price": 4032,
"vat_rate": 2400
}
]
}'

Response

{
"id": "txn_abc123",
"status": "success",
"fiscal_id": "A-12345",
"fiscal_id_upstream": "400001234567890",
"country": "GR",
"created_at": "2026-03-15T14:30:22Z"
}

fiscal_id is the issuer-side series-number. fiscal_id_upstream is the AADE-assigned MARK and is what regulators reference.

Submission window

myDATA requires real-time transmission for B2C and end-of-day batched transmission for B2B (current rules; future tightens to 24 hours under provider channel). Zyntem submits per transaction by default; configure batch mode via the location settings if your scale requires it.

Sandbox access

The ERP sandbox is at mydataapidev.aade.gr (Ocp-Apim-Subscription-Key header). Sandbox routing is automatic with a test API key. Subscription keys are obtained from mydata-dev.azure-api.net/portal — typical onboarding is 2–3 days.

Error handling

When AADE rejects an invoice, error.category distinguishes:

  • transient — network blip or AADE 5xx. Zyntem retries automatically.
  • regulatory_rejectRejectedClient status with error.authority_code carrying the validation-error code (e.g. 400 series). Correct the invoice and re-issue.
  • permanent — schema mismatch (e.g. wrong vatCategory, missing branch). Surface to operator.
  • duplicate_as_success — re-submitted invoice already accepted under this MARK. Treated as success.

myDATA also has a "quarantined-with-warnings" outcome — Zyntem reports this as success but surfaces the warning codes in the transaction's response_payload.warnings.

See the Error handling guide for the full taxonomy.