Το EMDI web API είναι ένας τρόπος να επικοινωνήσει το πρόγραμμά σου με την EMDI web (επαφές, προϊόντα, ραντεβού, παραστατικά) χωρίς να ανοίγεις την οθόνη με το χέρι.
Στέλνεις ένα μήνυμα σε μορφή JSON (κείμενο με δομή) και παίρνεις πίσω απάντηση JSON. Τα ονόματα των πεδίων είναι στα Αγγλικά (π.χ. name, city).
Πριν ξεκινήσεις
- Στο admin πακέτων, ενεργοποίησε το EMDI web API για το προϊόν.
- Στην EMDI web άνοιξε Ρυθμίσεις → Εφαρμογές → Σύνδεσμοι εφαρμογής API.
- Πάτησε δημιουργία κλειδιού, αποθήκευσε το HTTP Key.
- Αν άλλαξες πακέτο, κάνε αποσύνδεση και ξανασύνδεση στην EMDI web.
- Κράτα πρόχειρα: το όνομα χρήστη και το HTTP Key (μην τα δημοσιεύεις).
Η πρώτη σου κλήση
Όλες οι κλήσεις καλούν την ίδια διεύθυνση:
https://web.sbzsystems.com/apps/api/call.php?user=YOUR_USER&key=YOUR_HTTPKEY
Αντικατέστησε YOUR_USER και YOUR_HTTPKEY με τα δικά σου διαπιστευτήρια.
- Άνοιξε ένα τερματικό (ή το Postman αν προτιμάς).
- Αντέγραψε την εντολή cURL από κάτω.
- Εκτέλεσέ την. Αν όλα πάνε καλά, θα δεις
"success": trueκαι το αποτέλεσμα. - Αν δεις σφάλμα, διάβασε το
error.message— συνήθως λέει τι λείπει (λάθος κλειδί κ.λπ.).
Αυτή η πρώτη κλήση φέρνει τις λίστες αναφοράς:
|
1 2 3 4 5 6 7 8 |
curl -sS -X POST "https://web.sbzsystems.com/apps/api/call.php?user=YOUR_USER&key=YOUR_HTTPKEY" \ -H "Content-Type: application/json; charset=utf-8" \ -d '{ "action": "meta.lookups", "with": [ "cities" ] }' |
Επιτυχημένη απάντηση (παράδειγμα):
|
1 2 3 4 5 6 7 8 9 10 11 |
{ "success": true, "id": 123, "data": { "id": 123, "code": "C001", "name": "Γιάννης", "surname": "Παπαδόπουλος", "active": 1 } } |
Αποτυχημένη απάντηση (παράδειγμα):
|
1 2 3 4 5 6 7 8 |
{ "success": false, "error": { "code": "validation", "message": "id is required", "field": "id" } } |
Όριο χρήσης
Μπορείς να κάνεις μέχρι 60 κλήσεις ανά λεπτό (ανά χρήστη και IP). Αν ξεπεράσεις το όριο, περίμενε λίγο και ξαναδοκίμασε.
Κατάλογος ενεργειών
Πάτησε μία ενέργεια στον πίνακα για να πας κατευθείαν στο παράδειγμα από κάτω. Κάθε ενέργεια έχει όνομα τύπου contact.get. Πάντα στέλνεις ολόκληρο το JSON (όχι μόνο το action). Κάτω από κάθε αίτημα βλέπεις και παράδειγμα απάντησης.
Χρησιμοποίησέ το πρώτο. Σου φέρνει τις λίστες που χρειάζεσαι μετά (π.χ. είδη παραστατικών, ΦΠΑ, σχέσεις). Αν βάλεις cities, φέρνει και πόλεις.
| Πεδίο | Τι σημαίνει |
|---|---|
action |
τι θέλεις να κάνεις — εδώ πάντα meta.lookups |
with |
προαιρετικό: βάλε [“cities”] αν θέλεις και πόλεις |
|
1 2 3 4 5 6 |
{ "action": "meta.lookups", "with": [ "cities" ] } |
Παράδειγμα απάντησης:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
{ "success": true, "data": { "doc_types": [ { "id": 12, "name": "Τιμολόγιο πώλησης", "series": "Α", "kind": { "xrevstiko": 1, "emf_timvn": 1 }, "tax_docs": "", "till": "" } ], "vat_rates": [ { "id": 1, "rate": 24, "title": "24%" } ], "users": [ { "id": 1, "name": "admin" } ], "relations": [ { "id": 1, "name": "Πελάτης" } ], "units": [ { "id": 1, "name": "τεμ" } ], "main_categories": [ { "id": 1, "name": "Γενικά" } ], "categories": [ { "id": 1, "name": "Λοιπά", "main_category_id": 1 } ], "payment_methods": [ { "id": 1, "name": "Μετρητά" } ], "event_types": [ { "id": 1, "name": "Ραντεβού", "color": 0 } ], "cities": [ { "id": 1, "name": "Αθήνα", "country": "GR" } ] } } |
Διαβάζει μία επαφή με τον εσωτερικό αριθμό της (id). Άλλαξε το 123 με πραγματικό id από τη βάση σου.
| Πεδίο | Τι σημαίνει |
|---|---|
action |
contact.get |
id |
ο αριθμός της επαφής (Aa) |
|
1 2 3 4 |
{ "action": "contact.get", "id": 123 } |
Παράδειγμα απάντησης:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
{ "success": true, "id": 123, "data": { "id": 123, "code": "C001", "name": "Γιάννης", "surname": "Παπαδόπουλος", "company": "Παράδειγμα ΑΕ", "phone": "2100000000", "mobile": "6900000000", "fax": "", "email": "john@example.com", "address": "1 Main St", "area": "Center", "postal_code": "10431", "vat_number": "999999999", "notes": "Δημιουργήθηκε από EMDI web API", "city": "Αθήνα", "tax_office": "Αθηνών", "occupation": "Υπηρεσίες", "relation": "Πελάτης", "payment_method": "Μετρητά", "user": "admin", "parent_contact_id": null, "active": 1, "balance": 0, "created": "2026-09-01", "modified": "2026-09-15T12:00:00" } } |
Φέρνει πολλές επαφές. Το limit λέει πόσες (μέχρι 200). Το offset λέει από ποια θέση να ξεκινήσεις (0 = από την αρχή).
| Πεδίο | Τι σημαίνει |
|---|---|
action |
contact.list |
active |
1 = μόνο ενεργές, 0 = ανενεργές |
limit |
πόσες εγγραφές να φέρει |
offset |
πόσες να παραλείψει από την αρχή |
|
1 2 3 4 5 6 |
{ "action": "contact.list", "active": 1, "limit": 50, "offset": 0 } |
Παράδειγμα απάντησης:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
{ "success": true, "data": { "items": [ { "id": 123, "code": "C001", "name": "Γιάννης", "surname": "Παπαδόπουλος", "company": "Παράδειγμα ΑΕ", "phone": "2100000000", "mobile": "6900000000", "fax": "", "email": "john@example.com", "address": "1 Main St", "area": "Center", "postal_code": "10431", "vat_number": "999999999", "notes": "Δημιουργήθηκε από EMDI web API", "city": "Αθήνα", "tax_office": "Αθηνών", "occupation": "Υπηρεσίες", "relation": "Πελάτης", "payment_method": "Μετρητά", "user": "admin", "parent_contact_id": null, "active": 1, "balance": 0, "created": "2026-09-01", "modified": "2026-09-15T12:00:00" } ], "limit": 50, "offset": 0 } } |
Με id = 0 δημιουργείς νέα. Με match = code ψάχνει αν υπάρχει ήδη ο κωδικός και τον ενημερώνει. Αν η πόλη ή η σχέση δεν υπάρχει ακόμα, το σύστημα την δημιουργεί.
| Πεδίο | Τι σημαίνει |
|---|---|
action |
contact.save |
id |
0 = νέα επαφή |
match |
code = ψάξε/ενημέρωσε με κωδικό |
data |
τα στοιχεία της επαφής (όνομα, πόλη, …) |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
{ "action": "contact.save", "id": 0, "match": "code", "data": { "code": "C001", "name": "Γιάννης", "surname": "Παπαδόπουλος", "company": "Παράδειγμα ΑΕ", "phone": "2100000000", "mobile": "6900000000", "email": "john@example.com", "address": "1 Main St", "area": "Center", "postal_code": "10431", "vat_number": "999999999", "notes": "Δημιουργήθηκε από EMDI web API", "city": "Αθήνα", "tax_office": "Αθηνών", "occupation": "Υπηρεσίες", "relation": "Πελάτης", "payment_method": "Μετρητά", "active": 1 } } |
Παράδειγμα απάντησης:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
{ "success": true, "id": 123, "data": { "id": 123, "code": "C001", "name": "Γιάννης", "surname": "Παπαδόπουλος", "company": "Παράδειγμα ΑΕ", "phone": "2100000000", "mobile": "6900000000", "fax": "", "email": "john@example.com", "address": "1 Main St", "area": "Center", "postal_code": "10431", "vat_number": "999999999", "notes": "Δημιουργήθηκε από EMDI web API", "city": "Αθήνα", "tax_office": "Αθηνών", "occupation": "Υπηρεσίες", "relation": "Πελάτης", "payment_method": "Μετρητά", "user": "admin", "parent_contact_id": null, "active": 1, "balance": 0, "created": "2026-09-01", "modified": "2026-09-15T12:00:00" } } |
Διαγράφει την επαφή. Αν έχει παραστατικά ή είναι κλειδωμένη από myDATA, η κλήση αποτυγχάνει (δεν σβήνει τίποτα).
| Πεδίο | Τι σημαίνει |
|---|---|
action |
contact.delete |
id |
ο αριθμός της επαφής |
|
1 2 3 4 |
{ "action": "contact.delete", "id": 123 } |
Παράδειγμα απάντησης:
|
1 2 3 4 |
{ "success": true, "id": 123 } |
Διαβάζει ένα προϊόν (και barcodes αν υπάρχουν). Άλλαξε το id.
| Πεδίο | Τι σημαίνει |
|---|---|
action |
product.get |
id |
ο αριθμός του προϊόντος |
|
1 2 3 4 |
{ "action": "product.get", "id": 10 } |
Παράδειγμα απάντησης:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
{ "success": true, "id": 10, "data": { "id": 10, "code": "P001", "secondary_code": "", "description": "Δείγμα προϊόντος", "retail_price": 10.5, "wholesale_price": 8.0, "unit": "τεμ", "main_category": "Γενικά", "category": "Λοιπά", "vat_rate": 24, "supplier_id": null, "active": 1, "stock_qty": 100, "barcodes": [ "5200000000001" ], "notes": "Δημιουργήθηκε από EMDI web API", "modified": "2026-09-15T12:00:00" } } |
Φέρνει προϊόντα με φίλτρα. Μπορείς να φιλτράρεις με κωδικό.
| Πεδίο | Τι σημαίνει |
|---|---|
action |
product.list |
code |
κωδικός προϊόντος (προαιρετικό) |
active |
1 = ενεργά |
limit / offset |
σελίδωση |
|
1 2 3 4 5 6 7 |
{ "action": "product.list", "code": "P001", "active": 1, "limit": 50, "offset": 0 } |
Παράδειγμα απάντησης:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
{ "success": true, "data": { "items": [ { "id": 10, "code": "P001", "secondary_code": "", "description": "Δείγμα προϊόντος", "retail_price": 10.5, "wholesale_price": 8.0, "unit": "τεμ", "main_category": "Γενικά", "category": "Λοιπά", "vat_rate": 24, "supplier_id": null, "active": 1, "stock_qty": 100, "barcodes": [ "5200000000001" ], "notes": "Δημιουργήθηκε από EMDI web API", "modified": "2026-09-15T12:00:00" } ], "limit": 50, "offset": 0 } } |
Ίδια λογική με τις επαφές: id 0 = νέο, match:code = ενημέρωση με κωδικό. Το ποσοστό ΦΠΑ (vat_rate) πρέπει να υπάρχει ήδη στις ρυθμίσεις ΦΠΑ.
| Πεδίο | Τι σημαίνει |
|---|---|
action |
product.save |
id |
0 = νέο |
match |
code |
data |
στοιχεία προϊόντος |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
{ "action": "product.save", "id": 0, "match": "code", "data": { "code": "P001", "description": "Δείγμα προϊόντος", "retail_price": 10.5, "wholesale_price": 8.0, "unit": "τεμ", "main_category": "Γενικά", "category": "Λοιπά", "vat_rate": 24, "active": 1, "notes": "Δημιουργήθηκε από EMDI web API" } } |
Παράδειγμα απάντησης:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
{ "success": true, "id": 10, "data": { "id": 10, "code": "P001", "secondary_code": "", "description": "Δείγμα προϊόντος", "retail_price": 10.5, "wholesale_price": 8.0, "unit": "τεμ", "main_category": "Γενικά", "category": "Λοιπά", "vat_rate": 24, "supplier_id": null, "active": 1, "stock_qty": 100, "barcodes": [ "5200000000001" ], "notes": "Δημιουργήθηκε από EMDI web API", "modified": "2026-09-15T12:00:00" } } |
Διαγράφει το προϊόν. Αν χρησιμοποιείται σε παραστατικά, αποτυγχάνει.
| Πεδίο | Τι σημαίνει |
|---|---|
action |
product.delete |
id |
ο αριθμός του προϊόντος |
|
1 2 3 4 |
{ "action": "product.delete", "id": 10 } |
Παράδειγμα απάντησης:
|
1 2 3 4 |
{ "success": true, "id": 10 } |
Διαβάζει ένα ραντεβού με το id του.
| Πεδίο | Τι σημαίνει |
|---|---|
action |
calendar.get |
id |
ο αριθμός του ραντεβού |
|
1 2 3 4 |
{ "action": "calendar.get", "id": 5 } |
Παράδειγμα απάντησης:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
{ "success": true, "id": 5, "data": { "id": 5, "contact_id": 123, "event_type": "Ραντεβού", "user": "admin", "assigned_to": "", "start": "2026-09-20T10:00:00", "end": "2026-09-20T11:00:00", "alarm": "2026-09-20T09:45:00", "comment": "Συνάντηση", "repeat": "", "modified": "2026-09-15T12:00:00" } } |
Φέρνει ραντεβού ανάμεσα σε δύο ημερομηνίες. Η μορφή ημερομηνίας είναι όπως: 2026-09-01 00:00:00.
| Πεδίο | Τι σημαίνει |
|---|---|
action |
calendar.list |
start / end |
από / έως |
contact_id |
προαιρετικά μόνο για μία επαφή |
limit / offset |
σελίδωση |
|
1 2 3 4 5 6 7 8 |
{ "action": "calendar.list", "start": "2026-09-01 00:00:00", "end": "2026-09-30 23:59:59", "contact_id": 123, "limit": 50, "offset": 0 } |
Παράδειγμα απάντησης:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
{ "success": true, "data": { "items": [ { "id": 5, "contact_id": 123, "event_type": "Ραντεβού", "user": "admin", "assigned_to": "", "start": "2026-09-20T10:00:00", "end": "2026-09-20T11:00:00", "alarm": "2026-09-20T09:45:00", "comment": "Συνάντηση", "repeat": "", "modified": "2026-09-15T12:00:00" } ], "limit": 50, "offset": 0 } } |
Για νέο ραντεβού βάλε id 0 και υποχρεωτικά start μέσα στο data.
| Πεδίο | Τι σημαίνει |
|---|---|
action |
calendar.save |
id |
0 = νέο |
data.start |
ημερομηνία/ώρα έναρξης (υποχρεωτικό σε νέο) |
|
1 2 3 4 5 6 7 8 9 10 11 12 |
{ "action": "calendar.save", "id": 0, "data": { "start": "2026-09-20 10:00:00", "end": "2026-09-20 11:00:00", "alarm": "2026-09-20 09:45:00", "comment": "Συνάντηση", "contact_id": 123, "event_type": "Ραντεβού" } } |
Παράδειγμα απάντησης:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
{ "success": true, "id": 5, "data": { "id": 5, "contact_id": 123, "event_type": "Ραντεβού", "user": "admin", "assigned_to": "", "start": "2026-09-20T10:00:00", "end": "2026-09-20T11:00:00", "alarm": "2026-09-20T09:45:00", "comment": "Συνάντηση", "repeat": "", "modified": "2026-09-15T12:00:00" } } |
Διαγράφει το ραντεβού.
| Πεδίο | Τι σημαίνει |
|---|---|
action |
calendar.delete |
id |
ο αριθμός του ραντεβού |
|
1 2 3 4 |
{ "action": "calendar.delete", "id": 5 } |
Παράδειγμα απάντησης:
|
1 2 3 4 |
{ "success": true, "id": 5 } |
Διαβάζει παραστατικό μαζί με τις γραμμές του. Αν είναι κλειδωμένο στο myDATA, το βλέπεις αλλά δεν μπορείς να το αλλάξεις.
| Πεδίο | Τι σημαίνει |
|---|---|
action |
document.get |
id |
ο αριθμός του παραστατικού |
|
1 2 3 4 |
{ "action": "document.get", "id": 1001 } |
Παράδειγμα απάντησης:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
{ "success": true, "id": 1001, "data": { "id": 1001, "series": "Α", "number": 42, "date": "2026-09-15T12:00:00", "doc_type_id": 12, "doc_type": "Τιμολόγιο πώλησης", "contact_id": 45, "delivery_contact_id": null, "payment_method": "Μετρητά", "user": "admin", "comment": "Δοκιμή API", "notes": "", "plate": "", "related": "", "net": 21.0, "total": 26.04, "mydata_locked": false, "modified": "2026-09-15T12:00:00", "lines": [ { "id": 501, "product_id": 10, "code": "P001", "description": "Δείγμα προϊόντος", "unit": "τεμ", "qty": 2, "price": 10.5, "discount": 0, "vat_rate": 24, "order": 1 } ] } } |
Φέρνει παραστατικά. Με include_lines true παίρνεις και τις γραμμές ειδών.
| Πεδίο | Τι σημαίνει |
|---|---|
action |
document.list |
contact_id / doc_type_id |
φίλτρα |
date_from / date_to |
ημερομηνίες |
include_lines |
true = με γραμμές |
|
1 2 3 4 5 6 7 8 9 10 |
{ "action": "document.list", "contact_id": 123, "doc_type_id": 12, "date_from": "2026-09-01", "date_to": "2026-09-30", "include_lines": true, "limit": 20, "offset": 0 } |
Παράδειγμα απάντησης:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
{ "success": true, "data": { "items": [ { "id": 1001, "series": "Α", "number": 42, "date": "2026-09-15T12:00:00", "doc_type_id": 12, "doc_type": "Τιμολόγιο πώλησης", "contact_id": 45, "delivery_contact_id": null, "payment_method": "Μετρητά", "user": "admin", "comment": "Δοκιμή API", "notes": "", "plate": "", "related": "", "net": 21.0, "total": 26.04, "mydata_locked": false, "modified": "2026-09-15T12:00:00", "lines": [ { "id": 501, "product_id": 10, "code": "P001", "description": "Δείγμα προϊόντος", "unit": "τεμ", "qty": 2, "price": 10.5, "discount": 0, "vat_rate": 24, "order": 1 } ] } ], "limit": 20, "offset": 0 } } |
Για νέο παραστατικό χρειάζεσαι: είδος παραστατικού (doc_type_id), επαφή (contact_id) και τουλάχιστον μία γραμμή στο lines. Πάρε τα σωστά id από το meta.lookups. Είδη με φορολογική διαβίβαση (tax_docs) δεν δημιουργούνται από το API.
| Πεδίο | Τι σημαίνει |
|---|---|
action |
document.save |
id |
0 = νέο |
data.doc_type_id |
είδος παραστατικού |
data.contact_id |
επαφή |
data.lines |
γραμμές ειδών (τουλάχιστον μία σε νέο) |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
{ "action": "document.save", "id": 0, "data": { "doc_type_id": 12, "contact_id": 45, "date": "2026-09-15 12:00:00", "payment_method": "Μετρητά", "comment": "Δοκιμή API", "lines": [ { "code": "P001", "description": "Δείγμα προϊόντος", "qty": 2, "price": 10.5, "discount": 0, "vat_rate": 24, "unit": "τεμ", "order": 1 } ] } } |
Παράδειγμα απάντησης:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
{ "success": true, "id": 1001, "data": { "id": 1001, "series": "Α", "number": 42, "date": "2026-09-15T12:00:00", "doc_type_id": 12, "doc_type": "Τιμολόγιο πώλησης", "contact_id": 45, "delivery_contact_id": null, "payment_method": "Μετρητά", "user": "admin", "comment": "Δοκιμή API", "notes": "", "plate": "", "related": "", "net": 21.0, "total": 26.04, "mydata_locked": false, "modified": "2026-09-15T12:00:00", "lines": [ { "id": 501, "product_id": 10, "code": "P001", "description": "Δείγμα προϊόντος", "unit": "τεμ", "qty": 2, "price": 10.5, "discount": 0, "vat_rate": 24, "order": 1 } ] } } |
Διαγράφει παραστατικό και γραμμές. Αν είναι κλειδωμένο myDATA, αποτυγχάνει.
| Πεδίο | Τι σημαίνει |
|---|---|
action |
document.delete |
id |
ο αριθμός του παραστατικού |
|
1 2 3 4 |
{ "action": "document.delete", "id": 1001 } |
Παράδειγμα απάντησης:
|
1 2 3 4 |
{ "success": true, "id": 1001 } |
Σημειώσεις
- Ξεκίνα πάντα με
meta.lookupsπριν φτιάξεις παραστατικά. - Το
idείναι ο εσωτερικός αριθμός καιcodeείναι ο κωδικός που βλέπεις στην οθόνη. - Για ενημέρωση με κωδικό χρησιμοποίησε
"match": "code". - Παραστατικά κλειδωμένα στο myDATA δεν αλλάζουν ούτε διαγράφονται από το API.
