Μετάβαση στο κύριο περιεχόμενο

Coupons API

Ένα πρόγραμμα κουπονιών είναι η συνταγή από την οποία ένα μήνυμα εκδίδει προσωπικούς κωδικούς ({{ coupons.<slug>.code }}). Το Joryio δημιουργεί κάθε κωδικό στο συνδεδεμένο κατάστημα WooCommerce, Shopify, Magento ή PrestaShop (ή τον δημιουργεί και τον παρακολουθεί μόνο του όταν το πρόγραμμα δεν έχει κατάστημα) και αναγνωρίζει την παραγγελία που τον χρησιμοποίησε. Η συμπεριφορά των προγραμμάτων περιγράφεται στο Κωδικοί κουπονιών.

Όλα τα endpoints αυτής της σελίδας είναι σχετικά με το βασικό URL: https://api-eu1.joryio.com/api - δείτε Επισκόπηση API.

Δικαιώματα​

ΔικαίωμαΕπιτρέπει
campaigns:readΛίστα και ανάγνωση προγραμμάτων, της αναφοράς και των συνδεδεμένων καταστημάτων
campaigns:writeΔημιουργία προγραμμάτων, αλλαγή προγραμμάτων που δεν έχουν εκδώσει ακόμη κωδικούς, διαγραφή τους, έκδοση κωδικού
settings:writeΧρειάζεται επιπλέον για αλλαγή ενός ζωντανού προγράμματος - ενός που έχει εκδώσει πραγματικούς κωδικούς
users:readΛίστα εκδοθέντων κωδικών (οι κωδικοί ανήκουν σε άτομα)

Το αντικείμενο προγράμματος​

{
"id": "6c0f3c1e-8a52-4a8e-9a39-2a1d7f0b9a11",
"name": "Welcome 10%",
"slug": "welcome10",
"description": "10% off the first order",
"integrationId": "0b8d6f2a-5f43-4e0a-b9a3-7a8b2d1c4e55",
"platform": "woocommerce",
"storeName": "My Store",
"source": "personal",
"status": "active",
"rules": {
"discountType": "percent",
"amount": 10,
"currency": null,
"minimumSubtotal": 50,
"minimumQuantity": null,
"scope": { "kind": "all" },
"excludeSaleItems": false,
"usageLimit": 1,
"oncePerCustomer": true,
"combinable": false,
"expiry": { "mode": "relative", "amount": 14, "unit": "days", "endOfDay": true }
},
"rulesVersion": 1,
"codeFormat": { "length": 10, "charset": "unambiguous", "prefix": "WELCOME-", "suffix": "", "separatorEvery": null },
"fallback": { "policy": "skip", "sharedCode": null },
"reuseOpenCode": true,
"lockToPerson": false,
"live": true,
"sampleCode": "WELCOME-PREVIEW",
"storeError": null,
"stats": { "issued": 1240, "redeemed": 311, "revenue": 18420.5, "currency": "EUR" },
"createdAt": "2026-10-04T08:00:00.000Z",
"updatedAt": "2026-10-04T08:00:00.000Z"
}
ΠεδίοΤιμές
integrationIdΈνα συνδεδεμένο κατάστημα, ή null: το Joryio δημιουργεί και παρακολουθεί τους κωδικούς χωρίς κατάστημα
statusdraft, active, paused, archived - μόνο το active εκδίδει κωδικούς
rules.discountTypepercent, fixed_cart, fixed_product (όχι στο PrestaShop: 400), free_shipping
rules.scope{ "kind": "all" }, ή products (WooCommerce, Shopify, PrestaShop) / categories (WooCommerce, Magento, PrestaShop) / collections (Shopify) με ids - τα ids του ίδιου του καταστήματος· το products στο Magento απαντά 400
rules.minimumQuantityΜόνο Shopify
rules.excludeSaleItemsΜόνο WooCommerce
rules.usageLimitΧρήσεις ανά κωδικό, προεπιλογή 1· null = απεριόριστες
rules.expiry{ "mode": "none" }, { "mode": "fixed", "date": "2026-12-31T23:59:59Z" }, ή { "mode": "relative", "amount": 14, "unit": "days" | "hours", "endOfDay": true }
codeFormat.charsetunambiguous (γράμματα και ψηφία χωρίς όμοιους χαρακτήρες, προεπιλογή), letters, digits· length 6-20
fallback.policyskip (προεπιλογή), shared_code (χρειάζεται sharedCode), send_without
lockToPersonWooCommerce, Magento και PrestaShop (ο λογαριασμός πελάτη του ατόμου)
livetrue μόλις το πρόγραμμα εκδώσει πραγματικό (όχι δοκιμαστικό) κωδικό
rulesVersionΑυξάνεται όταν αλλάζουν οι κανόνες ενός ζωντανού προγράμματος· οι κωδικοί που έχουν ήδη εκδοθεί κρατούν τους κανόνες με τους οποίους δημιουργήθηκαν

Προγράμματα​

Λίστα προγραμμάτων​

GET /coupons/programs?status=active&includeArchived=false

Επιστρέφει πίνακα αντικειμένων προγράμματος. Τα αρχειοθετημένα προγράμματα παραλείπονται, εκτός αν includeArchived=true.

Δημιουργία προγράμματος​

POST /coupons/programs

Το σώμα είναι το αντικείμενο προγράμματος χωρίς τα πεδία μόνο ανάγνωσης (id, platform, storeName, rulesVersion, stock, live, sampleCode, storeError, stats, ημερομηνίες). Το slug είναι [a-z0-9_], μοναδικό ανά χώρο εργασίας. Το status μπορεί να είναι draft (προεπιλογή) ή active.

{
"name": "Welcome 10%",
"slug": "welcome10",
"integrationId": "0b8d6f2a-5f43-4e0a-b9a3-7a8b2d1c4e55",
"rules": { "discountType": "percent", "amount": 10, "scope": { "kind": "all" }, "usageLimit": 1, "oncePerCustomer": true, "combinable": false, "expiry": { "mode": "relative", "amount": 14, "unit": "days" } },
"codeFormat": { "length": 10, "charset": "unambiguous", "prefix": "WELCOME-" },
"fallback": { "policy": "skip" },
"reuseOpenCode": true,
"lockToPerson": false
}

Ανάγνωση προγράμματος​

GET /coupons/programs/{id}

Ενημέρωση προγράμματος​

PATCH /coupons/programs/{id}

Οποιοδήποτε πεδίο του σώματος δημιουργίας, ή status (draft, active, paused, archived). Η αλλαγή ζωντανού προγράμματος χρειάζεται settings:write εκτός από campaigns:write.

Διαγραφή προγράμματος​

DELETE /coupons/programs/{id}

204 για πρόγραμμα που δεν εξέδωσε ποτέ πραγματικό κωδικό. Ένα ζωντανό πρόγραμμα απαντά 409 - αρχειοθετήστε το αντί γι' αυτό (PATCH με "status": "archived").

Αναφορά προγράμματος​

GET /coupons/programs/{id}/report
{
"programId": "6c0f3c1e-8a52-4a8e-9a39-2a1d7f0b9a11",
"totals": { "issued": 1240, "redeemed": 311, "redemptionRate": 0.2508, "revenue": 18420.5, "discount": 1842.05, "currency": "EUR", "expired": 402, "failed": 3, "redeemedBySomeoneElse": 12 },
"bySource": [
{ "kind": "journey", "id": "a1b2c3d4-0000-4000-8000-000000000001", "name": "Welcome journey", "issued": 980, "redeemed": 270, "revenue": 15900 }
],
"daily": [{ "date": "2026-10-04", "issued": 52, "redeemed": 14 }]
}

Τα έσοδα και η έκπτωση είναι και τα δύο στο νόμισμα αναφορών του χώρου εργασίας (currency): μια παραγγελία σε άλλο νόμισμα μετατρέπεται με τη δική της ισοτιμία, την ίδια με την οποία μετατράπηκαν τα έσοδά της. Οι δοκιμαστικοί κωδικοί δεν μετρούν.

Έκδοση κωδικού​

POST /coupons/programs/{id}/issue

Δίνει έναν κωδικό από ενεργό πρόγραμμα σε μία επαφή - για συνεργάτες που δείχνουν τον κωδικό στο δικό τους κανάλι. Προσδιορίστε την επαφή με ένα από:

ΠεδίοΠεριγραφή
contactIdΤο εσωτερικό id επαφής του Joryio
externalIdΤο δικό σας id χρήστη
emailΤο email της επαφής
issueKeyΠροαιρετικό κλειδί idempotency: το ίδιο issueKey επιστρέφει πάντα τον ίδιο κωδικό
{ "externalId": "customer-123", "issueKey": "order-confirmation-9876" }

Απόκριση:

{
"issued": true,
"reused": false,
"applyUrl": "https://shop.example.com/?jry_coupon=WELCOME-7KQ4M2XH9P",
"issue": {
"id": "1f6a...", "programId": "6c0f...", "programSlug": "welcome10", "programName": "Welcome 10%",
"contactId": "66a1f2c3d4e5f6a7b8c9d0e1", "code": "WELCOME-7KQ4M2XH9P", "status": "issued", "isTest": false,
"sourceKind": "api", "campaignId": null, "canvasId": null, "nodeId": null, "channel": null,
"issuedAt": "2026-10-04T09:00:00.000Z", "expiresAt": "2026-10-18T23:59:59.000Z",
"redeemedAt": null, "redeemedOrderId": null, "redeemedRevenue": null, "failureReason": null
}
}

Με ενεργό το reuseOpenCode του προγράμματος, μια επαφή που έχει ακόμη ανοιχτό κωδικό από το πρόγραμμα παίρνει αυτόν τον κωδικό ("reused": true). Όταν δεν μπορεί να εκδοθεί κωδικός η απάντηση είναι { "issued": false, "reason": "..." } - για παράδειγμα program_paused, store_error, store_permission_missing (το κατάστημα Shopify δεν έχει εγκρίνει ακόμη το write_discounts), store_reconnect_required (το WooCommerce προστέθηκε στον ιστότοπο WordPress μετά τη σύνδεσή του - αποσυνδέστε και συνδέστε ξανά το πρόσθετο Joryio).

Εκδοθέντες κωδικοί​

GET /coupons/issues?contactId=66a1f2c3d4e5f6a7b8c9d0e1&programId=&status=&limit=50&offset=0

Επιστρέφει { "items": [issue, ...], "total": 3 }, από τον νεότερο. Το status είναι pending, issued, failed, redeemed, expired ή revoked. limit έως 200.

Συνδεδεμένα καταστήματα​

GET /coupons/stores
[
{
"integrationId": "0b8d6f2a-5f43-4e0a-b9a3-7a8b2d1c4e55",
"platform": "shopify",
"storeName": "My Shop",
"storeUrl": "https://my-shop.myshopify.com",
"status": "connected",
"capabilities": { "lockToPerson": false, "perCodeExpiry": false, "percentCap": false, "scopes": ["all", "products", "collections"] },
"missingPermission": "write_discounts"
}
]

Το missingPermission δηλώνει τι πρέπει να εγκρίνει ο έμπορος πριν δημιουργηθούν κωδικοί (Shopify: ανοίξτε Integrations → Shopify → Approve new permissions).

Πηγές κωδικών​

Το πεδίο source ενός προγράμματος λέει από πού προέρχονται οι κωδικοί του. Ορίζεται κατά τη δημιουργία (προεπιλογή personal) και δεν αλλάζει αφού το πρόγραμμα αποκτήσει κωδικούς. Δείτε Πηγές κωδικών.

sourceΚωδικοίsourceConfig
personalΈνας κωδικός ανά άτομο, που δημιουργείται όταν τον χρειάζεται ένα μήνυμα{}
bankΔημιουργούνται στο κατάστημα εκ των προτέρων και μοιράζονται ένας ανά άτομο. Χρειάζεται integrationId.{ "bankTargetSize": 5000 } - πόσοι αχρησιμοποίητοι κωδικοί μένουν έτοιμοι (0 = μόνο κατ' απαίτηση και πριν από καμπάνιες)
uploadedΤους ανεβάζετε εσείς (Ανέβασμα κωδικών) και μοιράζονται ένας ανά άτομο· δεν δημιουργούνται ποτέ σε κατάστημα. integrationId προαιρετικό· lockToPerson δεν επιτρέπεται.{}
sharedΈνας κωδικός για όλους, καταγεγραμμένος ανά έκδοση{ "sharedCode": "SUMMER10", "createInStore": true } - το createInStore χρειάζεται integrationId· το false απλώς καταχωρίζει κωδικό που υπάρχει ήδη

Τα προγράμματα έχουν επίσης:

ΠεδίοΤιμές
lowStock{ "threshold": 500, "percent": null } - για bank και uploaded: ειδοποίηση όταν απομένουν λιγότεροι από threshold αχρησιμοποίητοι κωδικοί, ή λιγότερο από percent (1-99) % όλων των κωδικών που φορτώθηκαν. Το null απενεργοποιεί έναν κανόνα.
stockΜόνο για ανάγνωση. { "available": 1830, "total": 5000, "level": "ok" } για bank και uploaded (level: ok, low, empty)· null για τις άλλες πηγές.

Σε πρόγραμμα uploaded, και σε shared με createInStore: false, τα rules περιγράφουν μόνο την αξία που δείχνει το {{ coupons.<slug>.value }} - το κατάστημα δεν τα βλέπει ποτέ.

{
"name": "Partner coffee voucher",
"slug": "coffee",
"source": "uploaded",
"integrationId": null,
"lowStock": { "threshold": 200 },
"rules": { "discountType": "fixed_cart", "amount": 3, "currency": "EUR", "scope": { "kind": "all" }, "usageLimit": 1, "oncePerCustomer": true, "combinable": false, "expiry": { "mode": "none" } },
"fallback": { "policy": "send_without" }
}

Απόθεμα​

GET /coupons/programs/{id}/stock
{
"programId": "6c0f3c1e-8a52-4a8e-9a39-2a1d7f0b9a11",
"source": "bank",
"tracked": true,
"available": 1830,
"total": 5000,
"used": 3170,
"level": "ok",
"lowStock": { "threshold": 500, "percent": null },
"bank": { "targetSize": 5000, "filling": false, "lastRunAt": "2026-10-04T09:15:00.000Z", "lastAdded": 250, "lastError": null }
}

Το tracked είναι false (και οι μετρήσεις 0) για προγράμματα personal και shared. Το bank υπάρχει μόνο στις τράπεζες κωδικών· το filling είναι true όσο εκτελείται συμπλήρωση.

Ανέβασμα κωδικών​

POST /coupons/programs/{id}/codes
POST /coupons/programs/{id}/codes?dryRun=true

Προσθέτει κωδικούς σε πρόγραμμα uploaded. Στείλτε είτε αρχείο CSV ως multipart/form-data (πεδίο file) είτε JSON { "text": "...", "fileName": "optional.csv" } με τους κωδικούς επικολλημένους. Κάθε ανέβασμα προστίθεται· οι προηγούμενοι κωδικοί μένουν. Το dryRun=true ελέγχει και επιστρέφει την ίδια αναφορά χωρίς να αποθηκεύσει τίποτα - η προεπισκόπηση.

{ "text": "code,expires_at,value\nCOFFEE-001,2026-12-31,Free coffee\nCOFFEE-002,,Free coffee" }
ΣτήληΥποχρεωτικήΜορφή
codeΝαι3-64 χαρακτήρες: γράμματα, ψηφία και - _ . # / +· συγκρίνονται χωρίς διάκριση πεζών-κεφαλαίων
expires_atΌχιYYYY-MM-DD (το τέλος εκείνης της ημέρας, UTC) ή ημερομηνία-ώρα ISO· πρέπει να είναι στο μέλλον
valueΌχιΈως 100 χαρακτήρες· εμφανίζεται ως {{ coupons.<slug>.value }} για αυτόν τον κωδικό

Η γραμμή επικεφαλίδας είναι προαιρετική (χωρίς αυτήν οι στήλες διαβάζονται με αυτή τη σειρά)· τα διαχωριστικά κόμμα, ερωτηματικό και tab αναγνωρίζονται από την πρώτη γραμμή. Όρια: 100.000 γραμμές και 10 MB ανά ανέβασμα, 2.000.000 κωδικοί ανά πρόγραμμα.

Απάντηση (CouponUploadReport):

{
"uploadId": "9d2e4b10-1c3f-4b7a-8a55-0e6f2c9d1a77",
"dryRun": false,
"totalRows": 3,
"accepted": 2,
"rejected": 1,
"duplicates": 1,
"truncated": false,
"maxRows": 100000,
"hasHeader": true,
"preview": [{ "line": 2, "code": "COFFEE-001", "expiresAt": "2026-12-31T23:59:59.000Z", "value": "Free coffee" }],
"rejectedRows": [{ "line": 4, "code": "COFFEE-001", "reason": "duplicate_in_file", "message": "The same code appears earlier in this file." }]
}

Το uploadId είναι null σε δοκιμαστική εκτέλεση (dry run). Το preview περιέχει τις πρώτες 10 αποδεκτές γραμμές και το rejectedRows τις πρώτες 500 που απορρίφθηκαν. Το truncated είναι true όταν το αρχείο είχε περισσότερες γραμμές από maxRows (οι υπόλοιπες δεν διαβάστηκαν).

reasonΣημασία
missing_codeΗ γραμμή δεν έχει κωδικό
invalid_codeΔεν είναι 3-64 γράμματα, ψηφία και - _ . # / +
invalid_expiryΗ λήξη δεν είναι ημερομηνία
expiredΗ λήξη έχει περάσει
value_too_longΗ αξία ξεπερνά τους 100 χαρακτήρες
duplicate_in_fileΟ ίδιος κωδικός εμφανίζεται νωρίτερα στο αρχείο
already_in_programΤο πρόγραμμα έχει ήδη τον κωδικό
already_existsΆλλο πρόγραμμα του χώρου εργασίας έχει τον κωδικό
over_limitΤο πρόγραμμα είναι γεμάτο

Ένα πρόγραμμα με άλλη πηγή απαντά 400.

Προηγούμενα ανεβάσματα​

GET /coupons/programs/{id}/uploads

Τα τελευταία 100 ανεβάσματα, από το νεότερο: { "id", "kind", "fileName", "totalRows", "accepted", "rejected", "duplicates", "rejectedRows", "createdBy", "createdAt" }.

Δημιουργία κωδικών τράπεζας​

POST /coupons/programs/{id}/bank/generate
{ "count": 5000 }

Δημιουργεί count (1-100.000) νέους κωδικούς στο κατάστημα για πρόγραμμα bank. Η εργασία τρέχει στο παρασκήνιο: η απάντηση είναι αμέσως 202 Accepted με { "started": true, "requested": 5000 }· παρακολουθήστε τη με το Απόθεμα (bank.filling, bank.lastAdded, bank.lastError). Ένα δεύτερο αίτημα όσο εκτελείται συμπλήρωση απαντά 400. Το Shopify προσθέτει κωδικούς στην έκπτωση του προγράμματος, το WooCommerce δημιουργεί ένα κουπόνι ανά κωδικό το Magento τους παράγει κάτω από τον κανόνα τιμής καλαθιού του προγράμματος με τη μορφή κωδικού του και το PrestaShop δημιουργεί έναν κανόνα καλαθιού ανά κωδικό.

Πριν σταλεί μια καμπάνια, κάθε τράπεζα που χρησιμοποιεί το περιεχόμενό της συμπληρώνεται αυτόματα ώστε να καλύπτει το κοινό. Το Launch Review μπλοκάρει καμπάνια της οποίας το κοινό είναι μεγαλύτερο από τους κωδικούς μιας τράπεζας ή λίστας (coupon_stock_short) και προειδοποιεί όταν η αποστολή αφήνει λιγότερους κωδικούς από την ειδοποίηση χαμηλού αποθέματος (coupon_stock_low).

Σφάλματα​

ΚατάστασηΠότε
400Επικύρωση - για παράδειγμα lockToPerson σε πρόγραμμα Shopify (το Shopify ορίζει ποιος χρησιμοποιεί μια έκπτωση ανά έκπτωση, όχι ανά κωδικό), slug που υπάρχει ήδη ή δεν είναι [a-z0-9_], shared_code χωρίς sharedCode, ημερομηνία λήξης στο παρελθόν
403Λείπει δικαίωμα - μαζί με το settings:write στην αλλαγή ζωντανού προγράμματος
404Το πρόγραμμα δεν βρίσκεται σε αυτόν τον χώρο εργασίας
409Διαγραφή ζωντανού προγράμματος