Połącz się z Data API
Data API udostępnia Business Entities jako wersjonowane endpointy REST pod adresem
/api/data/v{version}/{route}, na przykład
/api/data/v1/customers. Administrator decyduje, które encje są wystawione, jakimi
polami posługuje się każda wersja i które role mogą pobierać listy, odczytywać, tworzyć,
aktualizować lub usuwać. Endpoint może też wywoływać Script Module: przyjmuje parametry i
odpowiada tym, co moduł zwraca. Ten przewodnik jest dla osoby, która pisze integrację: jak się
połączyć, jako usługa z kluczem API albo jako użytkownik, który się loguje, i jak wywoływać
endpointy.
Zanim zaczniesz
Poproś administratora przestrzeni roboczej o cztery rzeczy:
- Adres API. To ten sam host, z którym komunikuje się sama aplikacja. Na ekranie API Endpoints panel Try pokazuje go w swojej linii curl.
- Endpoint i wersję, np.
customersw wersji 1. Odpowiada tylko wersja o statusie Active lub Deprecated, wersja Draft nie. - Rolę z dostępem do tego endpointu dla operacji, których potrzebujesz, ustawioną w siatce Who can call it endpointu. Role admin i owner zawsze mogą wywołać wszystko.
- Sposób dostępu z tą rolą: klucz API dla usługi albo konto użytkownika dla osoby lub prostego skryptu.
Do wszystkiego, co działa bez nadzoru, na przykład nocnej synchronizacji, sklepu internetowego czy narzędzia do raportowania, użyj klucza API. Nie wymaga hasła, logowania ani odświeżania, a otwiera dostęp do Data API i do niczego więcej.
Połącz usługę za pomocą klucza API
Administrator tworzy API client na ekranie API Clients: podaje nazwę, role, które klient otrzyma, i opcjonalnie datę wygaśnięcia. Klientowi nie można nadać ról admin ani owner, więc ma dostęp tylko do tego, co na poszczególnych endpointach przyznano jego rolom. Klucz jest pokazywany dokładnie raz, przy tworzeniu klienta. Zapisywany jest tylko jego odcisk, więc nikt nie może go później podejrzeć, nawet administrator.
Wysyłaj klucz jako token bearer przy każdym wywołaniu:
API=https://api.example.com
KEY=ask_api_acme.q7Vt0r2Lk_dP9sXw3eNfH1mA6yZc4uBgJ8oTiR5vWnE
curl "$API/api/data/v1/customers" -H "Authorization: Bearer $KEY" -
Klucz działa tylko pod
/api/data. W każdym innym miejscu produktu jest odrzucany, więc klucz, który wyciekł, nie da dostępu do innych danych aplikacji ani do jej ustawień. -
Jest ważny do chwili, gdy wygaśnie, klient zostanie wyłączony lub usunięty albo administrator
wykona jego rotację, czyli wymieni go na nowy. Każda z tych zmian obowiązuje od
następnego wywołania, które zwraca wtedy
401. - Zmiany wprowadzane przez usługę mają jako autora nazwę klienta, a Business Events widzą go jako użytkownika.
-
Klucz wskazuje swoją przestrzeń roboczą (
ask_api_{workspace}.{secret}), więc nie trzeba jej wybierać. Trzymaj go w magazynie sekretów, nigdy w kodzie.
Przejdź dalej do sekcji Wywołaj endpoint.
Połącz się jako użytkownik: zaloguj się
Użyj dedykowanego konta, a nie konta konkretnej osoby. Token uzyskany przy logowaniu pozwala na wszystko, co ten użytkownik może zrobić w aplikacji, nie tylko na wywoływanie Data API, więc daj kontu przyznaną rolę i nic więcej, a jego hasło trzymaj w magazynie sekretów. Dla usługi lepszym wyborem jest klucz API.
Wyślij e-mail i hasło konta metodą POST na /api/v1/auth/login:
API=https://api.example.com
curl -X POST "$API/api/v1/auth/login" \
-H "Content-Type: application/json" \
-d '{"email": "webshop-sync@example.com", "password": "..."}' Odpowiedź zawiera tokeny:
{
"token": "eyJhbGciOiJSUzI1NiIsImtpZCI6...",
"refreshToken": "q8Zr0dW3...",
"idToken": "eyJhbGciOiJSUzI1NiIsImtpZCI6...",
"expiresIn": 900,
"redirectHost": null
} -
tokento token dostępu. Wysyłaj go przy każdym wywołaniu. Wygasa poexpiresInsekundach, domyślnie po 15 minutach. -
refreshTokenpozwala uzyskać nową parę tokenów bez hasła (zobacz Utrzymuj sesję użytkownika). Domyślnie jest ważny 30 dni i działa dokładnie raz. idTokeniredirectHostsą dla aplikacji w przeglądarce, zignoruj je.
Odrzucone logowanie zwraca 401 z polem code:
invalid_credentials, disabled (konto jest wyłączone) lub
no_tenant (konto nie należy do żadnej aktywnej przestrzeni roboczej). Zbyt wiele
nieudanych prób kończy się odpowiedzią 429 z locked_out. Logowanie jest
też ograniczone do 20 prób na minutę z jednego adresu IP, więc zaloguj się raz i utrzymuj sesję,
zamiast logować się przy każdym wywołaniu.
Wywołaj endpoint
Umieść klucz API lub token dostępu w nagłówku Authorization. Poniżej
$TOKEN oznacza jedno lub drugie. Wywołanie listy zwraca jedną stronę elementów
oraz ich łączną liczbę:
curl "$API/api/data/v1/customers?pageSize=2&sort=name" \
-H "Authorization: Bearer $TOKEN" {
"items": [
{ "id": 1, "name": "Acme", "email": "info@acme.test", "creditLimit": 500 },
{ "id": 2, "name": "Globex", "email": "hello@globex.test", "creditLimit": 50 }
],
"page": 1,
"pageSize": 2,
"totalCount": 3
} Nazwy pól to te, które administrator nadał tej wersji, i nie muszą odpowiadać kolumnom w bazie danych. Odczyt pojedynczego elementu, tworzenie, zmiana i usuwanie wyglądają tak:
# One item
curl "$API/api/data/v1/customers/1" -H "Authorization: Bearer $TOKEN"
# Create: answers 201 with the stored item and a Location header
curl -X POST "$API/api/data/v1/customers" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "Hooli", "email": "hi@hooli.test"}'
# Change some fields
curl -X PATCH "$API/api/data/v1/customers/4" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"email": "sales@hooli.test"}'
# Delete: answers 204
curl -X DELETE "$API/api/data/v1/customers/4" -H "Authorization: Bearer $TOKEN" - PATCH zmienia tylko pola podane w ciele żądania. PUT robi to samo, ale odrzuca ciało, w którym brakuje wymaganego pola.
-
Id zawsze pochodzi z URL-a. Pole
idw ciele żądania tworzenia jest ignorowane, więc utworzenie nigdy nie nadpisze istniejącego elementu. -
Pola tylko do odczytu w ciele żądania są ignorowane, więc możesz odesłać element dokładnie w
takiej postaci, w jakiej go pobrałeś. Pole, którego wersja nie zna, jest odrzucane z kodem
400, co wyłapuje literówki. - Zapisy przez API działają dokładnie tak samo jak zapisy w aplikacji: uruchamiają się Business Events, działa walidacja, a otwarte ekrany się odświeżają.
Wywołaj Script Module
Niektóre endpointy uruchamiają Script Module zamiast udostępniać wiersze encji, do pracy, która wykracza poza odczyt lub zapis: wyceny zamówienia, rezerwacji terminu, raportu. Każda wersja takiego endpointu odpowiada na jedną metodę, a dokument OpenAPI mówi, na którą: POST przyjmuje parametry jako obiekt JSON w ciele żądania, GET w parametrach URL-a.
# A version called with POST: the parameters as a JSON object
curl -X POST "$API/api/data/v1/quote" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"quantity": 3, "express": true}'
# A version called with GET: the parameters in the query string
curl "$API/api/data/v1/planner-week?weekStart=2026-09-21" \
-H "Authorization: Bearer $TOKEN" Odpowiedzią jest to, co zwraca moduł, w formacie JSON:
{
"quantity": 3,
"total": 172.5,
"deliveryDate": "2026-09-28"
} -
Nazwy parametrów to te, które administrator nadał wersji. Każda wartość jest sprawdzana
względem swojego typu, zanim moduł się uruchomi: liczba całkowita, liczba, true lub false,
data z godziną lub bez (
2026-09-25,2026-09-25T14:30:00Z) albo tekst. Wartość złego typu, parametr, którego wersja nie zna, i brakujący parametr wymagany dają400;nullliczy się jako pominięty. -
Moduł, który nic nie zwraca, odpowiada
204 No Content. Moduł, który zawiedzie, odpowiada500z własnym komunikatem modułu wdetail. - Wywołanie wymaga roli, której na endpoincie przyznano operację Call. Moduł, który administrator oznaczył jako admin only, odpowiada tylko rolom admin i owner, więc klucz API nigdy do niego nie dotrze.
- Moduł działa naprawdę, dokładnie tak jak wtedy, gdy uruchamia go aplikacja: to, co zapisuje, uruchamia Business Events, a poczta, którą wysyła, naprawdę wychodzi.
-
Wywołanie inną metodą albo na ścieżce elementu, takiej jak
/quote/1, daje405, a nagłówekAllowpodaje metodę, której należy użyć.
Utrzymuj sesję użytkownika
Dotyczy to tylko zalogowanego użytkownika, klucz API niczego takiego nie potrzebuje. Zanim
token dostępu wygaśnie albo gdy wywołanie zwróci 401, wymień token odświeżania na
nową parę:
curl -X POST "$API/api/v1/auth/refresh" \
-H "Content-Type: application/json" \
-d '{"refreshToken": "q8Zr0dW3..."}' Odpowiedź ma ten sam kształt co przy logowaniu, z nowym tokenem odświeżania. Zapisz go i wyrzuć stary: token odświeżania działa tylko raz. Jeśli po upływie minuty ponownie użyjesz już zużytego tokenu, zostanie to potraktowane jako kradzież i cała sesja się zakończy, a potem trzeba będzie zalogować się od nowa. Dlatego daj każdemu procesowi lub workerowi własną sesję i nigdy nie współdziel jednego tokenu odświeżania między nimi.
Odświeżenie zwraca 401, gdy sesja się zakończyła: wygasła, konto zostało wyłączone
lub usunięte z przestrzeni roboczej albo nastąpiło wylogowanie. Wtedy zaloguj się ponownie.
Zmiany ról trafiają do tokenu przy następnym odświeżeniu, więc odebrana rola przestaje działać
w ciągu 15 minut. Aby samodzielnie zakończyć sesję:
curl -X POST "$API/api/v1/auth/logout" \
-H "Content-Type: application/json" \
-d '{"refreshToken": "q8Zr0dW3..."}' Konto w więcej niż jednej przestrzeni roboczej
Logowanie wybiera dla sesji jedną przestrzeń roboczą: tę, do której należy wywoływany adres,
jeśli konto jest jej członkiem, a w przeciwnym razie tę, której używało ostatnio. Dlatego
dedykowane konto powinno należeć tylko do jednej przestrzeni roboczej. Jeśli należy do kilku,
pobierz ich listę i przełącz się, podając tenantId tej, której potrzebujesz:
# The workspaces this account belongs to
curl "$API/api/v1/auth/tenants" -H "Authorization: Bearer $TOKEN"
# A new token pair for one of them
curl -X POST "$API/api/v1/auth/switch-tenant" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"tenantId": "3f1c2a9e-..."}' Przełączenie zwraca nową parę tokenów dla tej przestrzeni roboczej, dalej pracuj z nią tak jak po zalogowaniu.
Filtrowanie, sortowanie i stronicowanie
# Customers whose name contains "acme", highest credit limit first
curl -G "$API/api/data/v1/customers" \
-H "Authorization: Bearer $TOKEN" \
--data-urlencode "filter[name][like]=acme" \
--data-urlencode "filter[creditLimit][gte]=100" \
--data-urlencode "sort=-creditLimit" \
--data-urlencode "page=2" \
--data-urlencode "pageSize=50" | Parametr | Znaczenie |
|---|---|
page | Numer strony, liczony od 1. |
pageSize | Liczba elementów na stronę, domyślnie 50. Każda wersja ustala maksimum (100, o ile administrator go nie zmienił), a prośba o więcej kończy się kodem 400. |
sort | Jedno pole, poprzedzone - dla kolejności malejącej. Bez tego parametru najpierw najnowsze. |
search | Tekst dopasowywany do każdego pola, które zwraca wersja. |
filter[field] | Równe podanej wartości. |
filter[field][op] | Porównanie z użyciem operatora, patrz niżej. Przy kilku filtrach wszystkie muszą być spełnione. |
| Operator | Dopasowuje |
|---|---|
eq, ne | Równe, różne. |
gt, gte, lt, lte | Większe lub mniejsze niż. Liczby, daty i tekst. |
like, startswith, endswith | Tekst, który zawiera wartość, zaczyna się od niej lub na niej kończy, bez rozróżniania wielkości liter. Tylko pola tekstowe. |
in | Dowolna wartość z listy rozdzielonej przecinkami: filter[id][in]=1,2,3. |
null | true dla pustych wartości, false dla wypełnionych. |
Wartości są sprawdzane pod kątem typu pola, więc filter[creditLimit]=lots daje
400 ze wskazaniem pola. Filtrować, sortować i przeszukiwać można tylko pola, które
zwraca wersja, a nieznany parametr jest odrzucany, a nie ignorowany, więc literówka nigdy po
cichu nie zwróci wszystkiego. Parametry zaczynające się od _ są ignorowane, więc
możesz ich użyć do omijania cache.
Wersje
Wersja jest częścią ścieżki, a kilka wersji jednego endpointu może działać równolegle. Opublikowana wersja nigdy nie zmienia się w sposób, który psuje integrację: pola nigdy nie są usuwane ani przemianowywane i nic nie staje się wymagane. Tak samo wersja, która wywołuje Script Module, zachowuje swoją metodę i parametry i zyskuje tylko parametry opcjonalne. Takie zmiany trafiają do nowej wersji.
- Wersje Active i Deprecated odpowiadają.
- Wersja, która nie istnieje albo wciąż ma status Draft, zwraca
404i wymienia wersje, które istnieją. - Wersja Retired zwraca
410 Gonei wskazuje tę, na którą należy przejść.
Każda odpowiedź podaje, jakie wersje istnieją. Wersja Deprecated dodatkowo to zaznacza i mówi, kiedy zniknie:
HTTP/1.1 200 OK
api-supported-versions: 1, 2
api-deprecated-versions: 1
Deprecation: @1788220800
Sunset: Thu, 31 Dec 2026 00:00:00 GMT
Link: <https://api.example.com/api/data/v2/customers>; rel="successor-version" Deprecation to moment, w którym wersja dostała status Deprecated (czas Unix),
Sunset to data, od której przestanie odpowiadać, jeśli administrator ją ustawił, a
Link wskazuje następną wersję. Zapisywanie ostrzeżenia w logach za każdym razem,
gdy pojawi się Deprecation, to najprostszy sposób, żeby dowiedzieć się o tym na
czas.
Błędy
Odmowa z Data API to standardowy dokument Problem Details (RFC 7807), którego pole
detail mówi, co było nie tak:
HTTP/1.1 403 Forbidden
Content-Type: application/problem+json
{
"title": "Forbidden",
"status": 403,
"detail": "None of your roles may Delete on 'customers'."
}
Jeden wyjątek: gdy walidacja Business Event odrzuci zapis, ciało odpowiedzi 422
ma postać { "message": "...", "errorColumns": [...] } i wskazuje błędne
pola nazwami kolumn z samej bazy danych.
| Status | Znaczenie |
|---|---|
400 | Żądanie jest niepoprawne: nieznane pole lub parametr, wartość złego typu, brak wymaganego pola. |
401 | Brak tokenu lub klucza albo nie jest on już ważny. Użytkownik odświeża token i ponawia żądanie; klucz API wygasł, został wymieniony w ramach rotacji albo jego klient został wyłączony lub usunięty. |
403 | Żadna z ról konta nie pozwala na tę operację na tym endpoincie. |
404 | Nie ma takiego endpointu, wersji ani elementu. |
405 | Ta wersja nie oferuje tej operacji, np. usuwania, albo endpoint Script Module wywołano inną metodą. |
409 | Konflikt danych: taka unikalna wartość już istnieje albo inne rekordy wciąż odwołują się do tego. |
410 | Wersja została wycofana (Retired). |
422 | Reguła biznesowa lub reguła tabeli odrzuciła wartości. |
429 | Zbyt wiele żądań. Odczekaj chwilę i spróbuj ponownie. |
500 | Script Module za endpointem zawiódł; detail zawiera jego komunikat. |
Opis OpenAPI
GET /api/data/openapi.json, wywołany z twoim tokenem, zwraca dokument OpenAPI 3
opisujący dokładnie te wersje i operacje, z których może korzystać twoje konto, wraz z każdym
polem i jego typem. Zaimportuj go do Postmana lub Insomnii albo wygeneruj z niego typowanego
klienta. Pobierz go ponownie, gdy administrator opublikuje nową wersję.
Przykłady w Pythonie
Z kluczem API wystarczy sam nagłówek:
import os
import requests
API = os.environ["ARCHESTACK_API"]
session = requests.Session()
session.headers["Authorization"] = f"Bearer {os.environ['ARCHESTACK_API_KEY']}"
r = session.get(f"{API}/api/data/v1/customers", params={"pageSize": 100}, timeout=30)
r.raise_for_status()
for customer in r.json()["items"]:
print(customer["id"], customer["name"])
Po zalogowaniu jako użytkownik trzeba zadbać o sesję. Ten przykład loguje się, odświeża token
minutę przed jego wygaśnięciem, radzi sobie z 401, odczytuje wszystkie strony i
tworzy element. Adres i dane logowania umieść w zmiennych środowiskowych.
import os
import time
import requests
API = os.environ["ARCHESTACK_API"] # e.g. https://api.example.com
EMAIL = os.environ["ARCHESTACK_EMAIL"]
PASSWORD = os.environ["ARCHESTACK_PASSWORD"]
class DataApi:
"""One signed-in session. Give every process or worker its own."""
def __init__(self):
self.token = None
self.refresh_token = None
self.expires_at = 0.0
def _keep(self, body):
self.token = body["token"]
self.refresh_token = body["refreshToken"] # always replace it: each one works once
self.expires_at = time.time() + body["expiresIn"] - 60
def sign_in(self):
r = requests.post(f"{API}/api/v1/auth/login",
json={"email": EMAIL, "password": PASSWORD}, timeout=30)
r.raise_for_status()
self._keep(r.json())
def refresh(self):
r = requests.post(f"{API}/api/v1/auth/refresh",
json={"refreshToken": self.refresh_token}, timeout=30)
if r.status_code == 401: # the session ended: start a new one
return self.sign_in()
r.raise_for_status()
self._keep(r.json())
def call(self, method, path, **kwargs):
if self.token is None:
self.sign_in()
elif time.time() >= self.expires_at:
self.refresh()
r = self._send(method, path, **kwargs)
if r.status_code == 401: # expired early or revoked: refresh once and retry
self.refresh()
r = self._send(method, path, **kwargs)
return r
def _send(self, method, path, **kwargs):
headers = {"Authorization": f"Bearer {self.token}"}
return requests.request(method, f"{API}/api/data{path}",
headers=headers, timeout=30, **kwargs)
api = DataApi()
# Every page of customers
page = 1
while True:
r = api.call("GET", "/v1/customers", params={"page": page, "pageSize": 100})
r.raise_for_status()
body = r.json()
for customer in body["items"]:
print(customer["id"], customer["name"])
if page * body["pageSize"] >= body["totalCount"]:
break
page += 1
# Create one
r = api.call("POST", "/v1/customers", json={"name": "Hooli", "email": "hi@hooli.test"})
if r.status_code == 201:
print("created", r.json()["id"])
else:
print("refused:", r.json().get("detail")) Środowiska trial: API mogą tam wywoływać tylko konto właściciela trialu oraz każdy API client, którego ten właściciel utworzy.
Dokąd dalej
- Business Entities - z czego czyta endpoint i dlaczego encja złączona z tabelą jeden-do-wielu zwraca jeden element na każdy złączony wiersz.
- User Management - utwórz konto integracji i jego rolę.