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).
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:
- Your POS creates a transaction via
POST /v1/transactions. - Zyntem assembles the myDATA
<invoice>envelope (UBL-derived AADE schema). - Zyntem sends it to
/SendInvoiceswith theaade-user-idand subscription-key headers. - AADE responds synchronously with the MARK.
- The transaction returns with
fiscal_id=series-number(issuer-side) andfiscal_id_upstream= MARK. - 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:
| Field | Type | Required | Description |
|---|---|---|---|
afm | string | Yes | 9-digit Greek tax id (Αριθμός Φορολογικού Μητρώου). |
branch | integer | Yes | AADE branch id (0 = primary establishment). |
legal_name | string | Yes | Legal name (printed on the invoice and used in counterpart matching). |
aade_user_id | string | Yes | Per-merchant aade-user-id header value (issued by AADE at onboarding). |
subscription_key | string | Yes | Azure APIM subscription key (sealed at registration). |
env | string | Yes | sandbox, production, provider_sandbox, or provider_production. |
document_class | string | Yes | TypeA (single-leg) or TypeB (two-leg). |
default_series | string | Yes | Default 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_reject—RejectedClientstatus witherror.authority_codecarrying the validation-error code (e.g.400series). Correct the invoice and re-issue.permanent— schema mismatch (e.g. wrongvatCategory, missingbranch). 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.