Εμφάνιση
Δημιουργία παραγγελίας
Η κλήση POST /orders δημιουργεί μια νέα παραγγελία στο CourierHub, με τους ίδιους κανόνες όπως η χειροκίνητη δημιουργία παραγγελίας από το περιβάλλον πελάτη. Η παραγγελία εμφανίζεται αμέσως στη λίστα παραγγελιών του CourierHub, όπου μπορείτε να εκδώσετε voucher.
WARNING
Θα πρέπει να συμπεριλάβετε το API Token σας σε κάθε αίτημα ως Bearer Token. Αντικαταστήστε το YOUR_TOKEN με το API Token του καταστήματος (chub_...). Δείτε το Overview.
| Method | URI | Headers |
|---|---|---|
| POST | /api/v2/orders | Authorization: Bearer YOUR_TOKENContent-Type: application/json |
Πριν ξεκινήσετε
- Κατάστημα. Η νέα παραγγελία ανήκει στο κατάστημα του token που χρησιμοποιήσατε. Με το token άλλου καταστήματος του ίδιου λογαριασμού δημιουργείτε παραγγελία σε εκείνο το κατάστημα.
order_numberκαιorder_id. Τοorder_numberείναι ο δικός σας αριθμός παραγγελίας και είναι υποχρεωτικός. Τοorder_idτο παράγει το CourierHub (αριθμητικό, π.χ.20261015101200482) και δεν το στέλνετε. Δείτε order_id και order_number.- Μοναδικός αριθμός. Το
order_numberπρέπει να είναι μοναδικό ανάμεσα στις (μη διαγραμμένες) παραγγελίες του καταστήματος, συμπεριλαμβανομένων αυτών που ήρθαν από το e-shop. Τα#1001και1001θεωρούνται ο ίδιος αριθμός. Αν υπάρχει ήδη, η απάντηση είναι409 order_number_taken. Μια διαγραμμένη παραγγελία ελευθερώνει τον αριθμό της. - Χωρίς συγχρονισμό με e-shop. Οι παραγγελίες που δημιουργούνται από το API είναι παραγγελίες του CourierHub: δεν στέλνονται σε e-shop (Shopify, WooCommerce κ.λπ.), ακόμα κι αν το κατάστημα του token είναι συνδεδεμένο με e-shop.
- Courier. Το
courier_idείναι τοidαπό το GET /couriers, δηλαδή μία από τις courier που έχετε συνδέσει στον λογαριασμό σας.
Μεταβλητές αποστολής
Το σώμα (body) είναι JSON. Τα ποσά μπορείτε να τα στείλετε ως string ("12.90", προτείνεται) ή ως αριθμό (12.9), με έως 2 δεκαδικά. Στην απάντηση επιστρέφονται πάντα ως string.
| Variable Name | Type | Usage | Required |
|---|---|---|---|
order_number | String | Ο δικός σας αριθμός παραγγελίας, έως 64 χαρακτήρες. Επιτρέπονται γράμματα (και ελληνικά), ψηφία και οι χαρακτήρες # . _ / -, χωρίς κενά (π.χ. #1001, 1001, INV-2026/17). Τα κενά στην αρχή και στο τέλος αφαιρούνται. Αποθηκεύεται όπως το στείλατε (με ή χωρίς #). Μοναδικό στο κατάστημα. | * |
status | String | pending (προεπιλογή) ή processing. Οι υπόλοιπες καταστάσεις ορίζονται από το CourierHub. Με receive_from_reception: true η κατάσταση γίνεται store_pickup. | |
order_date | String | Ημερομηνία παραγγελίας. Προτείνεται ISO 8601 με ζώνη ώρας (π.χ. 2026-10-15T07:05:00Z ή 2026-10-15T10:05:00+03:00). Χωρίς ζώνη ώρας ερμηνεύεται ως ώρα Ελλάδας. Προεπιλογή: η στιγμή της δημιουργίας. | |
recipient | Object | Τα στοιχεία του παραλήπτη (τα παρακάτω πεδία). | * |
recipient.name | String | Ονοματεπώνυμο, έως 255 χαρακτήρες. | * |
recipient.phone | String | Τηλέφωνο. Πριν τον έλεγχο αφαιρούνται κενά, παύλες, τελείες, παρενθέσεις και /, και το 00 στην αρχή γίνεται + (π.χ. 0030 2310 123456 γίνεται +302310123456). Το αποτέλεσμα πρέπει να είναι 7 έως 15 ψηφία, με προαιρετικό + στην αρχή. | * |
recipient.email | String | Έγκυρο email, έως 255 χαρακτήρες. | * |
recipient.address | String | Διεύθυνση (οδός και αριθμός), έως 255 χαρακτήρες. | * |
recipient.city | String | Πόλη / περιοχή, έως 100 χαρακτήρες. | * |
recipient.postal_code | String | Ταχυδρομικός κώδικας. Τα κενά αφαιρούνται από αριθμητικούς κώδικες (105 63 γίνεται 10563) και τα γράμματα γίνονται κεφαλαία. Για GR: ακριβώς 5 ψηφία. Για CY: ακριβώς 4 ψηφία. Για τις άλλες χώρες: 2 έως 20 γράμματα, ψηφία, κενά ή παύλες. | * |
recipient.country | String | GR, CY, EU, US ή OTHER (γίνονται δεκτά και με πεζά, π.χ. gr). | * |
receive_from_reception | Boolean | true για παραλαβή από το δικό σας κατάστημα (store pickup): η παραγγελία δεν έχει courier και παίρνει κατάσταση store_pickup. Προεπιλογή false. Δείτε Παραλαβή από κατάστημα. | |
courier_id | Integer | Η courier της αποστολής: το id από το GET /couriers. Πρέπει να είναι courier συνδεδεμένη στον λογαριασμό σας. Υποχρεωτικό, εκτός αν receive_from_reception: true (τότε αγνοείται). | * |
services | Array | Επιπλέον υπηρεσίες courier, από τις saturday, epistrofi, receive_from_reception (χωρίς διπλές τιμές). Δεν επιτρέπονται για Box Now ή για παραλαβή από το κατάστημα. Δείτε Υπηρεσίες. | |
locker_id | String | Η θυρίδα (locker) Box Now, έως 64 χαρακτήρες (γράμματα, ψηφία και . _ : -). Υποχρεωτικό όταν η courier είναι Box Now, δεν επιτρέπεται για άλλες courier. | |
payment_method | String | Τρόπος πληρωμής: cod (αντικαταβολή), paypal, stripe, bank_transfer, other. | * |
cod_cost | String | Έξοδα αντικαταβολής, 0 έως 999999.99, έως 2 δεκαδικά. Μόνο με payment_method: cod: σε άλλο τρόπο πληρωμής γίνεται δεκτό μόνο 0 / null και αποθηκεύεται 0.00. Προεπιλογή 0. | |
shipping_cost | String | Μεταφορικά, 0 έως 999999.99, έως 2 δεκαδικά. Προεπιλογή 0. | |
subtotal | String | Αξία προϊόντων, 0 έως 99999999.99, έως 2 δεκαδικά. Αν λείπει, υπολογίζεται ως το άθροισμα των products (0 αν δεν υπάρχουν προϊόντα). Αν το στείλετε, υπερισχύει του αθροίσματος (π.χ. για εκπτώσεις). | |
weight | String | Βάρος σε κιλά, μεγαλύτερο του 0 και έως 99999.999, έως 3 δεκαδικά. | |
notes | String | Σημειώσεις, έως 1000 χαρακτήρες. | |
products | Array | Τα προϊόντα της παραγγελίας, έως 100. | |
products[].name | String | Όνομα προϊόντος, έως 255 χαρακτήρες. | * |
products[].sku | String | Κωδικός προϊόντος, έως 100 χαρακτήρες. | |
products[].unit_price | String | Τιμή μονάδας, 0 έως 99999999.99, έως 2 δεκαδικά. | * |
products[].quantity | Integer | Ποσότητα, 1 έως 100000. | * |
Τα πεδία με * στο products[] είναι υποχρεωτικά για κάθε προϊόν, όταν στέλνετε products.
Ποσά
- Το
total_amountδεν το στέλνετε: υπολογίζεται πάντα ωςsubtotal + shipping_cost + cod_cost. - Το
total_priceκάθε προϊόντος είναιunit_price × quantity. - Σε αντικαταβολή (
cod), το ποσό που εισπράττει η courier είναι τοtotal_amount(μαζί με μεταφορικά και έξοδα αντικαταβολής). - Το σύνολο της παραγγελίας και το σύνολο κάθε προϊόντος δεν μπορούν να ξεπερνούν το
99999999.99.
Υπηρεσίες (services)
| Τιμή | Σημασία |
|---|---|
saturday | Παράδοση το Σάββατο. |
epistrofi | Παράδοση / Παραλαβή: ο courier παραδίδει το δέμα και παραλαμβάνει ταυτόχρονα δέμα επιστροφής. |
receive_from_reception | Ο παραλήπτης παραλαμβάνει το δέμα από το κατάστημα της courier. |
Η υπηρεσία receive_from_reception (παραλαβή από κατάστημα της courier) είναι διαφορετική από το πεδίο receive_from_reception: true (παραλαβή από το δικό σας κατάστημα, χωρίς courier). Οι υπηρεσίες εφαρμόζονται όταν εκδίδεται το voucher, εφόσον τις υποστηρίζει η courier.
Παραλαβή από κατάστημα
Με receive_from_reception: true η παραγγελία γίνεται Παραλαβή από Κατάστημα: το courier_id αγνοείται (αποθηκεύεται χωρίς courier), δεν επιτρέπονται services ούτε locker_id, και η κατάσταση γίνεται store_pickup. Δεν χρειάζεται voucher.
Box Now
Για courier Box Now το locker_id είναι υποχρεωτικό και δεν επιτρέπονται services. Το locker_id είναι το ID της θυρίδας Box Now όπου θα παραδοθεί το δέμα.
Απάντηση αιτήματος
Επιτυχής δημιουργία: HTTP 201 με την παραγγελία μέσα στο κλειδί data, με τα πεδία που περιγράφονται στο GET /orders/{id} (μαζί με products και shipments, που είναι κενό). Κρατήστε το id για τις επόμενες κλήσεις (GET, PATCH, DELETE /orders/{id}).
| Variable Name | Type | Description |
|---|---|---|
data | Object | Η νέα παραγγελία (order). |
data.id | Integer | Το ID της παραγγελίας για τα /orders/{id}. |
data.order_id | String | Ο αριθμός που παρήγαγε το CourierHub. |
Παράδειγμα σώματος αιτήματος (αντικαταβολή, με προϊόντα):
json
{
"order_number": "#1001",
"order_date": "2026-10-15T07:05:00Z",
"recipient": {
"name": "Μαρία Παπαδοπούλου",
"phone": "694 123 4567",
"email": "maria@example.com",
"address": "Ερμού 25",
"city": "Αθήνα",
"postal_code": "105 63",
"country": "gr"
},
"courier_id": 8,
"payment_method": "cod",
"shipping_cost": "3.50",
"cod_cost": "1.50",
"weight": "1.2",
"notes": "Κουδούνι: Παπαδοπούλου",
"products": [
{ "name": "Κούπα κεραμική", "sku": "MUG-01", "unit_price": "12.90", "quantity": 2 },
{ "name": "Σουβέρ (σετ 4)", "unit_price": "6.00", "quantity": 1 }
]
}Παράδειγμα επιτυχημένης δημιουργίας (HTTP 201).
Το τηλέφωνο, ο ταχυδρομικός κώδικας και η χώρα έχουν κανονικοποιηθεί, το subtotal είναι το άθροισμα των προϊόντων (25.80 + 6.00) και το total_amount είναι 31.80 + 3.50 + 1.50.
json
{
"data": {
"id": 1,
"order_id": "20261015101200482",
"order_number": "#1001",
"status": "pending",
"status_label": "Εκκρεμής",
"order_date": "2026-10-15T07:05:00Z",
"recipient": {
"name": "Μαρία Παπαδοπούλου",
"phone": "6941234567",
"email": "maria@example.com",
"address": "Ερμού 25",
"city": "Αθήνα",
"postal_code": "10563",
"country": "GR"
},
"receive_from_reception": false,
"courier": {
"id": 8,
"name": "ACS"
},
"services": [],
"locker_id": null,
"payment_method": "cod",
"subtotal": "31.80",
"shipping_cost": "3.50",
"cod_cost": "1.50",
"total_amount": "36.80",
"weight": "1.200",
"notes": "Κουδούνι: Παπαδοπούλου",
"has_shipment": false,
"store": {
"id": 1,
"name": "Το Κατάστημά μου"
},
"products": [
{
"name": "Κούπα κεραμική",
"sku": "MUG-01",
"unit_price": "12.90",
"quantity": 2,
"total_price": "25.80"
},
{
"name": "Σουβέρ (σετ 4)",
"sku": null,
"unit_price": "6.00",
"quantity": 1,
"total_price": "6.00"
}
],
"shipments": [],
"created_at": "2026-10-15T07:12:00Z",
"updated_at": "2026-10-15T07:12:00Z"
}
}Παράδειγμα χωρίς αντικαταβολή, με υπηρεσία Σαββάτου (HTTP 201).
Αίτημα:
json
{
"order_number": "INV-2026/17",
"recipient": {
"name": "Γιώργος Νικολάου",
"phone": "0030 2310 123456",
"email": "giorgos@example.com",
"address": "Τσιμισκή 40",
"city": "Θεσσαλονίκη",
"postal_code": "54623",
"country": "GR"
},
"courier_id": 9,
"services": ["saturday"],
"payment_method": "stripe",
"shipping_cost": "0",
"products": [
{ "name": "Τσάντα πάνινη", "sku": "BAG-02", "unit_price": "24.00", "quantity": 1 }
]
}Απάντηση:
json
{
"data": {
"id": 2,
"order_id": "20261015101700155",
"order_number": "INV-2026/17",
"status": "pending",
"status_label": "Εκκρεμής",
"order_date": "2026-10-15T07:17:00Z",
"recipient": {
"name": "Γιώργος Νικολάου",
"phone": "+302310123456",
"email": "giorgos@example.com",
"address": "Τσιμισκή 40",
"city": "Θεσσαλονίκη",
"postal_code": "54623",
"country": "GR"
},
"receive_from_reception": false,
"courier": {
"id": 9,
"name": "ELTA"
},
"services": [
"saturday"
],
"locker_id": null,
"payment_method": "stripe",
"subtotal": "24.00",
"shipping_cost": "0.00",
"cod_cost": "0.00",
"total_amount": "24.00",
"weight": null,
"notes": null,
"has_shipment": false,
"store": {
"id": 1,
"name": "Το Κατάστημά μου"
},
"products": [
{
"name": "Τσάντα πάνινη",
"sku": "BAG-02",
"unit_price": "24.00",
"quantity": 1,
"total_price": "24.00"
}
],
"shipments": [],
"created_at": "2026-10-15T07:17:00Z",
"updated_at": "2026-10-15T07:17:00Z"
}
}Box Now και παραλαβή από κατάστημα
Box Now (με locker_id, χωρίς προϊόντα, με subtotal):
json
{
"order_number": "1003",
"recipient": {
"name": "Ελένη Γεωργίου",
"phone": "6977000111",
"email": "eleni@example.com",
"address": "Αγίου Δημητρίου 12",
"city": "Πάτρα",
"postal_code": "26221",
"country": "GR"
},
"courier_id": 10,
"locker_id": "4-123",
"payment_method": "paypal",
"subtotal": "18.00",
"shipping_cost": "2.90"
}Η απάντηση έχει "courier": {"id": 10, "name": "Box Now"}, "locker_id": "4-123", "products": [] και "total_amount": "20.90".
Παραλαβή από το κατάστημά σας (χωρίς courier_id):
json
{
"order_number": "1004",
"recipient": {
"name": "Νίκος Ιωάννου",
"phone": "6900000000",
"email": "nikos@example.com",
"address": "Ερμού 1",
"city": "Αθήνα",
"postal_code": "10563",
"country": "GR"
},
"receive_from_reception": true,
"payment_method": "other",
"products": [
{ "name": "Κούπα κεραμική", "sku": "MUG-01", "unit_price": "12.90", "quantity": 1 }
]
}Η απάντηση έχει "status": "store_pickup", "status_label": "Παραλαβή από Κατάστημα", "receive_from_reception": true και "courier": null.
Σφάλματα
Ο έλεγχος γίνεται σε δύο στάδια. Πρώτα ελέγχονται τα υποχρεωτικά πεδία και η μορφή κάθε πεδίου. Αν περάσουν, ελέγχεται ότι το order_number είναι ελεύθερο (409) και μετά οι κανόνες που συνδυάζουν πεδία (courier και locker_id / services, cod_cost και payment_method, ταχυδρομικός κώδικας και χώρα). Γι' αυτό, αφού διορθώσετε ένα 422, μπορεί να πάρετε δεύτερο 422 με άλλα πεδία.
| HTTP | code | Πότε |
|---|---|---|
| 409 | order_number_taken | Υπάρχει ήδη μη διαγραμμένη παραγγελία του καταστήματος με αυτό το order_number (#1001 = 1001), ή ένα άλλο αίτημα δημιουργεί αυτή τη στιγμή παραγγελία με τον ίδιο αριθμό. |
| 422 | validation_failed | Λείπουν υποχρεωτικά πεδία ή δεν είναι έγκυρα. Το errors έχει τα προβλήματα ανά πεδίο (π.χ. recipient.phone, products.0.quantity). |
Αριθμός παραγγελίας που υπάρχει ήδη (409 Conflict).
Αίτημα με "order_number": "1001", ενώ υπάρχει ήδη η #1001:
json
{
"message": "An order with this order_number already exists in this store.",
"code": "order_number_taken"
}Αν δύο αιτήματα με τον ίδιο αριθμό φτάσουν ταυτόχρονα, το δεύτερο περιμένει το πρώτο και παίρνει το παραπάνω 409. Αν η αναμονή ξεπεράσει τα λίγα δευτερόλεπτα, παίρνει 409 με τον ίδιο code και message "Another request is writing an order with this order_number. Retry later.". Πριν ξαναδοκιμάσετε, ελέγξτε με το GET /orders?order_number=... αν η παραγγελία δημιουργήθηκε ήδη.
Παράδειγμα σφάλματος (κενό σώμα).
json
{
"message": "The given data was invalid.",
"code": "validation_failed",
"errors": {
"order_number": [
"The order number field is required."
],
"recipient": [
"The recipient field is required."
],
"recipient.name": [
"The recipient.name field is required."
],
"recipient.phone": [
"The recipient.phone field is required."
],
"recipient.email": [
"The recipient.email field is required."
],
"recipient.address": [
"The recipient.address field is required."
],
"recipient.city": [
"The recipient.city field is required."
],
"recipient.postal_code": [
"The recipient.postal code field is required."
],
"recipient.country": [
"The recipient.country field is required."
],
"payment_method": [
"The payment method field is required."
]
}
}Παράδειγμα σφάλματος (μορφή πεδίων: "order_number": "WEB 1", "phone": "12-34").
json
{
"message": "The given data was invalid.",
"code": "validation_failed",
"errors": {
"order_number": [
"The order number field format is invalid."
],
"recipient.phone": [
"The recipient.phone field format is invalid."
]
}
}Παράδειγμα σφάλματος (κανόνες μεταξύ πεδίων).
Courier ELTA με "locker_id": "L1", "payment_method": "stripe" με "cod_cost": "2.00" και "country": "GR" με "postal_code": "5462":
json
{
"message": "The given data was invalid.",
"code": "validation_failed",
"errors": {
"locker_id": [
"The locker_id field is only allowed for Box Now shipments."
],
"cod_cost": [
"The cod_cost field is only allowed when payment_method is cod."
],
"recipient.postal_code": [
"A Greek postal code has 5 digits."
]
}
}Άλλα μηνύματα του ίδιου σταδίου:
| Πεδίο | Μήνυμα | Πότε |
|---|---|---|
courier_id | The courier_id field is required unless receive_from_reception is true. | Λείπει το courier_id (ή είναι null) χωρίς receive_from_reception: true. |
courier_id | The courier_id must be one of your connected couriers (GET /api/v2/couriers). | Η courier δεν είναι συνδεδεμένη στον λογαριασμό σας. |
locker_id | The locker_id field is required for Box Now shipments. | Courier Box Now χωρίς locker_id. |
services | Services are not available for store pickup or Box Now orders. | services με Box Now ή με receive_from_reception: true. |
recipient.postal_code | A Cyprus postal code has 4 digits. | CY χωρίς 4 ψηφία. |
recipient.postal_code | The postal code may only contain letters, digits, spaces and dashes. | Άλλη χώρα, μη έγκυρος κώδικας. |
Παράδειγμα κλήσης
bash
curl -X POST https://courierhub.gr/api/v2/orders \
-H "Authorization: Bearer chub_YOUR_API_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"order_number": "#1001",
"recipient": {
"name": "Μαρία Παπαδοπούλου",
"phone": "6941234567",
"email": "maria@example.com",
"address": "Ερμού 25",
"city": "Αθήνα",
"postal_code": "10563",
"country": "GR"
},
"courier_id": 8,
"payment_method": "cod",
"shipping_cost": "3.50",
"cod_cost": "1.50",
"products": [
{ "name": "Κούπα κεραμική", "sku": "MUG-01", "unit_price": "12.90", "quantity": 2 }
]
}'Μετά τη δημιουργία
- Το voucher εκδίδεται με POST /shipments, με
order_idτοidτης παραγγελίας από την απάντηση (όχι τοorder_idή τοorder_numberτης), ή από το περιβάλλον πελάτη του CourierHub, όπως για κάθε παραγγελία. Η έκδοση δεν ενημερώνει κανένα e-shop. Ακύρωση με DELETE /shipments/{voucher}. - Μόλις εκδοθεί voucher, η παραγγελία εμφανίζεται με
has_shipment: true, το voucher στοshipmentsτου GET /orders/{id} και στο GET /shipments, και webhooksshipment.*στέλνονται κανονικά. - Από εκείνη τη στιγμή η παραγγελία δεν αλλάζει ούτε διαγράφεται από το API (
409 order_has_shipment).