Nordlet

← Τεκμηρίωση / Οδηγοί

Συμβάσεις API

Δομή αιτημάτων, πεδία εμβέλειας (auth scopes), ερωτήματα λist, ποσά, σφάλματα, αμεταβλητότητα (idempotency), όρια ρυθμού κλήσεων (rate limits).

Δομή αιτημάτων

Κάθε λειτουργία είναι ένα POST τύπου RPC:

POST /v1/{module}/{resource}/{action}

Ενότητες (modules): reference, partners, catalog, sales, purchases, ledger, bank, declarations, files, webhooks, audit. Οι ενέργειες είναι ρήματα: create, get, update, delete, list, καθώς και ενέργειες τομέα όπως issue, register, match, apply-advance, generate.

Αυθεντικοποίηση και πεδία εμβέλειας (scopes)

Authorization: Bearer <api key>. Τα κλειδιά φέρουν πεδία εμβέλειας (scopes) που ελέγχονται ανά ενέργεια:

  • {module}:read - ενέργειες ανάγνωσης/λίστας (get/list)
  • {module}:write - τροποποιήσεις (mutations)
  • {module}:* ή * - χαρακτήρες μπαλαντέρ (wildcards)

Ελλιπές scope → 403 forbidden. Ελλιπές ή μη έγκυρο κλειδί → 401 unauthorized.

Ερωτήματα λίστας (List queries)

Όλες οι ενέργειες list μοιράζονται την ίδια σύμβαση:

{
  "page": 1,
  "pageSize": 50,
  "sort": [{ "field": "createdAt", "dir": "desc" }],
  "filter": [{ "field": "paymentStatus", "op": "eq", "value": "unpaid" }]
}

Τελεστές φίλτρων: eq (ίσο), ne (διάφορο), contains (αναζήτηση κειμένου χωρίς διάκριση πεζών-κεφαλαίων, μόνο για πεδία κειμένου), gte (μεγαλύτερο ή ίσο), lte (μικρότερο ή ίσο), in (οποιοδήποτε από μια λίστα έως και 500 τιμών). Τα πεδία ταξινόμησης και φιλτραρίσματος περιλαμβάνονται σε λευκή λίστα (whitelist) ανά τελικό σημείο (δείτε την προδιαγραφή OpenAPI). Τα άγνωστα πεδία επιστρέφουν 400. Προσθέστε το totals: ["field", …] στο αίτημα για να αθροίσετε αριθμητικά πεδία σε κάθε αντίστοιχη γραμμή. Όταν οι εγγραφές φέρουν νόμισμα, το totalsByCurrency παρέχει τα ίδια αθροίσματα χωρισμένα ανά κωδικό νομίσματος. Απαντήσεις: { rows, total, page, pageSize, totals?, totalsByCurrency? }.

Χρηματικά ποσά και ημερομηνίες

Οι χρηματικές αξίες είναι δεκαδικές συμβολοσειρές (strings) με έως 4 δεκαδικά ψηφία ("121.0000") και ποτέ αριθμοί κινητής υποδιαστολής (floats). Ο ΦΠΑ υπολογίζεται ανά γραμμή με στρογγυλοποίηση προς τα πάνω στο πλησιέστερο μισό (half-up). Οι ημερομηνίες είναι της μορφής YYYY-MM-DD, ενώ τα timestamps ακολουθούν το πρότυπο ISO 8601 UTC.

Σφάλματα

Ένας ενιαίος φάκελος (envelope) παντού:

{
  "error": {
    "code": "validation",
    "message": "Request validation failed",
    "requestId": "k1x…",
    "key": "request_invalid",
    "fieldErrors": { "lines.0.unitPriceExclVat": ["Invalid value"] }
  }
}

Κωδικοί: validation (400/422, καθώς και 413 όταν ένα μεταφορτωμένο αρχείο ή σώμα αιτήματος είναι πολύ μεγάλo), unauthorized (401), payment_required (402, η δοκιμαστική περίοδος ή η προπληρωμένη πίστωση έχει λήξει. Το μήνυμα εξηγεί πώς να συνεχίσετε), forbidden (403), not_found (404), conflict (409), idempotency_key_reuse (422), idempotency_in_progress (409), rate_limited (429), internal (5xx). Όταν το μήνυμα είναι ένα από τα σταθερά μηνύματα, το key το κατονομάζει ώστε ένας πελάτης (client) να μπορεί να εμφανίσει τη δική του μετάφραση, και το params περιέχει τις τιμές που ενσωματώνονται σε αυτό (για παράδειγμα { "period": "2026-09" } για μια κλειδωμένη λογιστική περίοδο). Συμπεριλάβετε το requestId όταν αναφέρετε προβλήματα.

Αμεταβλητότητα (Idempotency)

Προσθέστε Idempotency-Key: <οποιαδήποτε συμβολοσειρά ≤255 χαρακτήρων> σε οποιαδήποτε κλήση τροποποίησης (mutation):

  • Επανάληψη με το ίδιο κλειδί και ωφέλιμο φορτίο (payload) → η αποθηκευμένη απάντηση αναπαράγεται byte προς byte με επικεφαλίδα x-idempotent-replay: true.
  • Ίδιο κλειδί, διαφορετικό ωφέλιμο φορτίο → 422 idempotency_key_reuse.
  • Ταυτόχρονο διπλότυπο ενώ το πρώτο βρίσκεται σε εξέλιξη → 409 idempotency_in_progress.
  • Τα κλειδιά ανήκουν στο κλειδί API ή στον χρήστη που τα αποστέλλει, εντός της εταιρείας για την οποία γίνεται η κλήση, επομένως δύο ενοποιήσεις μιας εταιρείας μπορούν να χρησιμοποιήσουν το ίδιο κλειδί. Οι κλήσεις που γίνονται πριν από τη δημιουργία μιας εταιρείας, καθώς και οι κλήσεις account/*, διατηρούν τα κλειδιά ανά χρήστη, ώστε μια επαναλαμβανόμενη κλήση account/companies/create να δημιουργεί ακριβώς μία εταιρεία.
  • Μια αποθηκευμένη απάντηση επιστρέφεται μόνο αφότου ο καλών περάσει ξανά τους ίδιους ελέγχους δικαιωμάτων (scope, ρόλος, εταιρεία και κατάσταση χρέωσης). Διαφορετικά, η κλήση λαμβάνει το τρέχον σφάλμα.
  • Τα κλειδιά λήγουν μετά από 24 ώρες. Οι απαντήσεις σφαλμάτων (4xx) αναπαράγονται επίσης, ενώ οι απαντήσεις 5xx δεν αποθηκεύονται ώστε οι επαναλήψεις να εκτελούνται ξανά.

Όρια ρυθμού κλήσεων (Rate limits)

300 αιτήματα/λεπτό ανά κλειδί API (ανά προσκομιζόμενα διαπιστευτήρια. Τα αιτήματα χωρίς αυθεντικοποίηση περιορίζονται ανά IP). Σε περίπτωση 429, λάβετε υπόψη την κεφαλίδα retry-after. Οι κεφαλίδες x-ratelimit-* αναφέρουν το διαθέσιμο όριό σας.

Webhooks

Τα συμβάντα καταγράφονται σε ένα συναλλακτικό outbox (transactional outbox) στην ίδια συναλλαγή βάσης δεδομένων με την αλλαγή. Ένα έγγραφο του οποίου η συναλλαγή ακυρώθηκε (rolled-back) δεν εκπέμπει ποτέ συμβάν, και κανένα συμβάν δεν χάνεται. Παραδόσεις:

  • POST στη διεύθυνσή URL σας με το JSON του συμβάντος
  • x-nordlet-timestamp: <unix seconds>, η χρονική στιγμή κατά την οποία υπογράφηκε η παράδοση
  • x-nordlet-signature-v2: t=<timestamp>,v1=<hex HMAC-SHA256 of "<timestamp>.<raw body>"> με χρήση του μυστικού της συνδρομής σας
  • x-nordlet-signature: sha256=<hex HMAC-SHA256 of the raw body>, το οποίο διατηρείται αμετάβλητο για τους υφιστάμενους αποδέκτες
  • x-nordlet-delivery φέρει το αναγνωριστικό παράδοσης, το οποίο παραμένει ίδιο σε κάθε επανάληψη μιας παράδοσης
  • Μια απάντηση που δεν είναι 2xx ή μια ανακατεύθυνση επαναλαμβάνεται μετά από 30 δευτερόλεπτα, 2 λεπτά, 10 λεπτά, 30 λεπτά, 1 ώρα, 3 ώρες, 6 ώρες και 12 ώρες, δηλαδή περίπου 24 ώρες συνολικά, προτού η παράδοση χαρακτηριστεί ως αποτυχημένη
  • Κάθε παράδοση αποστέλλεται από έναν διακομιστή τη φορά, επομένως η εκτέλεση πολλών στιγμιότυπων API δεν προκαλεί διπλή αποστολή

Επαληθεύστε το x-nordlet-signature-v2 με μια σύγκριση σταθερού χρόνου (constant-time comparison) προτού εμπιστευτείτε το ωφέλιμο φορτίο, και απορρίψτε μια παράδοση της οποίας το timestamp απέχει περισσότερο από 5 λεπτά από το ρολόι σας. Το timestamp αποτελεί μέρος του υπογεγραμμένου κειμένου, επομένως μια υποδειγματική παράδοση που έχει καταγραφεί δεν μπορεί να επαναληφθεί αργότερα με ένα νέο timestamp. Αποθηκεύστε τα αναγνωριστικά x-nordlet-delivery που έχετε επεξεργαστεί για να αγνοήσετε μια επανάληψη εντός αυτού του παραθύρου. Μια αποτυχημένη παράδοση μπορεί να αποσταλεί ξανά με το webhooks/deliveries/redeliver.

Έλεγχος (Audit)

Κάθε τροποποίηση καταγράφεται (actor, action, entity, diff) και είναι διαθέσιμη προς ερώτησλη μέσω του audit/list.

Λογιστικές εγγυήσεις

  • Οι εγγραφές στο ημερολόγιο είναι ισοσκελισμένες - επιβάλλεται από έναν καθυστερημένο κανόνα (trigger) της βάσης δεδομένων κατά τη στιγμή της δέσμευσης (commit), και όχι απλώς από τον κώδικα της εφαρμογής.
  • Οι αριθμοί των εγγράφων είναι συνεχείς χωρίς κενά (gapless) ανά σειρά/έτος, ενώ η κατανομή είναι ασφαλής ως προς τον συγχρονισμό (concurrency-safe).
  • Οι κλειδωμένες λογιστικές περίοδοι απορρίπτουν οποιαδήποτε καταχώριση φέρει ημερομηνία εντός τους (409).
  • Τα έγγραφα που έχουν διαγραφεί προ-νήματα (soft-deleted) διατηρούν το irdex ελέγχου τους (audit trail). Τα εκδοθέντα/καταχωρισμένα έγγραφα δεν μπορούν να διαγραφούν.

FAQ

(Αυτή η ενότητα θα προστεθεί σύντομα.)