API για προγραμματιστές
Ένα API μόνο για ανάγνωση προς τον βοηθό του δικού σας καταστήματος: απαντήσεις, προτάσεις κατά την πληκτρολόγηση, παρόμοια προϊόντα και κατάλογος, για τον διακομιστή, την εφαρμογή ή τη σελίδα σας.
Έκδοση API 1.0.0
Επισκόπηση#
Το API δίνει στον κώδικά σας ό,τι δίνει ο βοηθός του ιστότοπου στους αγοραστές: πλήρη απάντηση σε ερώτηση με απλά λόγια, προτάσεις προϊόντων κατά την πληκτρολόγηση, λίστες παρόμοιων προϊόντων και ανάγνωση του καταλόγου. Βασικό URL: https://assistant.onesite.agency/api/v1.
Είναι μόνο για ανάγνωση και περιορίζεται σε ένα κατάστημα: ένα κλειδί ανοίγει το κατάστημα που το δημιούργησε και τίποτε άλλο. Ονόματα, τιμές, διαθεσιμότητα και σύνδεσμοι προέρχονται πάντα από τον κατάλογο· η ΤΝ γράφει μόνο τα σύντομα κείμενα say και why, και η απάντηση τα επισημαίνει (δείτε «Κείμενο που παράγεται από ΤΝ» παρακάτω).
Τα αιτήματα και οι απαντήσεις είναι JSON μέσω HTTPS. Η έκδοση βρίσκεται στη διαδρομή (/v1). Το API διατίθεται στα πακέτα που περιλαμβάνουν το API για προγραμματιστές.
Γρήγορη εκκίνηση#
Από το μηδέν στην πρώτη απάντηση σε τρία βήματα.
1. Δημιουργήστε κλειδί#
Στο cabinet ανοίξτε την καρτέλα Developers, ονομάστε το κλειδί και επιλέξτε τα scopes του, προαιρετικά και λίστα IP και προελεύσεις προγράμματος περιήγησης. Το κλειδί εμφανίζεται μία φορά και κρατάμε μόνο ένα hash: αντιγράψτε το κατευθείαν στα μυστικά του διακομιστή σας, ποτέ σε αποθετήριο. Ένα χαμένο κλειδί δεν ανακτάται: ανακαλέστε το και δημιουργήστε άλλο.
2. Ελέγξτε το#
Καλέστε GET /me. Ένα 200 δείχνει ποιο κατάστημα ανοίγει το κλειδί, τα scopes και τα όριά του. Αντικαταστήστε το YOUR_API_KEY με το κλειδί σας.
Παράδειγμα αιτήματος, curl
curl 'https://assistant.onesite.agency/api/v1/me' \
-H 'Authorization: Bearer YOUR_API_KEY'Παράδειγμα αιτήματος, JavaScript (fetch)
const response = await fetch("https://assistant.onesite.agency/api/v1/me", {
method: "GET",
headers: {
"Authorization": "Bearer YOUR_API_KEY",
},
});
const data = await response.json();
console.log(response.status, data);Παράδειγμα αιτήματος, Python (requests)
import requests
response = requests.get(
"https://assistant.onesite.agency/api/v1/me",
headers={
"Authorization": "Bearer YOUR_API_KEY",
},
)
print(response.status_code, response.json())3. Κάντε μια ερώτηση#
Στείλτε τα λόγια του αγοραστή στο POST /answers (απαιτεί το scope answer). Παίρνετε την καλύτερη αντιστοιχία, εναλλακτικές και έναν λόγο μίας γραμμής για καθεμία.
Παράδειγμα αιτήματος, curl
curl -X POST 'https://assistant.onesite.agency/api/v1/answers' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: 3f9d1c52-7b0e-4a53-9a6f-0c2f8e1d77aa' \
-d '{
"query": "a cold, quiet science fiction novel for a long winter",
"language": "en",
"in_stock_only": true,
"session_id": "visitor-8841"
}'Παράδειγμα αιτήματος, JavaScript (fetch)
const response = await fetch("https://assistant.onesite.agency/api/v1/answers", {
method: "POST",
headers: {
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
"Idempotency-Key": "3f9d1c52-7b0e-4a53-9a6f-0c2f8e1d77aa",
},
body: JSON.stringify({
"query": "a cold, quiet science fiction novel for a long winter",
"language": "en",
"in_stock_only": true,
"session_id": "visitor-8841"
}),
});
const data = await response.json();
console.log(response.status, data);Παράδειγμα αιτήματος, Python (requests)
import requests
response = requests.post(
"https://assistant.onesite.agency/api/v1/answers",
headers={
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
"Idempotency-Key": "3f9d1c52-7b0e-4a53-9a6f-0c2f8e1d77aa",
},
json={
"query": "a cold, quiet science fiction novel for a long winter",
"language": "en",
"in_stock_only": True,
"session_id": "visitor-8841",
},
)
print(response.status_code, response.json())Πιστοποίηση#
Στείλτε το κλειδί στην κεφαλίδα Authorization ως bearer token. Ποτέ στο URL: τα URL καταλήγουν σε αρχεία καταγραφής και στο ιστορικό του προγράμματος περιήγησης.
Πιστοποίηση
Authorization: Bearer YOUR_API_KEYΈνα κλειδί που λείπει, είναι κακοσχηματισμένο, άγνωστο ή ανακλημένο δίνει πάντα το ίδιο 401 invalid_api_key, ώστε η απάντηση να μη λέει ποτέ σε όποιον μαντεύει ότι ένα κλειδί είναι σχεδόν σωστό. Τα επαναλαμβανόμενα άκυρα κλειδιά από μία διεύθυνση επιβραδύνονται με 429 too_many_failed_attempts.
Ένα κλειδί ανήκει σε ένα μόνο κατάστημα και δεν διαβάζει άλλο: το id προϊόντος άλλου καταστήματος απαντά 404, όπως ένα ανύπαρκτο.
Μπορείτε να περιορίσετε περαιτέρω ένα κλειδί με λίστα επιτρεπόμενων IP (403 ip_not_allowed) και λίστα προελεύσεων προγράμματος περιήγησης (403 origin_not_allowed). Τα scopes ορίζονται κατά τη δημιουργία· για να τα διευρύνετε, δημιουργήστε άλλο κλειδί.
Scopes και όρια#
Κάθε κλειδί φέρει τα scopes που μπορεί να χρησιμοποιήσει. Τα όρια ισχύουν ανά κλειδί και ανά scope.
| Scope | Endpoints | Κλήσεις ανά 60 s |
|---|---|---|
answer | POST /answers | 20 |
suggest | GET /suggestions | 120 |
catalogue:read | GET /products, GET /products/{product_id} | 120 |
similar | GET /products/{product_id}/similar | 60 |
analytics:read | GET /analytics/summary, GET /analytics/series, GET /analytics/queries, GET /analytics/sales | 30 |
Το POST /answers έχει επιπλέον ημερήσιο όριο 500 κλήσεων ανά κλειδί (ημέρα UTC), επειδή κάθε απάντηση είναι κλήση στο μοντέλο. Μια επανάληψη με το ίδιο Idempotency-Key δεν μετρά.
Κάθε απάντηση φέρει X-RateLimit-Limit, X-RateLimit-Remaining και X-RateLimit-Reset· ένα 429 προσθέτει Retry-After (δευτερόλεπτα). Περιμένετε τόσο αντί να επαναλαμβάνετε σε βρόχο. Το GET /me θέλει έγκυρο κλειδί αλλά κανένα συγκεκριμένο scope.
Endpoints#
Κάθε λειτουργία παρακάτω δημιουργείται από το έγγραφο OpenAPI και κάθε παράδειγμα εκτελείται από τις δοκιμές μας απέναντι στο πραγματικό API, άρα τα παραδείγματα δεν μπορούν να αποκλίνουν από το API. Οι περιγραφές λειτουργιών και πεδίων είναι στα αγγλικά, όπως στο έγγραφο.
GET /me#
Ελέγξτε ποιο κατάστημα, scopes και όρια έχει ένα κλειδί.
Describes the key you are calling with: its scopes, shop, allow-lists and limits. Costs no quota; use it to check a key.
- Απαιτούμενο scope
- οποιοδήποτε έγκυρο κλειδί
Χωρίς παραμέτρους.
| Κατάσταση | Σχήμα απάντησης | Περιγραφή |
|---|---|---|
200 | KeyInfo | Successful Response |
401 | ErrorBody | Missing, malformed, unknown or revoked API key (all look the same). |
402 | ErrorBody | The shop's subscription is not active. |
403 | ErrorBody | Key not allowed here: missing scope, IP or origin not on the key's list, plan without API. |
429 | ErrorBody | Rate limit or daily quota reached. See Retry-After. |
Check a key (HTTP 200)#
Παράδειγμα αιτήματος, curl
curl 'https://assistant.onesite.agency/api/v1/me' \
-H 'Authorization: Bearer YOUR_API_KEY'Παράδειγμα αιτήματος, JavaScript (fetch)
const response = await fetch("https://assistant.onesite.agency/api/v1/me", {
method: "GET",
headers: {
"Authorization": "Bearer YOUR_API_KEY",
},
});
const data = await response.json();
console.log(response.status, data);Παράδειγμα αιτήματος, Python (requests)
import requests
response = requests.get(
"https://assistant.onesite.agency/api/v1/me",
headers={
"Authorization": "Bearer YOUR_API_KEY",
},
)
print(response.status_code, response.json())Παράδειγμα απάντησης · HTTP 200
{
"id": 3,
"name": "Storefront search",
"hint": "osk_…PLEE",
"scopes": [
"analytics:read",
"answer",
"catalogue:read",
"similar",
"suggest"
],
"shop": {
"domain": "alpha.example",
"currency": "EUR",
"language": "en"
},
"origins": [],
"networks": [],
"created_at": "2026-10-13T09:00:00+00:00",
"last_used_at": null,
"limits": {
"answer": {
"per_minute": 20
},
"suggest": {
"per_minute": 120
},
"similar": {
"per_minute": 60
},
"catalogue:read": {
"per_minute": 120
},
"analytics:read": {
"per_minute": 30
}
},
"answers_per_day": 500
}Missing or invalid key (HTTP 401)#
Παράδειγμα αιτήματος, curl
curl 'https://assistant.onesite.agency/api/v1/me'Παράδειγμα αιτήματος, JavaScript (fetch)
const response = await fetch("https://assistant.onesite.agency/api/v1/me", {
method: "GET",
});
const data = await response.json();
console.log(response.status, data);Παράδειγμα αιτήματος, Python (requests)
import requests
response = requests.get(
"https://assistant.onesite.agency/api/v1/me",
)
print(response.status_code, response.json())Παράδειγμα απάντησης · HTTP 401
{
"error": {
"type": "authentication_error",
"code": "invalid_api_key",
"message": "Missing or invalid API key. Send it as 'Authorization: Bearer osk_…'.",
"param": null,
"request_id": "req_9f2b000000000001"
}
}POST /answers#
Κάντε μια ερώτηση με τα λόγια του αγοραστή και πάρτε την καλύτερη αντιστοιχία, εναλλακτικές και έναν λόγο για καθεμία.
Answers a shopper's question the way the shop's own assistant does: the best match, alternatives and a one-line reason for each. Product facts (title, price, stock, link) always come from the shop's catalogue; only say and why are written by an AI model — see the ai object, and pass that on to your users.
Counted against the key's per-minute limit and its daily cap; a replay with the same Idempotency-Key is free.
- Απαιτούμενο scope
answer- Όριο
- 20 κλήσεις ανά 60 s
| Όνομα | Θέση | Τύπος | Υποχρεωτικό | Περιορισμοί | Περιγραφή |
|---|---|---|---|---|---|
Idempotency-Key | header | string | null | όχι | μήκος 1–64 | Makes a retry safe: the same key and body return the first answer without a second model call. |
Σώμα αιτήματος: AnswerRequest#
| Πεδίο | Τύπος | Υποχρεωτικό | Περιγραφή |
|---|---|---|---|
query | string | ναι | The shopper's question, in their own words. |
language | Language | null | όχι | Language of the reply (ru en el es de it fr). Defaults to the shop's language. |
session_id | string | null | όχι | Opaque id of one conversation. Send the same id to let follow-ups (“cheaper”, “something lighter”) build on earlier turns. Sessions are private to your API key. |
in_stock_only | boolean | όχι | Only products that can be bought now (excludes pre-orders). |
| Κατάσταση | Σχήμα απάντησης | Περιγραφή |
|---|---|---|
200 | Answer | Successful Response |
401 | ErrorBody | Missing, malformed, unknown or revoked API key (all look the same). |
402 | ErrorBody | The shop's subscription is not active. |
403 | ErrorBody | Key not allowed here: missing scope, IP or origin not on the key's list, plan without API. |
409 | ErrorBody | Same Idempotency-Key is still being processed. |
422 | ErrorBody | Invalid request body, or Idempotency-Key reused with a different body. |
429 | ErrorBody | Rate limit or daily quota reached. See Retry-After. |
502 | ErrorBody | The answer could not be produced right now. Safe to retry. |
A shopper asks in their own words (HTTP 200)#
Παράδειγμα αιτήματος, curl
curl -X POST 'https://assistant.onesite.agency/api/v1/answers' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: 3f9d1c52-7b0e-4a53-9a6f-0c2f8e1d77aa' \
-d '{
"query": "a cold, quiet science fiction novel for a long winter",
"language": "en",
"in_stock_only": true,
"session_id": "visitor-8841"
}'Παράδειγμα αιτήματος, JavaScript (fetch)
const response = await fetch("https://assistant.onesite.agency/api/v1/answers", {
method: "POST",
headers: {
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
"Idempotency-Key": "3f9d1c52-7b0e-4a53-9a6f-0c2f8e1d77aa",
},
body: JSON.stringify({
"query": "a cold, quiet science fiction novel for a long winter",
"language": "en",
"in_stock_only": true,
"session_id": "visitor-8841"
}),
});
const data = await response.json();
console.log(response.status, data);Παράδειγμα αιτήματος, Python (requests)
import requests
response = requests.post(
"https://assistant.onesite.agency/api/v1/answers",
headers={
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
"Idempotency-Key": "3f9d1c52-7b0e-4a53-9a6f-0c2f8e1d77aa",
},
json={
"query": "a cold, quiet science fiction novel for a long winter",
"language": "en",
"in_stock_only": True,
"session_id": "visitor-8841",
},
)
print(response.status_code, response.json())Παράδειγμα απάντησης · HTTP 200
{
"id": "6f1b4a52-3c0d-4d5e-9a7e-2b8c1d0f4e11",
"query": "a cold, quiet science fiction novel for a long winter",
"intent": "search",
"say": "Here is the best match for a cold, quiet read.",
"main": {
"product": {
"id": 101,
"title": "The Left Hand of Darkness",
"maker": "Ursula K. Le Guin",
"line": "Hainish Cycle",
"url": "https://alpha.example/products/101",
"handle": "the-left-hand-of-darkness",
"external_id": "gid://shop/101",
"price": {
"amount": "12.90",
"currency": "EUR"
},
"availability": "in_stock",
"ready_at": null,
"image_url": "https://cdn.alpha.example/101.jpg",
"thumb_url": "https://cdn.alpha.example/101-s.jpg"
},
"why": "A quiet, snowbound classic - the cold-world mood you described, in one of the genre's best-loved novels.",
"why_source": "model"
},
"alternatives": [
{
"product": {
"id": 102,
"title": "The Dispossessed",
"maker": "Ursula K. Le Guin",
"line": "Hainish Cycle",
"url": "https://alpha.example/products/102",
"handle": "the-dispossessed",
"external_id": "gid://shop/102",
"price": {
"amount": "13.50",
"currency": "EUR"
},
"availability": "in_stock",
"ready_at": null,
"image_url": "https://cdn.alpha.example/102.jpg",
"thumb_url": "https://cdn.alpha.example/102-s.jpg"
},
"why": "Set in the same universe: the politics of a desert moon instead of snow.",
"why_source": "model"
},
{
"product": {
"id": 104,
"title": "Solaris",
"maker": "Stanislaw Lem",
"line": null,
"url": "https://alpha.example/products/104",
"handle": "solaris",
"external_id": "gid://shop/104",
"price": {
"amount": "11.00",
"currency": "EUR"
},
"availability": "in_stock",
"ready_at": null,
"image_url": "https://cdn.alpha.example/104.jpg",
"thumb_url": "https://cdn.alpha.example/104-s.jpg"
},
"why": "A different kind of stillness: an ocean planet that studies the people studying it.",
"why_source": "model"
}
],
"shelves": [],
"miss": false,
"miss_reason": null,
"clarify": null,
"degraded": false,
"currency": "EUR",
"ai": {
"generated": true,
"fields": [
"say",
"main.why",
"alternatives[].why"
],
"notice": "The `say` and `why` texts are generated by an AI model from this shop's catalogue and may contain mistakes. Product names, prices, stock and links come from the shop's catalogue, not from the model."
}
}Rate limit reached (HTTP 429)#
Παράδειγμα αιτήματος, curl
curl -X POST 'https://assistant.onesite.agency/api/v1/answers' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"query": "a cold, quiet science fiction novel for a long winter"
}'Παράδειγμα αιτήματος, JavaScript (fetch)
const response = await fetch("https://assistant.onesite.agency/api/v1/answers", {
method: "POST",
headers: {
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
"query": "a cold, quiet science fiction novel for a long winter"
}),
});
const data = await response.json();
console.log(response.status, data);Παράδειγμα αιτήματος, Python (requests)
import requests
response = requests.post(
"https://assistant.onesite.agency/api/v1/answers",
headers={
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
json={
"query": "a cold, quiet science fiction novel for a long winter",
},
)
print(response.status_code, response.json())Παράδειγμα απάντησης · HTTP 429
{
"error": {
"type": "rate_limit_error",
"code": "rate_limited",
"message": "Rate limit reached: 20 calls per minute for this scope.",
"param": null,
"request_id": "req_9f2b000000000005"
}
}GET /suggestions#
Γρήγορες προτάσεις προϊόντων κάτω από ένα πεδίο αναζήτησης κατά την πληκτρολόγηση. Δεν εμπλέκεται μοντέλο ΤΝ.
Instant products for a half-typed query. No model is called and nothing is journalled, so it is cheap — but it is not a substitute for POST /answers when the shopper asked a full question.
- Απαιτούμενο scope
suggest- Όριο
- 120 κλήσεις ανά 60 s
| Όνομα | Θέση | Τύπος | Υποχρεωτικό | Περιορισμοί | Περιγραφή |
|---|---|---|---|---|---|
q | query | string | ναι | μήκος 1–500 | What has been typed so far. |
limit | query | integer | όχι | 1–20; προεπιλογή 6 | |
in_stock_only | query | boolean | όχι | προεπιλογή false | Only products that can be bought now. |
| Κατάσταση | Σχήμα απάντησης | Περιγραφή |
|---|---|---|
200 | SuggestionList | Successful Response |
304 | – | Not modified: your If-None-Match matched the current ETag. |
401 | ErrorBody | Missing, malformed, unknown or revoked API key (all look the same). |
402 | ErrorBody | The shop's subscription is not active. |
403 | ErrorBody | Key not allowed here: missing scope, IP or origin not on the key's list, plan without API. |
422 | ErrorBody | Invalid request. |
429 | ErrorBody | Rate limit or daily quota reached. See Retry-After. |
Suggestions while the shopper types (HTTP 200)#
Παράδειγμα αιτήματος, curl
curl 'https://assistant.onesite.agency/api/v1/suggestions?q=left+hand&limit=3' \
-H 'Authorization: Bearer YOUR_API_KEY'Παράδειγμα αιτήματος, JavaScript (fetch)
const response = await fetch("https://assistant.onesite.agency/api/v1/suggestions?q=left+hand&limit=3", {
method: "GET",
headers: {
"Authorization": "Bearer YOUR_API_KEY",
},
});
const data = await response.json();
console.log(response.status, data);Παράδειγμα αιτήματος, Python (requests)
import requests
response = requests.get(
"https://assistant.onesite.agency/api/v1/suggestions?q=left+hand&limit=3",
headers={
"Authorization": "Bearer YOUR_API_KEY",
},
)
print(response.status_code, response.json())Παράδειγμα απάντησης · HTTP 200
{
"object": "list",
"query": "left hand",
"data": [
{
"id": 101,
"title": "The Left Hand of Darkness",
"maker": "Ursula K. Le Guin",
"line": "Hainish Cycle",
"url": "https://alpha.example/products/101",
"handle": "the-left-hand-of-darkness",
"external_id": "gid://shop/101",
"price": {
"amount": "12.90",
"currency": "EUR"
},
"availability": "in_stock",
"ready_at": null,
"image_url": "https://cdn.alpha.example/101.jpg",
"thumb_url": "https://cdn.alpha.example/101-s.jpg"
}
]
}GET /products#
Διαβάστε ολόκληρο τον κατάλογο σελίδα προς σελίδα.
The shop's visible catalogue in a stable order (by product id), a page at a time. Products the owner has hidden or excluded are not listed. A page may hold fewer than limit items while has_more is still true; keep following next_cursor until it is null.
- Απαιτούμενο scope
catalogue:read- Όριο
- 120 κλήσεις ανά 60 s
| Όνομα | Θέση | Τύπος | Υποχρεωτικό | Περιορισμοί | Περιγραφή |
|---|---|---|---|---|---|
limit | query | integer | όχι | 1–100; προεπιλογή 20 | |
cursor | query | string | null | όχι | μήκος ≤ 64 | next_cursor of the previous page. |
| Κατάσταση | Σχήμα απάντησης | Περιγραφή |
|---|---|---|
200 | ProductPage | Successful Response |
304 | – | Not modified: your If-None-Match matched the current ETag. |
401 | ErrorBody | Missing, malformed, unknown or revoked API key (all look the same). |
402 | ErrorBody | The shop's subscription is not active. |
403 | ErrorBody | Key not allowed here: missing scope, IP or origin not on the key's list, plan without API. |
422 | ErrorBody | Invalid request. |
429 | ErrorBody | Rate limit or daily quota reached. See Retry-After. |
First page of the catalogue (HTTP 200)#
Παράδειγμα αιτήματος, curl
curl 'https://assistant.onesite.agency/api/v1/products?limit=2' \
-H 'Authorization: Bearer YOUR_API_KEY'Παράδειγμα αιτήματος, JavaScript (fetch)
const response = await fetch("https://assistant.onesite.agency/api/v1/products?limit=2", {
method: "GET",
headers: {
"Authorization": "Bearer YOUR_API_KEY",
},
});
const data = await response.json();
console.log(response.status, data);Παράδειγμα αιτήματος, Python (requests)
import requests
response = requests.get(
"https://assistant.onesite.agency/api/v1/products?limit=2",
headers={
"Authorization": "Bearer YOUR_API_KEY",
},
)
print(response.status_code, response.json())Παράδειγμα απάντησης · HTTP 200
{
"object": "list",
"data": [
{
"id": 101,
"title": "The Left Hand of Darkness",
"maker": "Ursula K. Le Guin",
"line": "Hainish Cycle",
"url": "https://alpha.example/products/101",
"handle": "the-left-hand-of-darkness",
"external_id": "gid://shop/101",
"price": {
"amount": "12.90",
"currency": "EUR"
},
"availability": "in_stock",
"ready_at": null,
"image_url": "https://cdn.alpha.example/101.jpg",
"thumb_url": "https://cdn.alpha.example/101-s.jpg"
},
{
"id": 102,
"title": "The Dispossessed",
"maker": "Ursula K. Le Guin",
"line": "Hainish Cycle",
"url": "https://alpha.example/products/102",
"handle": "the-dispossessed",
"external_id": "gid://shop/102",
"price": {
"amount": "13.50",
"currency": "EUR"
},
"availability": "in_stock",
"ready_at": null,
"image_url": "https://cdn.alpha.example/102.jpg",
"thumb_url": "https://cdn.alpha.example/102-s.jpg"
}
],
"has_more": true,
"next_cursor": "c1.MTAy"
}Following the cursor (HTTP 200)#
Παράδειγμα αιτήματος, curl
curl 'https://assistant.onesite.agency/api/v1/products?limit=2&cursor=c1.MTAy' \
-H 'Authorization: Bearer YOUR_API_KEY'Παράδειγμα αιτήματος, JavaScript (fetch)
const response = await fetch("https://assistant.onesite.agency/api/v1/products?limit=2&cursor=c1.MTAy", {
method: "GET",
headers: {
"Authorization": "Bearer YOUR_API_KEY",
},
});
const data = await response.json();
console.log(response.status, data);Παράδειγμα αιτήματος, Python (requests)
import requests
response = requests.get(
"https://assistant.onesite.agency/api/v1/products?limit=2&cursor=c1.MTAy",
headers={
"Authorization": "Bearer YOUR_API_KEY",
},
)
print(response.status_code, response.json())Παράδειγμα απάντησης · HTTP 200
{
"object": "list",
"data": [
{
"id": 103,
"title": "A Wizard of Earthsea",
"maker": "Ursula K. Le Guin",
"line": "Earthsea",
"url": "https://alpha.example/products/103",
"handle": "a-wizard-of-earthsea",
"external_id": "gid://shop/103",
"price": {
"amount": "9.99",
"currency": "EUR"
},
"availability": "in_stock",
"ready_at": null,
"image_url": "https://cdn.alpha.example/103.jpg",
"thumb_url": "https://cdn.alpha.example/103-s.jpg"
},
{
"id": 104,
"title": "Solaris",
"maker": "Stanislaw Lem",
"line": null,
"url": "https://alpha.example/products/104",
"handle": "solaris",
"external_id": "gid://shop/104",
"price": {
"amount": "11.00",
"currency": "EUR"
},
"availability": "in_stock",
"ready_at": null,
"image_url": "https://cdn.alpha.example/104.jpg",
"thumb_url": "https://cdn.alpha.example/104-s.jpg"
}
],
"has_more": true,
"next_cursor": "c1.MTA0"
}A parameter out of range (HTTP 422)#
Παράδειγμα αιτήματος, curl
curl 'https://assistant.onesite.agency/api/v1/products?limit=500' \
-H 'Authorization: Bearer YOUR_API_KEY'Παράδειγμα αιτήματος, JavaScript (fetch)
const response = await fetch("https://assistant.onesite.agency/api/v1/products?limit=500", {
method: "GET",
headers: {
"Authorization": "Bearer YOUR_API_KEY",
},
});
const data = await response.json();
console.log(response.status, data);Παράδειγμα αιτήματος, Python (requests)
import requests
response = requests.get(
"https://assistant.onesite.agency/api/v1/products?limit=500",
headers={
"Authorization": "Bearer YOUR_API_KEY",
},
)
print(response.status_code, response.json())Παράδειγμα απάντησης · HTTP 422
{
"error": {
"type": "invalid_request_error",
"code": "invalid_request",
"message": "Invalid request. limit: Input should be less than or equal to 100",
"param": "limit",
"request_id": "req_9f2b000000000004"
}
}GET /products/{product_id}#
Διαβάστε ένα προϊόν με το id του.
One product of the shop with its description and gallery. A product that belongs to another shop, does not exist or is hidden by the owner is the same 404.
- Απαιτούμενο scope
catalogue:read- Όριο
- 120 κλήσεις ανά 60 s
| Όνομα | Θέση | Τύπος | Υποχρεωτικό | Περιορισμοί | Περιγραφή |
|---|---|---|---|---|---|
product_id | path | integer | ναι | 1–9223372036854776000 | Product number (id in any product object). |
| Κατάσταση | Σχήμα απάντησης | Περιγραφή |
|---|---|---|
200 | ProductDetail | Successful Response |
304 | – | Not modified: your If-None-Match matched the current ETag. |
401 | ErrorBody | Missing, malformed, unknown or revoked API key (all look the same). |
402 | ErrorBody | The shop's subscription is not active. |
403 | ErrorBody | Key not allowed here: missing scope, IP or origin not on the key's list, plan without API. |
404 | ErrorBody | No such visible product in this shop. |
422 | ErrorBody | Invalid request. |
429 | ErrorBody | Rate limit or daily quota reached. See Retry-After. |
One product with its description and gallery (HTTP 200)#
Παράδειγμα αιτήματος, curl
curl 'https://assistant.onesite.agency/api/v1/products/101' \
-H 'Authorization: Bearer YOUR_API_KEY'Παράδειγμα αιτήματος, JavaScript (fetch)
const response = await fetch("https://assistant.onesite.agency/api/v1/products/101", {
method: "GET",
headers: {
"Authorization": "Bearer YOUR_API_KEY",
},
});
const data = await response.json();
console.log(response.status, data);Παράδειγμα αιτήματος, Python (requests)
import requests
response = requests.get(
"https://assistant.onesite.agency/api/v1/products/101",
headers={
"Authorization": "Bearer YOUR_API_KEY",
},
)
print(response.status_code, response.json())Παράδειγμα απάντησης · HTTP 200
{
"id": 101,
"title": "The Left Hand of Darkness",
"maker": "Ursula K. Le Guin",
"line": "Hainish Cycle",
"url": "https://alpha.example/products/101",
"handle": "the-left-hand-of-darkness",
"external_id": "gid://shop/101",
"price": {
"amount": "12.90",
"currency": "EUR"
},
"availability": "in_stock",
"ready_at": null,
"image_url": "https://cdn.alpha.example/101.jpg",
"thumb_url": "https://cdn.alpha.example/101-s.jpg",
"description": "The Left Hand of Darkness by Ursula K. Le Guin.",
"images": [
"https://cdn.alpha.example/101.jpg"
]
}A key without the needed scope (HTTP 403)#
Παράδειγμα αιτήματος, curl
curl 'https://assistant.onesite.agency/api/v1/products/101' \
-H 'Authorization: Bearer YOUR_API_KEY'Παράδειγμα αιτήματος, JavaScript (fetch)
const response = await fetch("https://assistant.onesite.agency/api/v1/products/101", {
method: "GET",
headers: {
"Authorization": "Bearer YOUR_API_KEY",
},
});
const data = await response.json();
console.log(response.status, data);Παράδειγμα αιτήματος, Python (requests)
import requests
response = requests.get(
"https://assistant.onesite.agency/api/v1/products/101",
headers={
"Authorization": "Bearer YOUR_API_KEY",
},
)
print(response.status_code, response.json())Παράδειγμα απάντησης · HTTP 403
{
"error": {
"type": "permission_error",
"code": "insufficient_scope",
"message": "This key lacks the 'catalogue:read' scope. Create a key that has it.",
"param": "catalogue:read",
"request_id": "req_9f2b000000000002"
}
}A product that is not in this shop (HTTP 404)#
Παράδειγμα αιτήματος, curl
curl 'https://assistant.onesite.agency/api/v1/products/987654' \
-H 'Authorization: Bearer YOUR_API_KEY'Παράδειγμα αιτήματος, JavaScript (fetch)
const response = await fetch("https://assistant.onesite.agency/api/v1/products/987654", {
method: "GET",
headers: {
"Authorization": "Bearer YOUR_API_KEY",
},
});
const data = await response.json();
console.log(response.status, data);Παράδειγμα αιτήματος, Python (requests)
import requests
response = requests.get(
"https://assistant.onesite.agency/api/v1/products/987654",
headers={
"Authorization": "Bearer YOUR_API_KEY",
},
)
print(response.status_code, response.json())Παράδειγμα απάντησης · HTTP 404
{
"error": {
"type": "not_found_error",
"code": "product_not_found",
"message": "No such product in this shop.",
"param": null,
"request_id": "req_9f2b000000000003"
}
}GET /products/{product_id}/similar#
Προϊόντα παρόμοια με ένα προϊόν. Δεν εμπλέκεται μοντέλο ΤΝ.
Neighbours of the product's own embedding vector, ranked the way the shop's assistant ranks them. No model is called. Needs only the similar scope — a key without catalogue:read cannot fetch the product itself.
- Απαιτούμενο scope
similar- Όριο
- 60 κλήσεις ανά 60 s
| Όνομα | Θέση | Τύπος | Υποχρεωτικό | Περιορισμοί | Περιγραφή |
|---|---|---|---|---|---|
product_id | path | integer | ναι | 1–9223372036854776000 | Product number (id in any product object). |
limit | query | integer | όχι | 1–24; προεπιλογή 8 |
| Κατάσταση | Σχήμα απάντησης | Περιγραφή |
|---|---|---|
200 | SimilarList | Successful Response |
304 | – | Not modified: your If-None-Match matched the current ETag. |
401 | ErrorBody | Missing, malformed, unknown or revoked API key (all look the same). |
402 | ErrorBody | The shop's subscription is not active. |
403 | ErrorBody | Key not allowed here: missing scope, IP or origin not on the key's list, plan without API. |
404 | ErrorBody | No such visible product in this shop. |
422 | ErrorBody | Invalid request. |
429 | ErrorBody | Rate limit or daily quota reached. See Retry-After. |
Products similar to one product (HTTP 200)#
Παράδειγμα αιτήματος, curl
curl 'https://assistant.onesite.agency/api/v1/products/101/similar?limit=3' \
-H 'Authorization: Bearer YOUR_API_KEY'Παράδειγμα αιτήματος, JavaScript (fetch)
const response = await fetch("https://assistant.onesite.agency/api/v1/products/101/similar?limit=3", {
method: "GET",
headers: {
"Authorization": "Bearer YOUR_API_KEY",
},
});
const data = await response.json();
console.log(response.status, data);Παράδειγμα αιτήματος, Python (requests)
import requests
response = requests.get(
"https://assistant.onesite.agency/api/v1/products/101/similar?limit=3",
headers={
"Authorization": "Bearer YOUR_API_KEY",
},
)
print(response.status_code, response.json())Παράδειγμα απάντησης · HTTP 200
{
"object": "list",
"data": [
{
"id": 102,
"title": "The Dispossessed",
"maker": "Ursula K. Le Guin",
"line": "Hainish Cycle",
"url": "https://alpha.example/products/102",
"handle": "the-dispossessed",
"external_id": "gid://shop/102",
"price": {
"amount": "13.50",
"currency": "EUR"
},
"availability": "in_stock",
"ready_at": null,
"image_url": "https://cdn.alpha.example/102.jpg",
"thumb_url": "https://cdn.alpha.example/102-s.jpg"
},
{
"id": 103,
"title": "A Wizard of Earthsea",
"maker": "Ursula K. Le Guin",
"line": "Earthsea",
"url": "https://alpha.example/products/103",
"handle": "a-wizard-of-earthsea",
"external_id": "gid://shop/103",
"price": {
"amount": "9.99",
"currency": "EUR"
},
"availability": "in_stock",
"ready_at": null,
"image_url": "https://cdn.alpha.example/103.jpg",
"thumb_url": "https://cdn.alpha.example/103-s.jpg"
},
{
"id": 109,
"title": "Gift Cookbook",
"maker": "Chef Example",
"line": null,
"url": "https://alpha.example/products/109",
"handle": "gift-cookbook",
"external_id": "gid://shop/109",
"price": {
"amount": "24.00",
"currency": "EUR"
},
"availability": "in_stock",
"ready_at": null,
"image_url": "https://cdn.alpha.example/109.jpg",
"thumb_url": "https://cdn.alpha.example/109-s.jpg"
}
],
"product_id": 101
}GET /analytics/summary#
Τα σύνολα του καταστήματός σας για ένα διάστημα — τα ίδια νούμερα με τα Στατιστικά του cabinet — με προαιρετική σύγκριση.
The cabinet's Statistics figures for the window: questions, people who asked, sessions, found and not found, clicks, and the shopper's path by step. Counted for people only. With compare, the same totals for the comparison window — only when the shop's history covers it; otherwise previous is null rather than a growth from nothing.
- Απαιτούμενο scope
analytics:read- Όριο
- 30 κλήσεις ανά 60 s
| Όνομα | Θέση | Τύπος | Υποχρεωτικό | Περιορισμοί | Περιγραφή |
|---|---|---|---|---|---|
compare | query | "prev" | "year" | "none" | όχι | προεπιλογή "prev" | Compare with the window just before (prev), the same window a year back (year), or nothing. |
since | query | string (date-time) | null | όχι | | Start of the window (ISO 8601; without an offset — UTC). Default: until minus 30 days. |
until | query | string (date-time) | null | όχι | | End of the window, exclusive (ISO 8601). Default: now. |
first_day | query | string (date) | null | όχι | | First day of the window (YYYY-MM-DD) in timezone, inclusive. Use with last_day instead of since/until. |
last_day | query | string (date) | null | όχι | | Last day of the window (YYYY-MM-DD) in timezone, inclusive. |
timezone | query | string | null | όχι | μήκος ≤ 64 | IANA time zone for days, e.g. Europe/Berlin. Default: the shop's time zone, or UTC when the shop has none. |
| Κατάσταση | Σχήμα απάντησης | Περιγραφή |
|---|---|---|
200 | AnalyticsSummary | Successful Response |
304 | – | Not modified: your If-None-Match matched the current ETag. |
401 | ErrorBody | Missing, malformed, unknown or revoked API key (all look the same). |
402 | ErrorBody | The shop's subscription is not active. |
403 | ErrorBody | Key not allowed here: missing scope, IP or origin not on the key's list, plan without API. |
422 | ErrorBody | Invalid request. |
429 | ErrorBody | Rate limit or daily quota reached. See Retry-After. |
Last week in figures, compared with the week before (HTTP 200)#
Παράδειγμα αιτήματος, curl
curl 'https://assistant.onesite.agency/api/v1/analytics/summary?first_day=2026-10-06&last_day=2026-10-12' \
-H 'Authorization: Bearer YOUR_API_KEY'Παράδειγμα αιτήματος, JavaScript (fetch)
const response = await fetch("https://assistant.onesite.agency/api/v1/analytics/summary?first_day=2026-10-06&last_day=2026-10-12", {
method: "GET",
headers: {
"Authorization": "Bearer YOUR_API_KEY",
},
});
const data = await response.json();
console.log(response.status, data);Παράδειγμα αιτήματος, Python (requests)
import requests
response = requests.get(
"https://assistant.onesite.agency/api/v1/analytics/summary?first_day=2026-10-06&last_day=2026-10-12",
headers={
"Authorization": "Bearer YOUR_API_KEY",
},
)
print(response.status_code, response.json())Παράδειγμα απάντησης · HTTP 200
{
"object": "analytics.summary",
"window": {
"since": "2026-10-06T00:00:00+00:00",
"until": "2026-10-13T00:00:00+00:00",
"timezone": "UTC"
},
"totals": {
"queries": 280,
"people": 154,
"sessions": 174,
"answered": 238,
"missed": 42,
"asked_again": 31,
"impressions": 840,
"clicks": 82,
"reached": 63,
"browsed": 7
},
"compare": "prev",
"previous_window": {
"since": "2026-09-29T00:00:00+00:00",
"until": "2026-10-06T00:00:00+00:00"
},
"previous": {
"queries": 273,
"people": 150,
"sessions": 174,
"answered": 238,
"missed": 42,
"asked_again": 31,
"impressions": 840,
"clicks": 82,
"reached": 63,
"browsed": 7
},
"funnel": [
{
"stage": "visit",
"sessions": 900,
"share_of_previous": null
},
{
"stage": "offered",
"sessions": 860,
"share_of_previous": 0.9555555555555556
},
{
"stage": "opened",
"sessions": 140,
"share_of_previous": 0.16279069767441862
},
{
"stage": "asked",
"sessions": 120,
"share_of_previous": 0.8571428571428571
},
{
"stage": "reached",
"sessions": 30,
"share_of_previous": 0.25
},
{
"stage": "carted",
"sessions": 70,
"share_of_previous": null
},
{
"stage": "bought",
"sessions": 12,
"share_of_previous": 0.17142857142857143
}
],
"funnel_since": null
}GET /analytics/series#
Ερωτήσεις, ερωτήσεις χωρίς αποτέλεσμα και ερωτήσεις που έφτασαν σε προϊόν, για κάθε ημέρα του διαστήματος.
Questions, misses and questions that reached a product, for every day of the window in timezone. Days without questions are zeros. Only the window is counted, so the first and last day may be partial, and the days add up to the summary's totals.
- Απαιτούμενο scope
analytics:read- Όριο
- 30 κλήσεις ανά 60 s
| Όνομα | Θέση | Τύπος | Υποχρεωτικό | Περιορισμοί | Περιγραφή |
|---|---|---|---|---|---|
since | query | string (date-time) | null | όχι | | Start of the window (ISO 8601; without an offset — UTC). Default: until minus 30 days. |
until | query | string (date-time) | null | όχι | | End of the window, exclusive (ISO 8601). Default: now. |
first_day | query | string (date) | null | όχι | | First day of the window (YYYY-MM-DD) in timezone, inclusive. Use with last_day instead of since/until. |
last_day | query | string (date) | null | όχι | | Last day of the window (YYYY-MM-DD) in timezone, inclusive. |
timezone | query | string | null | όχι | μήκος ≤ 64 | IANA time zone for days, e.g. Europe/Berlin. Default: the shop's time zone, or UTC when the shop has none. |
| Κατάσταση | Σχήμα απάντησης | Περιγραφή |
|---|---|---|
200 | AnalyticsSeries | Successful Response |
304 | – | Not modified: your If-None-Match matched the current ETag. |
401 | ErrorBody | Missing, malformed, unknown or revoked API key (all look the same). |
402 | ErrorBody | The shop's subscription is not active. |
403 | ErrorBody | Key not allowed here: missing scope, IP or origin not on the key's list, plan without API. |
422 | ErrorBody | Invalid request. |
429 | ErrorBody | Rate limit or daily quota reached. See Retry-After. |
Questions per day (HTTP 200)#
Παράδειγμα αιτήματος, curl
curl 'https://assistant.onesite.agency/api/v1/analytics/series?first_day=2026-10-06&last_day=2026-10-12&timezone=Europe/Berlin' \
-H 'Authorization: Bearer YOUR_API_KEY'Παράδειγμα αιτήματος, JavaScript (fetch)
const response = await fetch("https://assistant.onesite.agency/api/v1/analytics/series?first_day=2026-10-06&last_day=2026-10-12&timezone=Europe/Berlin", {
method: "GET",
headers: {
"Authorization": "Bearer YOUR_API_KEY",
},
});
const data = await response.json();
console.log(response.status, data);Παράδειγμα αιτήματος, Python (requests)
import requests
response = requests.get(
"https://assistant.onesite.agency/api/v1/analytics/series?first_day=2026-10-06&last_day=2026-10-12&timezone=Europe/Berlin",
headers={
"Authorization": "Bearer YOUR_API_KEY",
},
)
print(response.status_code, response.json())Παράδειγμα απάντησης · HTTP 200
{
"object": "analytics.series",
"window": {
"since": "2026-10-05T22:00:00+00:00",
"until": "2026-10-12T22:00:00+00:00",
"timezone": "Europe/Berlin"
},
"data": [
{
"date": "2026-10-06",
"queries": 40,
"missed": 6,
"reached": 9
},
{
"date": "2026-10-07",
"queries": 40,
"missed": 6,
"reached": 9
},
{
"date": "2026-10-08",
"queries": 40,
"missed": 6,
"reached": 9
},
{
"date": "2026-10-09",
"queries": 40,
"missed": 6,
"reached": 9
},
{
"date": "2026-10-10",
"queries": 40,
"missed": 6,
"reached": 9
},
{
"date": "2026-10-11",
"queries": 40,
"missed": 6,
"reached": 9
},
{
"date": "2026-10-12",
"queries": 40,
"missed": 6,
"reached": 9
}
]
}GET /analytics/queries#
Οι πιο συχνές ερωτήσεις και εκείνες που πιο συχνά μένουν χωρίς προϊόν.
The questions people ask most, and the questions most often left without a product — what to stock and what to describe better. Questions are grouped without regard to case; e-mail addresses and phone or card numbers in them are masked.
- Απαιτούμενο scope
analytics:read- Όριο
- 30 κλήσεις ανά 60 s
| Όνομα | Θέση | Τύπος | Υποχρεωτικό | Περιορισμοί | Περιγραφή |
|---|---|---|---|---|---|
limit | query | integer | όχι | 1–100; προεπιλογή 20 | Rows in each list. |
since | query | string (date-time) | null | όχι | | Start of the window (ISO 8601; without an offset — UTC). Default: until minus 30 days. |
until | query | string (date-time) | null | όχι | | End of the window, exclusive (ISO 8601). Default: now. |
first_day | query | string (date) | null | όχι | | First day of the window (YYYY-MM-DD) in timezone, inclusive. Use with last_day instead of since/until. |
last_day | query | string (date) | null | όχι | | Last day of the window (YYYY-MM-DD) in timezone, inclusive. |
timezone | query | string | null | όχι | μήκος ≤ 64 | IANA time zone for days, e.g. Europe/Berlin. Default: the shop's time zone, or UTC when the shop has none. |
| Κατάσταση | Σχήμα απάντησης | Περιγραφή |
|---|---|---|
200 | AnalyticsQueries | Successful Response |
304 | – | Not modified: your If-None-Match matched the current ETag. |
401 | ErrorBody | Missing, malformed, unknown or revoked API key (all look the same). |
402 | ErrorBody | The shop's subscription is not active. |
403 | ErrorBody | Key not allowed here: missing scope, IP or origin not on the key's list, plan without API. |
422 | ErrorBody | Invalid request. |
429 | ErrorBody | Rate limit or daily quota reached. See Retry-After. |
What people ask most, and what they do not find (HTTP 200)#
Παράδειγμα αιτήματος, curl
curl 'https://assistant.onesite.agency/api/v1/analytics/queries?first_day=2026-10-06&last_day=2026-10-12&limit=3' \
-H 'Authorization: Bearer YOUR_API_KEY'Παράδειγμα αιτήματος, JavaScript (fetch)
const response = await fetch("https://assistant.onesite.agency/api/v1/analytics/queries?first_day=2026-10-06&last_day=2026-10-12&limit=3", {
method: "GET",
headers: {
"Authorization": "Bearer YOUR_API_KEY",
},
});
const data = await response.json();
console.log(response.status, data);Παράδειγμα αιτήματος, Python (requests)
import requests
response = requests.get(
"https://assistant.onesite.agency/api/v1/analytics/queries?first_day=2026-10-06&last_day=2026-10-12&limit=3",
headers={
"Authorization": "Bearer YOUR_API_KEY",
},
)
print(response.status_code, response.json())Παράδειγμα απάντησης · HTTP 200
{
"object": "analytics.queries",
"window": {
"since": "2026-10-06T00:00:00+00:00",
"until": "2026-10-13T00:00:00+00:00",
"timezone": "UTC"
},
"top": [
{
"text": "science fiction for winter",
"count": 42,
"missed": 0,
"clicks": 28
},
{
"text": "gift for a ten-year-old",
"count": 28,
"missed": 7,
"clicks": 14
},
{
"text": "write to me at [email]",
"count": 1,
"missed": 1,
"clicks": 0
}
],
"missed": [
{
"text": "signed first editions",
"count": 21,
"missed": 21,
"clicks": 0
},
{
"text": "gift for a ten-year-old",
"count": 28,
"missed": 7,
"clicks": 14
}
]
}GET /analytics/sales#
Τι πούλησε ο βοηθός, σύμφωνα με τις δικές σας παραγγελίες — τα ίδια νούμερα με τη σύνοψη Αγορών του cabinet.
Orders and revenue the assistant helped with, by the shop's own orders: products its button put into the cart and products bought after it showed them. Orders after a conversation without either are counted apart and not as its revenue. The shop's total turnover is not part of this API.
- Απαιτούμενο scope
analytics:read- Όριο
- 30 κλήσεις ανά 60 s
| Όνομα | Θέση | Τύπος | Υποχρεωτικό | Περιορισμοί | Περιγραφή |
|---|---|---|---|---|---|
days | query | integer | όχι | προεπιλογή 30 | Period: today and the days before it. One of 7, 30, 90. |
timezone | query | string | null | όχι | μήκος ≤ 64 | IANA time zone for days. Default: the shop's time zone, or UTC. |
| Κατάσταση | Σχήμα απάντησης | Περιγραφή |
|---|---|---|
200 | AnalyticsSales | Successful Response |
304 | – | Not modified: your If-None-Match matched the current ETag. |
401 | ErrorBody | Missing, malformed, unknown or revoked API key (all look the same). |
402 | ErrorBody | The shop's subscription is not active. |
403 | ErrorBody | Key not allowed here: missing scope, IP or origin not on the key's list, plan without API. |
422 | ErrorBody | Invalid request. |
429 | ErrorBody | Rate limit or daily quota reached. See Retry-After. |
What the assistant sold in the last 7 days (HTTP 200)#
Παράδειγμα αιτήματος, curl
curl 'https://assistant.onesite.agency/api/v1/analytics/sales?days=7' \
-H 'Authorization: Bearer YOUR_API_KEY'Παράδειγμα αιτήματος, JavaScript (fetch)
const response = await fetch("https://assistant.onesite.agency/api/v1/analytics/sales?days=7", {
method: "GET",
headers: {
"Authorization": "Bearer YOUR_API_KEY",
},
});
const data = await response.json();
console.log(response.status, data);Παράδειγμα αιτήματος, Python (requests)
import requests
response = requests.get(
"https://assistant.onesite.agency/api/v1/analytics/sales?days=7",
headers={
"Authorization": "Bearer YOUR_API_KEY",
},
)
print(response.status_code, response.json())Παράδειγμα απάντησης · HTTP 200
{
"object": "analytics.sales",
"days": 7,
"since": "2026-10-07T00:00:00+00:00",
"timezone": "UTC",
"currency": "EUR",
"assistant_orders": 2,
"assistant_revenue": {
"amount": "23.90",
"currency": "EUR"
},
"button_revenue": {
"amount": "12.90",
"currency": "EUR"
},
"shown_revenue": {
"amount": "11.00",
"currency": "EUR"
},
"carted": 3,
"talked_orders": 1,
"average_order": {
"amount": "18.70",
"currency": "EUR"
},
"days_data": [
{
"date": "2026-10-07",
"orders": 0,
"revenue": {
"amount": "0.00",
"currency": "EUR"
}
},
{
"date": "2026-10-08",
"orders": 0,
"revenue": {
"amount": "0.00",
"currency": "EUR"
}
},
{
"date": "2026-10-09",
"orders": 0,
"revenue": {
"amount": "0.00",
"currency": "EUR"
}
},
{
"date": "2026-10-10",
"orders": 0,
"revenue": {
"amount": "0.00",
"currency": "EUR"
}
},
{
"date": "2026-10-11",
"orders": 1,
"revenue": {
"amount": "11.00",
"currency": "EUR"
}
},
{
"date": "2026-10-12",
"orders": 0,
"revenue": {
"amount": "0.00",
"currency": "EUR"
}
},
{
"date": "2026-10-13",
"orders": 1,
"revenue": {
"amount": "12.90",
"currency": "EUR"
}
}
],
"products": [
{
"product_id": 101,
"title": "The Left Hand of Darkness",
"quantity": 1,
"revenue": {
"amount": "12.90",
"currency": "EUR"
}
},
{
"product_id": 104,
"title": "Solaris",
"quantity": 1,
"revenue": {
"amount": "11.00",
"currency": "EUR"
}
}
]
}Τύποι δεδομένων#
Τα αντικείμενα που χρησιμοποιούνται σε αιτήματα και απαντήσεις. Το | null σημαίνει ότι το πεδίο υπάρχει πάντα αλλά μπορεί να είναι null· ένας πίνακας γράφεται Τύπος[].
AiDisclosure#
Shown to your users? Then say so. The wording below is the minimum we ask integrations to pass on.
| Πεδίο | Τύπος | Υποχρεωτικό | Περιγραφή |
|---|---|---|---|
generated | boolean | όχι | Some text in this response was written by an AI model. |
fields | string[] | ναι | JSON paths of the AI-written strings. |
notice | string | ναι |
AnalyticsFunnelStep#
| Πεδίο | Τύπος | Υποχρεωτικό | Περιγραφή |
|---|---|---|---|
stage | "visit" | "offered" | "opened" | "asked" | "reached" | "carted" | "bought" | ναι | |
sessions | integer | ναι | Sessions that reached this step. Sessions, not people: events on the site carry no visitor mark. |
share_of_previous | number | null | όχι | sessions divided by the previous step. null on the first step and where a step is larger than the one before it (for example, carts added with the shop's own button without a click in an answer). |
AnalyticsPeriod#
| Πεδίο | Τύπος | Υποχρεωτικό | Περιγραφή |
|---|---|---|---|
since | string | ναι | |
until | string | ναι |
AnalyticsPoint#
| Πεδίο | Τύπος | Υποχρεωτικό | Περιγραφή |
|---|---|---|---|
date | string | ναι | The day (YYYY-MM-DD) in window.timezone. The first and last day may be partial: only the window is counted. |
queries | integer | ναι | |
missed | integer | ναι | |
reached | integer | ναι | Questions of the day after which the shopper opened a product page from the answer. |
AnalyticsQueries#
| Πεδίο | Τύπος | Υποχρεωτικό | Περιγραφή |
|---|---|---|---|
object | "analytics.queries" | όχι | |
window | AnalyticsWindow | ναι | |
top | AnalyticsQuery[] | ναι | Most frequent questions, most frequent first. |
missed | AnalyticsQuery[] | ναι | Questions most often left without a product, by number of misses. Its own list, not a filter of top. |
AnalyticsQuery#
| Πεδίο | Τύπος | Υποχρεωτικό | Περιγραφή |
|---|---|---|---|
text | string | ναι | The question as asked (case-insensitive group). E-mail addresses, phone and card numbers are masked. |
count | integer | ναι | How many times it was asked. |
missed | integer | ναι | How many of those had nothing to show. |
clicks | integer | ναι | Clicks from its answers to product pages. |
AnalyticsSales#
What the assistant sold, by the shop's own orders — the same figures as the summary in the cabinet's Purchases section.
| Πεδίο | Τύπος | Υποχρεωτικό | Περιγραφή |
|---|---|---|---|
object | "analytics.sales" | όχι | |
days | integer | ναι | Today and the days before it, from midnight in timezone. |
since | string | ναι | Midnight of the first day (ISO 8601). |
timezone | string | ναι | |
currency | string | ναι | Orders in another currency are not added up. |
assistant_orders | integer | ναι | Orders with a product added to the cart by the assistant's button or bought after the assistant showed it. |
assistant_revenue | Money | ναι | The value of those products (not the whole orders). |
button_revenue | Money | ναι | Part of assistant_revenue added to the cart by the assistant's button. |
shown_revenue | Money | ναι | Part of assistant_revenue bought after the assistant showed the product. |
carted | integer | ναι | Products the assistant helped to put into a cart in the period (by its button or after showing them). |
talked_orders | integer | ναι | Orders placed after a conversation with the assistant without any of the above. Not counted as its revenue. |
average_order | Money | null | όχι | Average total of assistant_orders; null when none has a total. |
days_data | AnalyticsSalesDay[] | ναι | Every day of the period, empty days included. |
products | AnalyticsSoldProduct[] | ναι | Top products sold through the assistant, by revenue. |
AnalyticsSalesDay#
| Πεδίο | Τύπος | Υποχρεωτικό | Περιγραφή |
|---|---|---|---|
date | string | ναι | The day (YYYY-MM-DD) in timezone. |
orders | integer | ναι | |
revenue | Money | ναι |
AnalyticsSeries#
| Πεδίο | Τύπος | Υποχρεωτικό | Περιγραφή |
|---|---|---|---|
object | "analytics.series" | όχι | |
window | AnalyticsWindow | ναι | |
data | AnalyticsPoint[] | ναι | Every day of the window, days without questions included as zeros. The sum of queries equals totals.queries of the summary. |
AnalyticsSoldProduct#
| Πεδίο | Τύπος | Υποχρεωτικό | Περιγραφή |
|---|---|---|---|
product_id | integer | null | όχι | null when the product is no longer in the catalogue. |
title | string | null | όχι | |
quantity | integer | ναι | |
revenue | Money | ναι |
AnalyticsSummary#
| Πεδίο | Τύπος | Υποχρεωτικό | Περιγραφή |
|---|---|---|---|
object | "analytics.summary" | όχι | |
window | AnalyticsWindow | ναι | |
totals | AnalyticsTotals | ναι | |
compare | "prev" | "year" | "none" | ναι | |
previous_window | AnalyticsPeriod | null | όχι | The window compared with. null when compare is none or the shop's history covers less than 90 % of it. |
previous | AnalyticsTotals | null | όχι | Totals of previous_window, counted the same way. null — no comparison. |
funnel | AnalyticsFunnelStep[] | ναι | Sessions by step of the shopper's path, in order. |
funnel_since | string | null | όχι | Set when the funnel is counted from a later moment than window.since: before it one of the steps was not yet recorded. |
AnalyticsTotals#
Counted for people only: bots, our own checks, calls made with API keys and conversations removed by the operator are not counted.
| Πεδίο | Τύπος | Υποχρεωτικό | Περιγραφή |
|---|---|---|---|
queries | integer | ναι | Questions people asked the assistant, in their own words. |
people | integer | ναι | Different people who asked at least once, by the visitor mark in their browser: someone back three days later is one person, the same person on phone and laptop is two. A question without the mark (no analytics consent) counts its session. |
sessions | integer | ναι | Different sessions with at least one question. A session lasts about a day, so this is not people. |
answered | integer | ναι | Questions answered with at least one product. |
missed | integer | ναι | Questions with nothing to show. |
asked_again | integer | ναι | Sessions that asked another question after an answer. |
impressions | integer | ναι | Product cards shown in answers. |
clicks | integer | ναι | Clicks from answer cards to product pages. |
reached | integer | ναι | Questions after which the shopper opened a product page from the answer. Counted per question, not per click. |
browsed | integer | ναι | Clicks to product pages from shelves and collections, with no question before them. |
AnalyticsWindow#
| Πεδίο | Τύπος | Υποχρεωτικό | Περιγραφή |
|---|---|---|---|
since | string | ναι | Start of the window, inclusive (ISO 8601, UTC). |
until | string | ναι | End of the window, exclusive (ISO 8601, UTC). |
timezone | string | ναι | IANA time zone in which days are cut (daily series, first_day/last_day). |
Answer#
| Πεδίο | Τύπος | Υποχρεωτικό | Περιγραφή |
|---|---|---|---|
id | string | ναι | Id of this answer in the shop's journal. Quote it when you report a problem. |
query | string | ναι | |
intent | string | ναι | What the question was understood to be: search, browse, basket, question, greeting, off_topic, code, about_item, order…. New values may appear; treat unknown ones as search. |
say | string | null | όχι | A short spoken-style reply, written by an AI model. May be null. |
main | Recommendation | null | όχι | The single best match, when there is one. |
alternatives | Recommendation[] | όχι | |
shelves | Shelf[] | όχι | For “everything by …” questions: whole shelves instead of picks. |
miss | boolean | ναι | true when the shop has nothing that fits. Do not invent a product then. |
miss_reason | "absent" | "unstocked" | "unmatched" | null | όχι | Why nothing is shown: not in the catalogue (absent), sold out (unstocked), or nothing matched the question's hard limits such as price (unmatched). |
clarify | string | null | όχι | A clarifying question to ask the user, when the answer needs one. |
degraded | boolean | όχι | true when the answer was built without the model (it was unavailable). |
currency | string | ναι | |
ai | AiDisclosure | ναι |
AnswerRequest#
| Πεδίο | Τύπος | Υποχρεωτικό | Περιγραφή |
|---|---|---|---|
query | string | ναι | The shopper's question, in their own words. |
language | Language | null | όχι | Language of the reply (ru en el es de it fr). Defaults to the shop's language. |
session_id | string | null | όχι | Opaque id of one conversation. Send the same id to let follow-ups (“cheaper”, “something lighter”) build on earlier turns. Sessions are private to your API key. |
in_stock_only | boolean | όχι | Only products that can be bought now (excludes pre-orders). |
ErrorBody#
| Πεδίο | Τύπος | Υποχρεωτικό | Περιγραφή |
|---|---|---|---|
error | ErrorDetail | ναι |
ErrorDetail#
| Πεδίο | Τύπος | Υποχρεωτικό | Περιγραφή |
|---|---|---|---|
type | "authentication_error" | "permission_error" | "invalid_request_error" | "not_found_error" | "conflict_error" | "rate_limit_error" | "billing_error" | "api_error" | ναι | |
code | string | ναι | Stable machine-readable reason. Branch on this, not on message. |
message | string | ναι | For humans. The wording may change between releases. |
param | string | null | όχι | The offending field or parameter, for invalid_request. |
request_id | string | ναι | Also in the X-Request-Id response header. |
KeyInfo#
| Πεδίο | Τύπος | Υποχρεωτικό | Περιγραφή |
|---|---|---|---|
id | integer | ναι | |
name | string | ναι | |
hint | string | ναι | Which key this is, e.g. osk_…x9Zq. The secret itself is never shown again. |
scopes | string[] | ναι | |
shop | KeyShop | ναι | |
origins | string[] | ναι | Browser origins allowed to use this key. Empty = any (server-side use). |
networks | string[] | ναι | IP networks the key is accepted from. Empty = any. |
created_at | string | ναι | |
last_used_at | string | null | όχι | |
limits | map<string, ScopeLimit> | ναι | Calls per minute, per scope. |
answers_per_day | integer | ναι | Daily cap on POST /answers calls for this key (UTC day). |
KeyShop#
| Πεδίο | Τύπος | Υποχρεωτικό | Περιγραφή |
|---|---|---|---|
domain | string | ναι | |
currency | string | ναι | |
language | string | ναι |
Language#
Language code: ru, en, el, es, de, it, fr.
"ru" | "en" | "el" | "es" | "de" | "it" | "fr"
Money#
| Πεδίο | Τύπος | Υποχρεωτικό | Περιγραφή |
|---|---|---|---|
amount | string | ναι | Decimal amount as a string, e.g. "12.90". Never a float: no rounding surprises. |
currency | string | ναι | ISO 4217 code of the shop currency, e.g. EUR. |
Product#
A catalogue card. Everything here comes from the shop's own catalogue, never from the model.
| Πεδίο | Τύπος | Υποχρεωτικό | Περιγραφή |
|---|---|---|---|
id | integer | ναι | Product number in this shop's catalogue. Stable until the product is removed from the shop. |
title | string | ναι | |
maker | string | null | όχι | Whoever the shop credits as the maker of the product. |
line | string | null | όχι | Series, collection or product line, when the shop names one. |
url | string | null | όχι | Product page on the shop's own site. |
handle | string | null | όχι | The platform's product handle (Shopify handle, WooCommerce slug), when known. |
external_id | string | null | όχι | The shop platform's own product id, for mapping back to your system. |
price | Money | null | όχι | Current price; null when the shop does not publish one. |
availability | "in_stock" | "preorder" | "out_of_stock" | ναι | |
ready_at | string | null | όχι | For preorder: the shop's promised ship date (ISO 8601). |
image_url | string | null | όχι | |
thumb_url | string | null | όχι | A smaller image, when the shop has one. |
ProductDetail#
| Πεδίο | Τύπος | Υποχρεωτικό | Περιγραφή |
|---|---|---|---|
id | integer | ναι | Product number in this shop's catalogue. Stable until the product is removed from the shop. |
title | string | ναι | |
maker | string | null | όχι | Whoever the shop credits as the maker of the product. |
line | string | null | όχι | Series, collection or product line, when the shop names one. |
url | string | null | όχι | Product page on the shop's own site. |
handle | string | null | όχι | The platform's product handle (Shopify handle, WooCommerce slug), when known. |
external_id | string | null | όχι | The shop platform's own product id, for mapping back to your system. |
price | Money | null | όχι | Current price; null when the shop does not publish one. |
availability | "in_stock" | "preorder" | "out_of_stock" | ναι | |
ready_at | string | null | όχι | For preorder: the shop's promised ship date (ISO 8601). |
image_url | string | null | όχι | |
thumb_url | string | null | όχι | A smaller image, when the shop has one. |
description | string | null | όχι | |
images | string[] | όχι | The shop's gallery, in the shop's order. |
ProductPage#
| Πεδίο | Τύπος | Υποχρεωτικό | Περιγραφή |
|---|---|---|---|
object | "list" | όχι | |
data | Product[] | ναι | |
has_more | boolean | ναι | |
next_cursor | string | null | όχι | Pass as cursor to get the next page. null on the last page. |
Recommendation#
| Πεδίο | Τύπος | Υποχρεωτικό | Περιγραφή |
|---|---|---|---|
product | Product | ναι | |
why | string | null | όχι | One sentence on why this fits the question. Written by an AI model when why_source is model; a fixed catalogue template when it is catalogue. |
why_source | "model" | "catalogue" | null | όχι | Who wrote why. null when there is no why. |
ScopeLimit#
| Πεδίο | Τύπος | Υποχρεωτικό | Περιγραφή |
|---|---|---|---|
per_minute | integer | ναι |
Shelf#
| Πεδίο | Τύπος | Υποχρεωτικό | Περιγραφή |
|---|---|---|---|
title | string | ναι | |
total | integer | ναι | How many products the shelf holds in the shop — not how many are shown in items. |
items | Product[] | ναι |
SimilarList#
| Πεδίο | Τύπος | Υποχρεωτικό | Περιγραφή |
|---|---|---|---|
object | "list" | όχι | |
data | Product[] | ναι | |
product_id | integer | ναι |
SuggestionList#
| Πεδίο | Τύπος | Υποχρεωτικό | Περιγραφή |
|---|---|---|---|
object | "list" | όχι | |
query | string | ναι | |
data | Product[] | ναι |
Σφάλματα#
Όλα τα σφάλματα έχουν την ίδια μορφή και ένα request_id (και στην κεφαλίδα X-Request-Id): αναφέρετέ το όταν μας γράφετε. Διακλαδίστε με βάση το code, ποτέ το message, του οποίου η διατύπωση μπορεί να αλλάξει.
Σφάλματα · HTTP 422
{
"error": {
"type": "invalid_request_error",
"code": "invalid_request",
"message": "Invalid request. limit: Input should be less than or equal to 100",
"param": "limit",
"request_id": "req_9f2b000000000004"
}
}| Κωδικός | HTTP | Τι σημαίνει και τι να κάνετε | Επανάληψη |
|---|---|---|---|
invalid_api_key | 401 | Το κλειδί λείπει, είναι κακοσχηματισμένο, άγνωστο ή ανακλήθηκε. Οι τέσσερις περιπτώσεις φαίνονται ίδιες εσκεμμένα. Στείλτε Authorization: Bearer <κλειδί> ή δημιουργήστε νέο κλειδί. | διορθώστε το αίτημα |
ip_not_allowed | 403 | Το κλειδί έχει λίστα επιτρεπόμενων IP και αυτή η διεύθυνση δεν περιλαμβάνεται. Καλέστε από δίκτυο της λίστας ή αλλάξτε τη λίστα στο cabinet. | διορθώστε το αίτημα |
origin_not_allowed | 403 | Η κλήση έρχεται από σελίδα προγράμματος περιήγησης της οποίας η προέλευση δεν είναι στη λίστα του κλειδιού. Προσθέστε ακριβώς την προέλευση (σχήμα, host, θύρα) στο cabinet. | διορθώστε το αίτημα |
insufficient_scope | 403 | Το κλειδί δεν έχει το scope που απαιτεί αυτό το endpoint. Τα scopes δεν διευρύνονται: δημιουργήστε νέο κλειδί με αυτό το scope. | διορθώστε το αίτημα |
api_disabled | 403 | Το API για προγραμματιστές δεν είναι ενεργό για αυτό το κατάστημα. Ανοίξτε την καρτέλα Developers στο cabinet ή επικοινωνήστε μαζί μας αν δεν τη βλέπετε. | διορθώστε το αίτημα |
subscription_inactive | 402 | Η συνδρομή του καταστήματος δεν είναι ενεργή, οπότε το API είναι σε παύση. Συνεχίζει μόνο του όταν η συνδρομή ενεργοποιηθεί ξανά· τα κλειδιά παραμένουν έγκυρα. | διορθώστε το αίτημα |
plan_not_entitled | 403 | Το πακέτο του καταστήματος δεν περιλαμβάνει το API για προγραμματιστές. Διατίθεται στα πακέτα που το περιλαμβάνουν. | διορθώστε το αίτημα |
rate_limited | 429 | Το όριο ανά λεπτό για αυτό το κλειδί και scope εξαντλήθηκε. Περιμένετε τα δευτερόλεπτα του Retry-After και ξαναδοκιμάστε· κατανείμετε τις κλήσεις ή αποθηκεύστε αποτελέσματα στην κρυφή μνήμη. | αργότερα |
daily_quota_exceeded | 429 | Το ημερήσιο όριο απαντήσεων για αυτό το κλειδί συμπληρώθηκε (ημέρα UTC). Ξαναδοκιμάστε μετά τα δευτερόλεπτα του Retry-After, δηλαδή μετά την αλλαγή ημέρας. | αργότερα |
too_many_failed_attempts | 429 | Από αυτή τη διεύθυνση ήρθαν πάρα πολλά άκυρα κλειδιά. Περιμένετε τα δευτερόλεπτα του Retry-After και ελέγξτε ποιο κλειδί στέλνει ο κώδικάς σας. | αργότερα |
invalid_request | 422 | Λείπει παράμετρος ή πεδίο σώματος ή είναι εκτός ορίων. Το param δείχνει το πρώτο λάθος· διορθώστε το αίτημα, η επανάληψη δεν βοηθά. | διορθώστε το αίτημα |
invalid_cursor | 422 | Ο δρομέας (cursor) τροποποιήθηκε ή δεν ανήκει σε αυτή τη λίστα. Στείλτε το next_cursor ακριβώς όπως το λάβατε ή ξεκινήστε ξανά χωρίς cursor. | διορθώστε το αίτημα |
product_not_found | 404 | Δεν υπάρχει τέτοιο προϊόν σε αυτό το κατάστημα. Το id προϊόντος άλλου καταστήματος απαντά το ίδιο: ένα κλειδί διαβάζει μόνο το δικό του κατάστημα. | διορθώστε το αίτημα |
idempotency_key_reused | 422 | Αυτό το Idempotency-Key έχει ήδη χρησιμοποιηθεί με διαφορετικό σώμα. Χρησιμοποιήστε νέο κλειδί για άλλη ερώτηση. | διορθώστε το αίτημα |
idempotency_in_progress | 409 | Ένα αίτημα με το ίδιο Idempotency-Key εξακολουθεί να επεξεργάζεται. Περιμένετε λίγο και στείλτε ξανά το ίδιο αίτημα για να πάρετε το αποτέλεσμα. | αργότερα |
request_too_large | 413 | Το σώμα του αιτήματος υπερβαίνει το όριο. Στείλτε μικρότερο σώμα. | διορθώστε το αίτημα |
answer_unavailable | 502 | Η απάντηση δεν μπόρεσε να παραχθεί αυτή τη στιγμή. Ξαναδοκιμάστε σύντομα με το ίδιο Idempotency-Key. | αργότερα |
internal_error | 500 | Κάτι πήγε στραβά από τη δική μας πλευρά. Ξαναδοκιμάστε με παύση· αν επιμένει, στείλτε μας το request_id. | αργότερα |
not_found | 404 | Δεν υπάρχει τέτοιο endpoint. Ελέγξτε τη διαδρομή με την αναφορά· οι διαδρομές ξεκινούν με την έκδοση, /api/v1. | διορθώστε το αίτημα |
method_not_allowed | 405 | Η διαδρομή υπάρχει, αλλά όχι για αυτή τη μέθοδο HTTP. Η κεφαλίδα Allow απαριθμεί τις επιτρεπόμενες. | διορθώστε το αίτημα |
Το type ομαδοποιεί τους κωδικούς: authentication_error, permission_error, invalid_request_error, not_found_error, conflict_error, rate_limit_error, billing_error, api_error. Νέοι κωδικοί μπορεί να εμφανιστούν μέσα στο v1· χειριστείτε έναν άγνωστο code με βάση την κατάσταση HTTP.
Σελιδοποίηση#
Οι λίστες χρησιμοποιούν cursors. Περάστε το next_cursor μιας απάντησης ως cursor στο επόμενο αίτημα μέχρι το next_cursor να γίνει null. Το limit είναι από προεπιλογή 20 και το πολύ 100. Μια σελίδα μπορεί να έχει λιγότερα στοιχεία από το limit όσο το has_more είναι true, γι' αυτό ακολουθήστε το next_cursor αντί να μετράτε. Θεωρήστε το cursor αδιαφανές: ένα τροποποιημένο δίνει 422 invalid_cursor.
Cache και ETag#
Οι απαντήσεις GET φέρουν ETag. Στείλτε το πίσω ως If-None-Match· αν δεν άλλαξε τίποτα, παίρνετε 304 Not Modified χωρίς σώμα, πιο γρήγορα και ελαφριά από νέα λήψη της λίστας. Αποθηκεύστε τις αναγνώσεις καταλόγου σε cache και επαληθεύστε έτσι.
Idempotency και επαναλήψεις#
Το POST /answers δέχεται την κεφαλίδα Idempotency-Key (1 έως 64 χαρακτήρες: γράμματα, ψηφία και . _ : -). Η επανάληψη του ίδιου σώματος εντός 24 ωρών επιστρέφει την πρώτη απάντηση χωρίς δεύτερη κλήση στο μοντέλο και χωρίς κατανάλωση ποσόστωσης· η επανάληψη φέρει Idempotent-Replayed: true. Το ίδιο κλειδί με άλλο σώμα δίνει 422 idempotency_key_reused· όσο το πρώτο αίτημα τρέχει, 409 idempotency_in_progress.
Δημιουργήστε νέο UUID για κάθε ερώτηση χρήστη και επαναχρησιμοποιήστε το μόνο για επαναλήψεις της ίδιας ερώτησης.
Τα σώματα αιτημάτων περιορίζονται σε 16384 byte (413 request_too_large).
Προγράμματα περιήγησης και CORS#
Μια ιστοσελίδα μπορεί να καλεί το API μόνο από προέλευση που είναι στη λίστα του κλειδιού (σχήμα, host και θύρα, π.χ. https://shop.example)· το API στέλνει κεφαλίδες CORS μόνο στις προελεύσεις της λίστας. Ό,τι υπάρχει στον κώδικα μιας σελίδας είναι δημόσιο, άρα ένα κλειδί εκεί μπορεί να αντιγραφεί από όποιον ανοίξει τη σελίδα.
Γι' αυτό για χρήση στον browser δώστε στο κλειδί μόνο τα scopes suggest και similar και λίστα προελεύσεων, και κρατήστε τα κλειδιά answer στον διακομιστή σας.
Αναλυτικά#
Το δικαίωμα analytics:read ανοίγει τα νούμερα του δικού σας καταστήματος: τα ίδια σύνολα, ημερήσια σειρά, κορυφαίες ερωτήσεις και πωλήσεις του βοηθού με το cabinet, υπολογισμένα από τον ίδιο κώδικα. Δώστε το μόνο σε κλειδιά που μένουν στον διακομιστή σας.
Μετρούν μόνο άνθρωποι: όχι bots, όχι οι δικοί μας έλεγχοι, όχι κλήσεις με κλειδιά API ούτε συνομιλίες που αφαίρεσε ο διαχειριστής. Το people μετρά διαφορετικούς επισκέπτες από το σημάδι στο πρόγραμμα περιήγησής τους — όποιος επιστρέφει μετά από τρεις μέρες είναι ένα άτομο, το ίδιο άτομο σε κινητό και λάπτοπ είναι δύο· οι sessions διαρκούν περίπου μία ημέρα· τα βήματα της χοάνης είναι συνεδρίες. Ο συνολικός τζίρος του καταστήματος δεν είναι μέρος του API.
Ένα διάστημα είναι είτε since/until (ISO 8601· χωρίς μετατόπιση, UTC) είτε first_day/last_day, με τις δύο ημέρες να περιλαμβάνονται, κομμένες στη timezone (προεπιλογή: η ζώνη ώρας του καταστήματος ή UTC). Σύγκριση (compare) επιστρέφεται μόνο όταν το ιστορικό του καταστήματος καλύπτει το διάστημα σύγκρισης· αλλιώς το previous είναι null.
Κείμενο που παράγεται από ΤΝ#
Σε μια απάντηση, το say και κάθε why γράφονται από μοντέλο ΤΝ, και η απάντηση το δηλώνει στο αντικείμενο ai: generated, οι διαδρομές JSON στο fields και ένα κείμενο notice. Αν εμφανίζετε αυτά τα κείμενα στους χρήστες σας, πείτε τους ότι παράγονται από ΤΝ· το notice είναι η ελάχιστη διατύπωση που ζητάμε από τις ενσωματώσεις να μεταφέρουν.
Ονόματα, τιμές, διαθεσιμότητα και σύνδεσμοι δεν προέρχονται ποτέ από το μοντέλο. Όταν το miss είναι true, το κατάστημα δεν έχει κάτι κατάλληλο: δείξτε το και μην επινοήσετε προϊόν.
Εκδόσεις#
Η έκδοση είναι μέρος της διαδρομής: /v1. Μέσα στο v1 κάνουμε μόνο αλλαγές συμβατές προς τα πίσω: νέα endpoints, νέες προαιρετικές παραμέτρους, νέα πεδία απάντησης και νέες τιμές απαριθμήσεων (π.χ. νέες τιμές intent). Γράψτε clients που αγνοούν άγνωστα πεδία και υποχωρούν λογικά σε άγνωστες τιμές απαρίθμησης. Μια ασύμβατη αλλαγή θα κυκλοφορούσε μόνο με νέα διαδρομή έκδοσης.
Για μηχανές και βοηθούς ΤΝ#
Η ίδια αναφορά σε μορφή αναγνώσιμη από μηχανές. Εισαγάγετε το έγγραφο OpenAPI στο Postman, στο Insomnia ή σε γεννήτρια κώδικα.