Αναφορά

REST API παράδοσης

Δύο διαδρομές μόνο για ανάγνωση εξυπηρετούν κάθε συλλογή του χώρου εργασίας σας. Ο ιστότοπός σας τις καλεί με ένα κλειδί API· οι συντάκτες δεν χρειάζεται καν να γνωρίζουν ότι υπάρχουν.

Τελικά σημεία#

Η βασική διεύθυνση URL είναι https://api.console.citronos.com. Το {collection} είναι το slug της συλλογής, δηλαδή το όνομά της στο API μέσα στην κονσόλα. Η μετονομασία του slug αλλάζει τη διαδρομή, γι’ αυτό η κονσόλα σάς προειδοποιεί πριν το επιτρέψει.

GET/v1/content/{collection}

Οι δημοσιευμένες εγγραφές μιας συλλογής, μία σελίδα κάθε φορά. Για μια συλλογή μοναδικού εγγράφου επιστρέφει το ίδιο το έγγραφο.

GET/v1/content/{collection}/{slugOrId}

Μία δημοσιευμένη εγγραφή, βάσει slug ή αναγνωριστικού.

Έλεγχος ταυτότητας#

Στείλτε ένα κλειδί παράδοσης στο Authorization: Bearer … ή στο x-api-key. Δημιουργήστε κλειδιά στην κονσόλα, στις Ρυθμίσεις → Προγραμματιστές → Κλειδιά API. Το πλήρες κλειδί εμφανίζεται μία μόνο φορά· το Citron κρατά μόνο το hash του.

ΚλειδίΔιαβάζειΠού χρησιμοποιείται
ck_pub_…Δημοσιευμένο περιεχόμενοΣε διακομιστή, στο edge ή κατά το build. Με όριο αιτημάτων ανά κλειδί.
ck_prev_…Δημοσιευμένο περιεχόμενο και πρόχειρα (status=draft)Μόνο σε διακομιστή που ελέγχετε. Μην το στέλνετε ποτέ σε πρόγραμμα περιήγησης.

Ένα κλειδί που λείπει, είναι άγνωστο ή έχει ανακληθεί λαμβάνει απάντηση 401.

curl
# Either header works
curl https://api.console.citronos.com/v1/content/products \
  -H "Authorization: Bearer $CITRON_API_KEY"

curl https://api.console.citronos.com/v1/content/products \
  -H "x-api-key: $CITRON_API_KEY"

Λίστα εγγραφών#

curl "https://api.console.citronos.com/v1/content/products?locale=bg&populate=related&richtext=html" \
  -H "Authorization: Bearer $CITRON_API_KEY"
Απάντηση
{
  "data": [
    {
      "id": "cmf3k9x2p0004s601q8w7e2rt",
      "slug": "bio-6",
      "publishedAt": "2026-09-21T09:30:00.000Z",
      "updatedAt": "2026-09-21T09:30:00.000Z",
      "sortOrder": 0,
      "data": {
        "code": "BIO-6",
        "category": "station",
        "inCapacityTable": true,
        "name": "Пречиствателна станция BIO 6",
        "body": "<p>Компактна станция за една къща.</p>",
        "capacity": 6,
        "specRows": [{ "label": "Капацитет", "value": "6 ЕЖ" }],
        "cover": {
          "id": "cmf3k7a1b0001s601m2n3b4v5",
          "url": "https://cdn.example.com/media/bio-6.webp",
          "mimeType": "image/webp",
          "width": 1600,
          "height": 900,
          "alt": "Станция BIO 6",
          "variants": { "thumb": "https://cdn.example.com/media/bio-6-thumb.webp" },
          "focal": { "x": 0.5, "y": 0.4 }
        },
        "related": [
          {
            "id": "cmf3k9x2p0007s601z5x4c3v2",
            "slug": "bio-10",
            "publishedAt": "2026-09-18T12:00:00.000Z",
            "updatedAt": "2026-09-18T12:00:00.000Z",
            "sortOrder": 1,
            "collection": "products",
            "data": {
              "code": "BIO-10",
              "name": "Пречиствателна станция BIO 10",
              "capacity": 10,
              "related": ["cmf3k9x2p0004s601q8w7e2rt"]
            }
          }
        ]
      }
    }
  ],
  "meta": { "total": 2, "page": 1, "pageSize": 20, "pageCount": 1 }
}

Κάθε εγγραφή έχει id, slug, publishedAt, updatedAt, sortOrder και data, που περιέχει τα πεδία της συλλογής. Το meta περιέχει total, page, pageSize και pageCount. Χωρίς sort ισχύει η σειρά που έχει οριστεί για τη συλλογή στην κονσόλα.

  • Τα πεδία εικόνας και πολυμέσων επιστρέφονται ως αρχεία πολυμέσων: id, url, mimeType, width, height, alt και variants (ονομασμένες εκδοχές, όπως thumb). Τα πεδία εικόνας προσθέτουν το focal, την υπόδειξη περικοπής του συντάκτη από 0 έως 1.
  • Ένα πεδίο συσχέτισης περιέχει το αναγνωριστικό της συσχετισμένης εγγραφής. Αν το δηλώσετε στο populate, περιέχει αντί γι’ αυτό την ίδια την εγγραφή, μαζί με το slug της collection. Οι εγγραφές που φορτώνονται έτσι είναι ρηχές (οι δικές τους συσχετίσεις μένουν αναγνωριστικά) και είναι πάντα οι δημοσιευμένες εκδόσεις.
  • Οι ζωντανές συλλογές που διαβάζουν από εξωτερικό σύστημα είναι διαθέσιμες μόνο στην κονσόλα· το API παράδοσης απαντά σε αυτές με 404.

Ανάκτηση μίας εγγραφής#

curl "https://api.console.citronos.com/v1/content/products/bio-6?locale=en&richtext=json" \
  -H "Authorization: Bearer $CITRON_API_KEY"
Απάντηση
{
  "data": {
    "id": "cmf3k9x2p0004s601q8w7e2rt",
    "slug": "bio-6",
    "publishedAt": "2026-09-21T09:30:00.000Z",
    "updatedAt": "2026-09-21T09:30:00.000Z",
    "sortOrder": 0,
    "data": {
      "code": "BIO-6",
      "category": "station",
      "name": "Treatment plant BIO 6",
      "body": {
        "type": "doc",
        "content": [{ "type": "paragraph", "content": [{ "type": "text", "text": "A compact plant for one house." }] }]
      },
      "capacity": 6,
      "datasheet": {
        "id": "cmf3k7a1b0002s601p9o8i7u6",
        "url": "https://cdn.example.com/media/bio-6.pdf",
        "mimeType": "application/pdf",
        "width": 0,
        "height": 0,
        "alt": "Datasheet",
        "variants": {}
      },
      "related": ["cmf3k9x2p0007s601z5x4c3v2"]
    }
  }
}

Το τελευταίο τμήμα της διαδρομής αντιστοιχίζεται με το slug ή με το αναγνωριστικό. Μια εγγραφή που δεν υπάρχει ή δεν έχει δημοσιευτεί ποτέ λαμβάνει απάντηση 404.

Συλλογές μοναδικού εγγράφου#

Μια συλλογή μοναδικού εγγράφου περιέχει ένα μόνο έγγραφο, όπως τις ρυθμίσεις του ιστοτόπου ή την αρχική σελίδα. Η διεύθυνση λίστας της απαντά με { "data": { … } }, δηλαδή με το έγγραφο αντί για λίστα, και με 404 μέχρι να δημοσιευτεί το έγγραφο.

curl "https://api.console.citronos.com/v1/content/site-settings?locale=bg" \
  -H "Authorization: Bearer $CITRON_API_KEY"

Παράμετροι ερωτήματος#

ΠαράμετροςΤιμέςΣημειώσεις
localeΜια γλώσσα του χώρου εργασίας, π.χ. bgΤα μεταφρασμένα πεδία επιστρέφονται μόνο σε αυτή τη γλώσσα. Μια άγνωστη γλώσσα λαμβάνει απάντηση 400.
filter[field], filter[field][op]Δείτε τα φίλτραΈως 10.
sortfield ή -fieldΈνα πεδίο. publishedAt, createdAt, updatedAt, sortOrder, slug ή οποιοδήποτε πεδίο δεν είναι αντικείμενο ή λίστα.
page1, 2, …Προεπιλογή 1.
pageSizeΑπό 1 έως 100Προεπιλογή: το μέγεθος λίστας που έχει οριστεί για τη συλλογή.
populateΚλειδιά πεδίων συσχέτισης, χωρισμένα με κόμμαΈως 10 πεδία συσχέτισης πρώτου επιπέδου.
fieldsΚλειδιά του data, χωρισμένα με κόμμαΤα id, slug, publishedAt, updatedAt και sortOrder επιστρέφονται πάντα.
richtexthtml, json, bothΠροεπιλογή both.
statusdraftΜόνο με κλειδί ck_prev_· διαφορετικά 403.
previewΈνα διακριτικό προεπισκόπησηςΊδιο με την κεφαλίδα x-citron-preview· δείτε την προεπισκόπηση προχείρων.

Γλώσσες και μορφοποιημένο κείμενο#

Χωρίς locale, κάθε μεταφρασμένο πεδίο είναι ένας χάρτης με όλες τις γλώσσες σας και το μορφοποιημένο κείμενο έρχεται και στις δύο μορφές. Με locale=bg λαμβάνετε τη βουλγαρική τιμή· όπου αυτή είναι κενή, την τιμή της προεπιλεγμένης γλώσσας.

Απάντηση χωρίς locale (συντομευμένη)
{
  "data": [
    {
      "id": "cmf3k9x2p0004s601q8w7e2rt",
      "slug": "bio-6",
      "publishedAt": "2026-09-21T09:30:00.000Z",
      "updatedAt": "2026-09-21T09:30:00.000Z",
      "sortOrder": 0,
      "data": {
        "code": "BIO-6",
        "name": { "bg": "Пречиствателна станция BIO 6", "en": "Treatment plant BIO 6" },
        "body": {
          "bg": { "html": "<p>Компактна станция.</p>", "json": { "type": "doc", "content": [] } },
          "en": { "html": "<p>A compact plant.</p>", "json": { "type": "doc", "content": [] } }
        }
      }
    }
  ],
  "meta": { "total": 2, "page": 1, "pageSize": 20, "pageCount": 1 }
}

Το richtext=html επιστρέφει το μορφοποιημένο κείμενο ως συμβολοσειρά HTML, το richtext=json ως έγγραφο του επεξεργαστή (ProseMirror JSON) και το both, η προεπιλογή, ως { "html", "json" }. Παλαιότερες εγγραφές ενδέχεται να περιέχουν απλή συμβολοσειρά HTML, ό,τι κι αν ζητήσετε.

Φίλτρα#

Το filter[field]=value σημαίνει «ισούται με»· το filter[field][op]=value επιλέγει τελεστή. Μπορείτε να φιλτράρετε με βάση το id, το slug και οποιοδήποτε πεδίο εκτός από πεδία αντικειμένου, γεωγραφικά πεδία και πεδία JSON. Τα φίλτρα συνδυάζονται με λογικό ΚΑΙ. Ένα άγνωστο πεδίο ή ένας τελεστής που δεν υποστηρίζει ο τύπος του πεδίου λαμβάνει απάντηση 400.

Τύπος πεδίουΤελεστέςΣημειώσεις
Κείμενο, επιλογή, ημερομηνία, slug, μορφοποιημένο κείμενο, πολυμέσα, συσχέτισηeq ne lt lte gt gte contains in notInΤο contains αναζητά υποσυμβολοσειρά χωρίς διάκριση πεζών-κεφαλαίων. Τα in και notIn δέχονται τιμές χωρισμένες με κόμμα. Η σύγκριση είναι κειμενική, οπότε οι ημερομηνίες ISO ταξινομούνται σωστά.
Αριθμόςeq ne lt lte gt gte in notInΟι τιμές πρέπει να είναι αριθμοί.
Λογική τιμήeq netrue ή false.
Πολλαπλή επιλογή, πολλαπλή συσχέτιση, λίσταeq containsΚαι οι δύο εντοπίζουν τις εγγραφές των οποίων η λίστα περιέχει την τιμή.

Ένα μεταφρασμένο πεδίο συγκρίνεται στη γλώσσα που ζητήθηκε με locale ή, αν δεν δοθεί, στην προεπιλεγμένη γλώσσα. Εδώ δεν υπάρχει εναλλακτική γλώσσα: μια εγγραφή χωρίς τιμή σε αυτή τη γλώσσα δεν ταιριάζει.

# -g stops curl from treating [ ] as a glob
curl -g "https://api.console.citronos.com/v1/content/products?locale=en\
&filter[category]=station\
&filter[capacity][gte]=5\
&filter[code][in]=BIO-6,BIO-10\
&sort=-publishedAt&page=1&pageSize=20" \
  -H "Authorization: Bearer $CITRON_API_KEY"

Το curl ερμηνεύει τα [ και ] ως μοτίβο glob. Χρησιμοποιήστε το -g ή κωδικοποιήστε τα ως %5B και %5D.

Σελιδοποίηση#

Οι σελίδες αριθμούνται από το 1 και περιέχουν έως 100 εγγραφές. Σταματήστε όταν το page φτάσει το meta.pageCount. Το SDK προσθέτει έναν αδιαφανή nextCursor και έναν επαναλήπτη all() πάνω στους ίδιους αριθμούς σελίδων.

TypeScript SDK
import type { ListResult } from '@citron/sdk';

// Page by page with the opaque cursor
let cursor: string | null = null;
do {
  const page: ListResult<Record<string, unknown>> = await citron.collection('products').list({ limit: 100, cursor });
  console.log(page.data.length);
  cursor = page.nextCursor;
} while (cursor);

// Or let the SDK walk every page
for await (const product of citron.collection('products').all({ fields: ['code', 'name'] })) {
  console.log(product.slug);
}

Επιλογή πεδίων#

Το fields κρατά μόνο τα κλειδιά του data που απαριθμείτε, κάνοντας τις σελίδες λίστας μικρότερες. Συνδυάζεται με τα populate και locale.

curl
# Only these data keys (id, slug, publishedAt, updatedAt, sortOrder always come)
curl "https://api.console.citronos.com/v1/content/products?locale=en&fields=code,name,cover" \
  -H "Authorization: Bearer $CITRON_API_KEY"

Προσωρινή αποθήκευση και ETag#

Οι δημοσιευμένες απαντήσεις φέρουν Cache-Control: public, max-age=60, stale-while-revalidate=300 και ένα ETag. Στείλτε το ETag πίσω στο If-None-Match και μια αμετάβλητη απάντηση θα είναι ένα κενό 304. Οι απαντήσεις με πρόχειρα και προεπισκοπήσεις είναι no-store. Για να εμφανίζονται οι αλλαγές τη στιγμή που ένας συντάκτης δημοσιεύει, κρατήστε την προσωρινή αποθήκευση περισσότερο στη δική σας πλευρά και κάντε επανεπικύρωση με webhooks.

curl
curl -i "https://api.console.citronos.com/v1/content/products?locale=en" \
  -H "Authorization: Bearer $CITRON_API_KEY" \
  -H 'If-None-Match: "3f1c9e0a8b7d6c5e4f3a2b1c0d9e8f7a6b5c4d3e"'
# HTTP/1.1 304 Not Modified   (when nothing changed)

Προεπισκόπηση προχείρων#

Ορίστε στην κονσόλα μια διεύθυνση URL προεπισκόπησης για τη συλλογή, με οποιοδήποτε από τα σύμβολα κράτησης θέσης {slug}, {id}, {locale}, {token} και {collection}, για παράδειγμα https://example.com/{locale}/products/{slug}?preview={token}. Η επιλογή Άνοιγμα προεπισκόπησης σε μια εγγραφή ανοίγει αυτή τη διεύθυνση με ένα υπογεγραμμένο διακριτικό (cpt1.…). Αν το πρότυπο δεν περιέχει {token}, το διακριτικό προστίθεται ως ?preview=.

Η σελίδα σας επιστρέφει το διακριτικό στην κεφαλίδα x-citron-preview (ή στο ?preview=) μαζί με το συνηθισμένο κλειδί ck_pub_. Τότε το API επιστρέφει τα πρόχειρα μόνο αυτής της συλλογής, χωρίς προσωρινή αποθήκευση. Τα διακριτικά λήγουν από προεπιλογή μετά από 30 λεπτά (το πολύ 24 ώρες) και λειτουργούν μόνο για τον χώρο εργασίας σας και για τη συλλογή για την οποία εκδόθηκαν.

Κεφαλίδα απάντησης X-Citron-PreviewΣημασία
draftΤο διακριτικό είναι έγκυρο· επιστράφηκαν τα πρόχειρα.
invalidΤο διακριτικό είναι κακοσχηματισμένο, έχει λήξει ή ανήκει σε άλλο χώρο εργασίας· επιστράφηκε το δημοσιευμένο περιεχόμενο.
other-collectionΤο διακριτικό εκδόθηκε για άλλη συλλογή· επιστράφηκε το δημοσιευμένο περιεχόμενο.

Ένα λανθασμένο διακριτικό δεν προκαλεί ποτέ σφάλμα: η απάντηση είναι ακριβώς η δημοσιευμένη, οπότε ένας παλιός σύνδεσμος προεπισκόπησης απλώς δείχνει τη ζωντανή σελίδα.

# The token arrives in your preview URL: https://example.com/products/bio-6?preview=cpt1.…
curl -i "https://api.console.citronos.com/v1/content/products/bio-6?locale=en" \
  -H "Authorization: Bearer $CITRON_API_KEY" \
  -H "x-citron-preview: cpt1.eyJvIjoi….k1Qm…"
# X-Citron-Preview: draft
# Cache-Control: no-store

Κλειδιά προεπισκόπησης#

Ένα κλειδί ck_prev_ με status=draft (στο SDK, preview: true) διαβάζει τα πρόχειρα όλων των συλλογών. Χρησιμοποιήστε το για προεπισκοπήσεις κατά το build σε διακομιστή που ελέγχετε, ποτέ σε πρόγραμμα περιήγησης.

TypeScript SDK
import { createClient } from '@citron/sdk';

// Server only: a ck_prev_ key reads every draft of the workspace
const drafts = createClient({
  baseUrl: 'https://api.console.citronos.com',
  apiKey: process.env.CITRON_PREVIEW_KEY, // ck_prev_…
  preview: true, // sends status=draft
});

const draft = await drafts.collection('products').find('bio-6');
console.log(draft?.updatedAt);

Όρια#

Από προεπιλογή, κάθε κλειδί μπορεί να κάνει 300 αιτήματα ανά λεπτό· τα REST και GraphQL μοιράζονται αυτό το όριο. Δείτε τα σφάλματα και όρια ρυθμού για να δείτε πώς μοιάζει μια απάντηση 429.

Αυτή η αναφορά καλύπτει μόνο το δημόσιο API και ακολουθεί τη σύμβαση συμβατότητας του API: οι δημόσιες αποκρίσεις μόνο αποκτούν νέα πεδία. Η περιγραφή OpenAPI αυτών των διαδρομών βρίσκεται στο /developers/openapi.json.