AstroBaaS

Tax & compliance

Greece myDATA E-Invoicing

Paid pluginsize Lcommitted · 2

Indicative price, not an offer: €79–€399/year by volume, or more if the provider fee is bundled (reseller)

Generated from docs/plan/paid/greece-mydata-e-invoicing/PLAN.md in the project's planning notes, which are not part of the public repository. Nothing described below is implemented — it is the written plan for it.

Committed, number 2 in the build order. Greek B2B e-invoicing mandate, issued through a licensed provider. The first paid pack to be built. It comes after Invoices and credit memos. The whole list.

This plan takes over all or part of Accounting Sync (myDATA, Billtrust) and Greek myDATA e-invoicing, entries merged into it.

Paid — commercial track · Tax & compliance · size L Status: planned, not built.

Paid module for Greece that issues legal Greek invoices and receipts through a licensed electronic-invoicing provider (ΥΠΑΗΕΣ), and stores the ΜΑΡΚ, UID, signature and QR code the provider returns on the order. AstroBaaS never issues a legal document itself and never transmits to ΑΑΔΕ on its own.

  • Retail receipts. Under ν.4308/2014 άρθρο 12, these are issued by certified fiscal hardware (ΦΗΜ, παρ. 8) or a licensed provider (παρ. 10).
  • B2B invoices. Under the B2B e-invoicing mandate, these go through a licensed provider, or through ΑΑΔΕ’s own free invoicing app for small issuers. That app is outside this module.

The legal analysis behind this plan is section 1 of docs/PAID-PLUGINS-EU.md. This module attaches to the core invoice record (core/invoices-and-credit-memos).

Rewritten 2026-10-10. The first version of this plan had the module sign invoices with a certificate the merchant uploaded and send them straight to ΑΑΔΕ. That would build software that reports documents nothing lawfully issued. It also got the myDATA API wrong: myDATA’s REST API authenticates with a user id and a subscription key, not a certificate. Both are corrected below.

The problem

A Greek business must issue its sales documents lawfully and report them to ΑΑΔΕ myDATA. A shop that keeps a ΦΗΜ may keep issuing its retail receipts through it, and then this module stays off for retail. A shop that wants to drop the ΦΗΜ for online orders (παρ. 10), and every shop issuing B2B e-invoices under the mandate, needs a licensed provider. Today an AstroBaaS merchant has no connection to one. They re-key every order by hand into the provider’s portal, or they cannot sell to the businesses that now require e-invoices.

Two things that must not be confused

What it isWho may do it
IssuanceCreating the legal document: signed, uniquely marked, archivedA ΦΗΜ, or a licensed ΥΠΑΗΕΣ provider. Never this module.
myDATA transmissionReporting a summary of a document to ΑΑΔΕ, which returns a ΜΑΡΚThe provider does it as part of issuing

This module only connects AstroBaaS to the provider. The merchant remains the legal issuer under their own ΑΦΜ.

What it does

  • Provider adapter interface. It maps an order to a myDATA document type, calls the provider’s API, and stores what comes back. One adapter per provider. The first adapter is for a provider that sells a white-label partner API for exactly this case (Wrapp, provider code 029, is the candidate named in PAID-PLUGINS-EU.md; the choice is an owner decision, see below).
  • Document mapping. Each order maps to a myDATA document type:
    • Τιμολόγιο Πώλησης (1.1) for a domestic business buyer with an ΑΦΜ;
    • 1.2 for a business buyer in another EU country (needs the VIES check, paid/b2b-vat-id-validation-tax-exemption);
    • 1.3 for a business buyer outside the EU;
    • Απόδειξη Λιανικής (11.1) for a consumer, only when the shop issues retail through the provider rather than a ΦΗΜ;
    • Πιστωτικό (5.1 / 11.4) for a refund or a return. The mapping is a pure function with its own tests; the provider never sees an ambiguous order.
  • Issue on the right event, chosen by the shop. Issuance follows the core invoice record becoming final:
    • for retail that is usually payment;
    • for B2B on credit terms it is delivery, or the statutory deadline, not payment. A refund issues the credit document against the original ΜΑΡΚ. A record the shop marked as issued by its ΦΗΜ is never sent, so nothing is reported twice.
  • Stored result. The provider returns the ΜΑΡΚ, UID, authentication code and QR URL. They are stored on the order and printed on the receipt and the PDF exactly as supplied. The issuer owns correctness, and a partner that renders its own PDF must reproduce the mandatory fields verbatim.
  • Queue and retry. Issuing goes through an outbox, never inside the checkout request. A provider outage delays a document; it never fails a checkout. Retries are idempotent: each order carries one stable key, so a retry cannot issue a second document for the same sale.
  • Visible state. Each order shows one of: not yet issued, issued (with ΜΑΡΚ), failed (with the provider’s reason in Greek and English), or cancelled. Failures stop the retry and raise an admin alert.

What it deliberately does NOT do

Each boundary carries its reason. A boundary without a reason gets crossed by the next person who reads this.

  • No direct issuance or direct ΑΑΔΕ transmission. Reason: software alone cannot lawfully issue a Greek document (ν.4308/2014 άρθρο 12 παρ. 8 and 10). A “transmit-only” path would report documents nothing issued.
  • We do not become a provider. Reason: that needs an Άδεια Καταλληλόλητας under Α.1035/2020 and makes us a regulated entity. It is a different business, not a plugin. This is an owner decision already made.
  • No ΦΗΜ driver. Reason: a shop that issues through its cash register keeps doing so. The core records the device’s document number, and this module stays off for those documents. Driving fiscal hardware is a per-vendor project of its own.
  • No accounting. Reason: ledgers, VAT returns and journal entries belong to the accountant and to the ERP bridge (paid/erp-accounting-bridge).

Data model

  • Settings:
    • mydata_provider (the adapter id);
    • provider credentials, stored encrypted like every other payment or carrier secret, never returned by the API;
    • mydata_mode (sandbox or production);
    • the issuer’s ΑΦΜ and the branch number (default 0).
  • Order gains mydata: { status: 'pending' | 'issued' | 'failed' | 'cancelled', doc_type, mark, uid, auth_code, qr_url, issued_at, provider, attempts, last_error }.
  • Customer: the buyer’s ΑΦΜ is the core’s existing Address.tax_id; no second field. The ΔΟΥ is optional. An ΑΦΜ that fails the format or check digit is shown as a warning to staff and to the buyer. It does not block checkout: the core records tax_id without validating it, and a plugin that can veto checkout over it would need an explicit owner decision.
  • Audit: every provider call is logged with its request id and response code. Logs never hold credentials or full personal data.

API

  • GET /api/orders/:id/mydata returns the status and stored identifiers (staff only).
  • POST /api/orders/:id/mydata/issue issues or retries one order (admin only, idempotent).
  • GET /api/mydata/queue lists pending and failed documents (admin only, paginated).
  • POST /api/settings/mydata/test runs a sandbox round trip with the stored credentials.

Every route added here must also appear in src/pages/openapi.json.ts; a test fails the build if it does not.

Admin

  • Settings → Greece: myDATA. Choose the provider, enter credentials, choose sandbox or production, then Test. Test issues a sandbox document and shows the ΜΑΡΚ it got back.
  • Orders list. A myDATA column showing issued, pending or failed.
  • Order detail. The ΜΑΡΚ, UID and QR, the provider’s last response, and an Issue again button for failed documents.
  • Dashboard. A count of failed documents, which links to the queue.

The seam: why this is paid

This module owns:

  • the provider credential;
  • a Greek legal obligation that changes with ΑΑΔΕ decisions;
  • a support commitment when a document is rejected.

The core owns orders, refunds, receipts, the PDF and the plugin seam (PRODUCT_FIELD_DEFS, after-save hooks). Under the shape the owner picks, the provider relationship is either bundled into the price (reseller) or held by the merchant (bring your own provider).

Dependencies

  • core/invoices-and-credit-memos: the frozen invoice and credit-memo record the ΜΑΡΚ is attached to.
  • paid/b2b-vat-id-validation-tax-exemption, for intra-EU documents (1.2) only.
  • Order payment and refund events (core, shipped).
  • Receipt PDF with Greek font support (core, shipped).
  • A provider’s partner API and a signed partner agreement. Not code; the first blocker.

Owner decisions this plan needs

  1. Reseller or bring your own provider. Reseller is simpler for the merchant and is what WooMyData and myApodixi do. Bring your own is simpler for us and has no reseller contract.
  2. Which provider first. Wrapp is named because it sells a partner API, not because it was compared on price or terms.
  3. The mandate dates. B2B e-invoicing is reported to be in force for all remaining businesses since 1 October 2026 (one source says 12 October), and retail is excluded. These dates come from secondary sources. Check them against the ΑΑΔΕ decisions before quoting them to a customer.
  4. Whether a plugin may block checkout over an ΑΦΜ. This plan assumes not.

Acceptance checks

Each of these must be able to fail. Before claiming this is done, break the code deliberately and watch each one go red.

  • A paid B2C order in sandbox comes back with a ΜΑΡΚ and QR. Both appear on the order, the receipt and the PDF, byte-for-byte as the provider returned them.
  • A domestic B2B order with an ΑΦΜ maps to 1.1, an intra-EU one to 1.2, and a non-EU one to 1.3. A retail order maps to 11.1 only when retail issuance is switched on.
  • An ΑΦΜ that fails the check digit warns but never blocks checkout.
  • A record marked as issued by the shop’s ΦΗΜ is never sent to the provider.
  • The provider is down: checkout still succeeds, the document stays pending, and it is issued once the provider is back. Exactly one document exists for that order.
  • Two concurrent retries of one order produce one document (idempotency key).
  • A full refund issues a credit document that references the original ΜΑΡΚ.
  • The provider rejects a document: the order shows failed with the provider’s reason, retries stop, and the admin sees the alert.
  • No code path calls ΑΑΔΕ’s myDATA endpoints directly. A test asserts that only the provider adapter makes outbound calls.
  • Credentials never appear in any API response, log line or export.

Risks

  • The provider changes its API or its terms. Mitigation: the adapter boundary, and a contract with notice periods.
  • ΑΑΔΕ changes document types or dates. Mitigation: the mapping is one tested function, and the dates live in this plan’s owner-decision list, not in code.
  • A rendered PDF drops a mandatory field. Mitigation: the acceptance check above compares fields byte-for-byte.
  • The merchant assumes the module makes them compliant on its own. The admin screen says plainly that the merchant is the legal issuer and that their accountant confirms the setup.

Commercial context

Suggested price€79–€399/year by volume, or more if the provider fee is bundled (reseller)
Rival anchorWooMyData Pro €79–€399/yr; myApodixi ~€179/yr including 50k documents; Primer and Oxygen are providers selling their own subscription.

The anchor is what the nearest equivalent charges for WooCommerce in Greece today. It is context for a pricing decision, not the decision.


Rewritten from the commerce plan on 2026-10-10. See docs/PAID-PLUGINS-EU.md section 1 for the legal analysis and docs/COMMERCE-PLAN.md for the catalogue.