myDATA fuel codes (fuel_code): issuing fuel station documents through the API
What turns a document into a fuel document, which fields you send and exactly where each one belongs, all 29 accepted fuel_code values, the three ΑΑΔΕ validation rules, and ready payloads for a forecourt sale and for heating oil.
A fuel station issues the same documents as any other business, with one difference: myDATA wants to know which fuel was sold on each line. That takes two fields, a switch in the header and a code on the line.
{
"fuel_invoice": true,
"invoice_lines": [
{ "fuel_code": 20 }
]
}
Those two are the whole foundation. The rest of this article is where each field belongs, what it accepts, what ΑΑΔΕ rejects, and two complete payloads you can copy.
First, the question underneath: is retail through a provider allowed?
The common assumption is that a station is tied to a fiscal device and that providers are for wholesale and fleet sales only. That is not the case, and the answer sits in the text of the decision itself.
Α.1060/2021, whose άρθρο 1 παρ. 2 was replaced by Α.1155/2021 (ΦΕΚ Β΄ 3132/19.7.2021), provides that the obliged entities transmit «είτε με τη χρήση Φ.Η.Μ., είτε με τη χρήση υπηρεσιών παρόχου ηλεκτρονικής τιμολόγησης», that is either through a fiscal device or through the services of an electronic invoicing provider.
And the very next paragraph lists the data to be transmitted twice: once for «λογιστικά στοιχεία χονδρικής πώλησης (τιμολόγια)», wholesale documents, and once for «λογιστικά στοιχεία λιανικής πώλησης», retail documents. Retail is not carved out of the provider route.
Two qualifications worth as much as the conclusion. First, that decision governs transmission. The right to issue a marked retail document requires a licensed ΥΠΑΗΕΣ provider, which is a different thing from a myDATA connection. The distinction is set out in the article on connecting a SaaS or ERP to myDATA.
Second, and this is where most of the confusion lives: the εισροές-εκροές input-output measuring system is a separate obligation and none of the above touches it. The provider handles the marking and the transmission of the document. Measuring the fuel in the tanks and at the pumps stays exactly where it was.
The four fields, and where each one lives
Placement is half the work here, because a field at the wrong level does not raise an error. It is simply ignored.
| Field | Where it goes | What it does |
|---|---|---|
fuel_invoice |
Header | Boolean. The master switch. Without it, every fuel_code is rejected |
fuel_code |
Line, inside invoice_lines |
Integer. The fuel sold on that particular line |
supply_account_no |
Inside counterpart |
The electricity supply number. At header level it is silently ignored |
special_invoice_category |
Header | Integer. Value 11 is the «Επίδομα Θέρμανσης» heating allowance indication |
The myDATA fuel codes
Twenty eight fuel codes, plus the value 999 for other service charges. They are sent as integers, not strings. A code outside the list is rejected by Wrapp at draft creation, with HTTP 422.
| Value | Description |
|---|---|
10 | Benzine 95RON |
11 | Benzine 95RON+ |
12 | Benzine 100RON |
13 | Benzine LRP |
14 | Aviation gasoline |
15 | Jet fuel |
20 | Diesel |
21 | Diesel premium |
30 | Diesel Heat |
31 | Diesel Heat premium |
32 | Diesel Light |
33 | Diesel for other uses |
34 | Marine diesel |
35 | Kerosene JP1 |
36 | Kerosene for other uses |
37 | Fuel oil |
38 | Marine fuel oil |
40 | LPG |
41 | LPG and methane, industrial / commercial engine use (bulk) |
42 | LPG and methane, heating and other uses (bulk) |
43 | LPG and methane, industrial / commercial engine use (bottled) |
44 | LPG and methane, heating and other uses (bottled) |
50 | CNG (compressed natural gas) |
60 | Aromatic hydrocarbons of tariff heading 2707 |
61 | Cyclic hydrocarbons of tariff heading 2902 |
70 | White spirit |
71 | Light oils |
72 | Biodiesel |
999 | Other service charges |
Forecourt: a retail receipt with two fuels and one service
The typical pump document: a retail receipt (type 11.1), a counterpart with a name only, more than one fuel on the same receipt, and a single 999 line for whatever is not fuel. Replace billing_book_id with the id of your own series, from GET /billing_books.
{
"invoice_type_code": "11.1",
"billing_book_id": "xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"payment_method_type": 1,
"fuel_invoice": true,
"net_total_amount": 91.00,
"vat_total_amount": 21.84,
"total_amount": 112.84,
"payable_total_amount": 112.84,
"counterpart": {
"name": "Retail sale",
"country_code": "GR"
},
"invoice_lines": [
{
"line_number": 1,
"name": "Unleaded 95",
"quantity": 40,
"unit_price": 1.40,
"net_total_price": 56.00,
"vat_rate": 24,
"vat_total": 13.44,
"subtotal": 69.44,
"classification_category": "category1_1",
"classification_type": "E3_561_003",
"fuel_code": 10
},
{
"line_number": 2,
"name": "Road diesel",
"quantity": 20,
"unit_price": 1.50,
"net_total_price": 30.00,
"vat_rate": 24,
"vat_total": 7.20,
"subtotal": 37.20,
"classification_category": "category1_1",
"classification_type": "E3_561_003",
"fuel_code": 20
},
{
"line_number": 3,
"name": "Car wash",
"quantity": 1,
"unit_price": 5.00,
"net_total_price": 5.00,
"vat_rate": 24,
"vat_total": 1.20,
"subtotal": 6.20,
"classification_category": "category1_3",
"classification_type": "E3_561_003",
"fuel_code": 999
}
]
}
Note the 999 line. One per document is allowed, and its net value (5.00) must not exceed the sum of the net values of the other lines (56.00 + 30.00). The classification codes and the payment method code are your own tax decisions per case: the accepted values are in the API documentation.
The three ΑΑΔΕ validation rules
ΑΑΔΕ enforces three rules around these fields, and all three are checked at issue rather than at draft creation.
| Code | Message | When |
|---|---|---|
247 |
fuelCode is forbidden | A fuel_code on a document without fuel_invoice: true |
270 |
only one line can have fuelCode equal with 999 | More than one line carrying 999 |
269 |
the net value of the invoice line with fuelCode 999 must be less or equal than sum of net values of the other invoice lines | The 999 line is larger than the sum of the others |
The practical advice: check all three on your side, even though ΑΑΔΕ enforces them. A code outside the list is caught earlier, at draft creation, with HTTP 422. These three are caught at issue.
Heating oil: four mandatory data points
This is where the schema gets demanding, and the demand is not ours. Α.1139/2025 (ΦΕΚ Β΄ 5464/13.10.2025) added a paragraph to Α.1138/2020 providing that, in the case of transmission through a provider of electronic issuing services, heating oil purchase documents used for the heating allowance must carry four additional data points.
| What the decision requires | Where it goes in the payload |
|---|---|
| The buyer ΑΦΜ | counterpart.vat |
| The fuel code and quantity, «30-Diesel Heating» or «31-Diesel Heating premium» | fuel_code and quantity on the line |
| The electricity supply number | counterpart.supply_account_no |
| The «Επίδομα Θέρμανσης» indication of column 40 | special_invoice_category: 11 |
The fourth is the one that gets misread. The decision says «επιλέγεται η ένδειξη «Επίδομα Θέρμανσης» της στήλης 40 [Παρατηρήσεις - Επισημάνσεις]», and it reads literally: this is a discrete value in a coded column, not free text. Writing it into notes does not satisfy the requirement. The decision names document types 1.1, 1.4, 1.6, 5.1, 5.2, 11.1 and 11.4.
{
"invoice_type_code": "11.1",
"billing_book_id": "xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"payment_method_type": 1,
"fuel_invoice": true,
"special_invoice_category": 11,
"net_total_amount": 800.00,
"vat_total_amount": 192.00,
"total_amount": 992.00,
"payable_total_amount": 992.00,
"counterpart": {
"name": "Giannis Ioannou",
"country_code": "GR",
"vat": "123456789",
"supply_account_no": "12345678"
},
"invoice_lines": [
{
"line_number": 1,
"name": "Heating oil",
"quantity": 800,
"unit_price": 1.00,
"net_total_price": 800.00,
"vat_rate": 24,
"vat_total": 192.00,
"subtotal": 992.00,
"classification_category": "category1_1",
"classification_type": "E3_561_003",
"fuel_code": 30
}
]
}
For a sale to a business rather than a private buyer the structure is the same and the classification changes: invoice type 1.1 with classification_type E3_561_001, because an invoice is always a wholesale document. The four data points still apply, and credit notes are covered too.
The buyer ΑΦΜ is the last thing that should stay a placeholder. Staging accepts anything, production needs the real one, and here it is not just another field: it is one of the four data points the customer's allowance depends on.
The mistake that raises no error
One payload is worth seeing the wrong way round. Below is the most common error in this schema: supply_account_no at the top level instead of inside counterpart.
{
"fuel_invoice": true,
"special_invoice_category": 11,
"supply_account_no": "12345678",
"counterpart": {
"name": "Giannis Ioannou",
"vat": "123456789"
}
}
The document issues normally. You get no error, and the electricity supply number is simply missing: the API ignores unknown top-level fields rather than rejecting them. The Α.1139/2025 requirement goes unmet with no visible sign. The only way to catch it is to read the document back and confirm the field came with it.
Reading the fields back
fuel_invoice and fuel_code come back from find_invoice_by_id and from find_all_invoices. supply_account_no returns inside counterpart, exactly where you sent it. GET /invoices/{id} is deliberately lean, a fiscal-status projection with ΜΑΡΚ, UID, QR, series and number, so it is not the right endpoint for this check.
Useful for idempotency: external_id is unique per account and a duplicate is rejected at draft creation, so retrying a call after a timeout does not produce a second document. The same field is accepted by find_invoice_by_id in place of the id, so you can read a document back by your own identifier.
What the document itself shows
These fields do not stop at myDATA. The document your customer receives prints the «(Παραστατικό Καυσίμων)» fuel-document marking next to the title, the code with its description on each line, for example «(30 - Diesel Heat)», the «Ειδική Κατηγορία Παραστατικού: Επίδομα Θέρμανσης» category and the «Αρ. Παροχής Ηλ. Ρεύματος» supply number.
Getting started
For access to the staging environment, fill in the form on the API partnership page with your ΑΦΜ. Your staging account is created automatically and we will come back to you with your credentials, so you can test every document type before going to production. The full field schema is in the REST API documentation.
If the question behind all this is broader, namely what changes across the board for issuing from 1 October 2026, the timeline and the obligations are there.
Frequently asked questions
Can a petrol station issue a retail receipt through a provider, or is a ΦΗΜ mandatory?
The two routes are alternatives. Α.1060/2021, as replaced by Α.1155/2021 (ΦΕΚ Β΄ 3132/19.7.2021), states that the obliged entities transmit «είτε με τη χρήση Φ.Η.Μ., είτε με τη χρήση υπηρεσιών παρόχου ηλεκτρονικής τιμολόγησης», that is either through a fiscal device or through the services of an electronic invoicing provider. The same decision lists the required data separately for wholesale documents and for retail documents, so retail is not carved out of the provider route. Mind the scope: that decision governs transmission. The right to issue a marked retail document requires a licensed ΥΠΑΗΕΣ provider.
Does a provider replace the input-output measuring system?
No. They are two separate obligations and neither covers the other. The provider handles the marking and the transmission of the document. The εισροές-εκροές system measures fuel in the tanks and at the pumps and is unaffected. Confusing the two is the main reason operators assume retail is closed to providers.
What actually makes a document a fuel document?
The fuel_invoice field in the header, set to true. It is the master switch: without it, a fuel_code on a line is rejected by ΑΑΔΕ with code 247, fuelCode is forbidden. With it on, every line may declare its own fuel_code.
How many fuel codes are there?
Twenty eight fuel codes, from 10 (Benzine 95RON) through 72 (biodiesel), plus the value 999 for other service charges. That is 29 accepted values in total. The full table is in this article and in the API documentation.
Why is supply_account_no not stored when I send it?
Because it belongs to the counterpart object, not to the header. Sent at the top level of the payload it is silently ignored: the document issues normally, you get no error, and the electricity supply number is simply absent. It is the most common mistake with this schema precisely because it does not look like one. Verify by reading the document back.
What does Α.1139/2025 require for heating oil?
The decision (ΦΕΚ Β΄ 5464/13.10.2025) adds four mandatory data points to heating oil purchase documents used for the heating allowance: the buyer ΑΦΜ, the fuel code and quantity (30 or 31), the electricity supply number, and the «Επίδομα Θέρμανσης» indication. The obligation applies explicitly «στην περίπτωση διαβίβασης μέσω Παρόχου Υπηρεσιών Ηλεκτρονικής Έκδοσης Στοιχείων», in the case of transmission through a provider. It does not make the provider route mandatory: it binds those already issuing through one.
Where does the «Επίδομα Θέρμανσης» indication go?
In the special_invoice_category field, with value 11. The decision refers to «την ένδειξη «Επίδομα Θέρμανσης» της στήλης 40 [Παρατηρήσεις - Επισημάνσεις]», and that reads literally: it is a discrete value in a coded column, not free text in a comments field. Writing it into notes does not satisfy the requirement.
Which validation rules does ΑΑΔΕ enforce on the fuel fields?
Three: 247 (fuel_code without fuel_invoice), 270 (more than one line carrying fuel_code 999) and 269 (the net value of the 999 line exceeds the sum of the others). All three are checked at issue. A code outside the list is caught earlier, at draft creation, with HTTP 422. It pays to check all three on your side before you send.
How do I test before going to production?
To get access to the staging environment, fill in the form at wrapp.ai/en/api/becomeapartner with your ΑΦΜ. Your staging account is created automatically and we will come back to you with your credentials so you can start testing.
Need help?
If you have a question about this topic or want to make sure everything is set up correctly, contact us and we will look at it together.