Skip to main content

Tworzenie zamówienia "create-order"

Przegląd

Endpoint POST /create-order tworzy zamówienie klienta na podstawie listy produktów. AMPER sam wylicza ceny – cenę klienta z jego cennika i najlepszą dostępną promocję – i zwraca je w odpowiedzi. W trybie playground można tylko policzyć ceny, bez tworzenia zamówienia.

Przed wywołaniem trzeba uzyskać token JWT przez endpoint /auth/. Klucz API (api_key) z API zewnętrznego tutaj nie działa.


1. Autoryzacja – uzyskanie tokena

1.1 Pobranie tokena (logowanie)

POST /auth/
Content-Type: application/json

Body żądania:

{
  "username": "login_uzytkownika",
  "password": "haslo"
}

Przykład (curl):

curl -X POST https://<host>/auth/ \
  -H "Content-Type: application/json" \
  -d '{"username": "jan.kowalski", "password": "tajnehaslo"}'

Odpowiedź (200 OK):

{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cC...",
  "expires_in": 300,
  "refresh_expires_in": 1800,
  "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5c...",
  "token_type": "Bearer",
  "not-before-policy": 0,
  "session_state": "abc123...",
  "scope": "amper",
  "amper-company-assigned": "amper-xyz"
}
Pole Opis
access_token token JWT do autoryzacji żądań API
expires_in czas ważności tokena w sekundach (zwykle 300 s = 5 min)
refresh_token token do odświeżenia sesji bez ponownego logowania
refresh_expires_in czas ważności refresh tokena w sekundach
amper-company-assigned identyfikator instalacji AMPER, do której należy konto

Konto musi należeć do instalacji AMPER, do której się logujesz – inaczej odpowiedź to 403.


1.2 Odświeżenie tokena

Gdy access_token wygaśnie, użyj refresh_token zamiast ponownie logować użytkownika.

POST /auth/token-refresh/
Content-Type: application/json

Body żądania:

{
  "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5c..."
}

Przykład (curl):

curl -X POST https://<host>/auth/token-refresh/ \
  -H "Content-Type: application/json" \
  -d '{"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5c..."}'

Odpowiedź: taki sam format jak przy logowaniu – nowy access_token i refresh_token. Wygasły refresh token daje odpowiedź 400 z błędem invalid_grant – wtedy zaloguj się ponownie przez /auth/.


2. Tworzenie zamówienia

Endpoint

POST /create-order
Authorization: Bearer <access_token>
Content-Type: application/json

Wymagane uprawnienia

Token musi należeć do użytkownika z zakresem B2B (konto klienta) lub TRANSLATOR (konto integracji ERP).


2.1 Parametry żądania

Body żądania (JSON):

Pole Typ Wymagane Opis
customer_id integer Tak* ID klienta w AMPER
customer_external_id string Tak* ID klienta w systemie ERP (alternatywa dla customer_id)
lines array Tak linie zamówienia (patrz niżej)
playground boolean Nie true – tylko wyliczenie cen, bez zapisu zamówienia (domyślnie false)
description string Nie uwagi do zamówienia
recipient_order_number string lub integer Nie własny numer zamówienia odbiorcy; trafia do uwag jako pierwsza linia: Własny identyfikator zamówienia: <numer>
shipment_type_id integer Nie ID rodzaju wysyłki – listę zwraca /external/v1/shipment-types/

* Wymagane jest podanie customer_id lub customer_external_id.

Pola obiektu w tablicy lines:

Pole Typ Wymagane Opis
product_id integer Tak* ID produktu w AMPER
product_external_id string Tak* ID produktu w systemie ERP
ean string Tak* kod EAN produktu albo opakowania zbiorczego – dla EAN-u opakowania ilość jest przeliczana na jednostki podstawowe
quantity decimal Tak ilość w jednostce podstawowej (zaokrąglana w górę do kroku jednostki produktu)
suggested_price decimal lub null Tak pole musi wystąpić, ale AMPER nie używa go do wyceny (patrz niżej)
promotion_id integer Nie ID promocji – AMPER sprawdza wtedy tylko tę jedną promocję

* Linia musi zawierać product_id, product_external_id lub ean (sprawdzane w tej kolejności).

Nie wysyłaj pola order_line_promotion_id. To pole wewnętrzne – linia, która je zawiera, jest pomijana i nie trafia do zamówienia.

Zamówienia producenckie (tylko konto Translatora)

Zamówienie złożone przez kanał sprzedaży producenta (EDI itp.) w imieniu klienta. Pola są brane pod uwagę tylko wtedy, gdy wysyła je konto z zakresem TRANSLATOR; dla innych kont są ignorowane.

Pole Typ Wymagane Opis
is_producer_order boolean Nie true – zamówienie producenckie
producer_order_number string lub integer Tak, gdy is_producer_order numer zamówienia u producenta (najwyżej 128 znaków)
document_provider_short_name string Nie skrót dostawcy dokumentu (producenta)

Ponowne wysłanie zamówienia o tym samym numerze i dostawcy nie tworzy duplikatu – odpowiedź to 200 OK z "already_exists": true i ID istniejącego zamówienia.


2.2 Jak AMPER wylicza ceny

  • Cena linii to cena promocyjna (given_price), jeśli warunki promocji są spełnione, a w przeciwnym razie cena klienta z jego cennika (customer_price). Wartość suggested_price z żądania nie wpływa na cenę.
  • Promocje są wybierane automatycznie: AMPER szuka najkorzystniejszej promocji typu stała cena, której warunki spełnia całe zamówienie. Podanie promotion_id zawęża wybór do tej jednej promocji.
  • Ilość jest zaokrąglana w górę do kroku jednostki produktu – np. przy kroku 5 zamówienie 7 szt. zostanie zaokrąglone do 10.
  • Linie są pomijane, gdy produkt nie istnieje, nie jest dostępny dla klienta albo klient nie ma wymaganej koncesji (np. na alkohol). Pominięte linie nie pojawiają się w odpowiedzi.

2.3 Przykłady żądań

Przykład z wewnętrznymi ID:

curl -X POST https://<host>/create-order \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cC..." \
  -H "Content-Type: application/json" \
  -d '{
    "customer_id": 42,
    "lines": [
      {
        "product_id": 101,
        "quantity": 10,
        "suggested_price": null
      },
      {
        "product_id": 205,
        "quantity": 5,
        "suggested_price": null,
        "promotion_id": 7
      }
    ],
    "description": "Zamówienie testowe"
  }'

Przykład z zewnętrznymi ID i EAN-em (integracja ERP):

curl -X POST https://<host>/create-order \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cC..." \
  -H "Content-Type: application/json" \
  -d '{
    "customer_external_id": "ERP-KLIENT-0042",
    "recipient_order_number": "ZAM/2026/10/0153",
    "lines": [
      {
        "product_external_id": "SKU-ABC-001",
        "quantity": 10,
        "suggested_price": null
      },
      {
        "ean": "5901234123457",
        "quantity": 2,
        "suggested_price": null
      }
    ]
  }'

Przykład trybu playground (tylko wyliczenie cen):

curl -X POST https://<host>/create-order \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cC..." \
  -H "Content-Type: application/json" \
  -d '{
    "customer_id": 42,
    "playground": true,
    "lines": [
      {
        "product_id": 101,
        "quantity": 10,
        "suggested_price": null
      }
    ]
  }'

2.4 Odpowiedź

Sukces – 201 Created:

{
  "order_id": 12345,
  "lines": [
    {
      "product_id": 101,
      "product_external_id": "SKU-ABC-001",
      "quantity": 10,
      "suggested_price": null,
      "default_price": 100.00,
      "customer_price": 95.00,
      "given_price": 90.00,
      "promotion": {
        "price": 90.00,
        "promotion_min_order_quantity": 5,
        "promotion_condition_item_id": 123,
        "promotion_condition_id": 456,
        "relation_id": 789,
        "promotion_name": "Letnia wyprzedaż",
        "promotion_id": 999,
        "promotion_url": "https://<adres-b2b>/promotions/999/"
      }
    }
  ]
}
Pole Opis
order_id ID utworzonego zamówienia; 0, gdy playground=true, gdy żadna linia nie została przyjęta albo gdy nie znaleziono klienta
lines przyjęte linie z wyliczonymi cenami
lines[].default_price cena katalogowa netto
lines[].customer_price cena netto z cennika klienta
lines[].given_price cena promocyjna netto; 0, gdy żadna promocja nie ma zastosowania
lines[].promotion zastosowana promocja albo null

Utworzone zamówienie ma status Oczekujące (Pending) i jest eksportowane do ERP jak każde inne. Zamówienie producenckie może od razu trafić do przedstawiciela handlowego klienta jako dokument do sprawdzenia – zależy to od konfiguracji instalacji.

Uwaga: kod 201 nie gwarantuje, że zamówienie powstało. Zawsze sprawdzaj order_id – wartość 0 oznacza, że zamówienia nie utworzono.


3. Kody odpowiedzi

Kod Endpoint Opis
200 OK /auth/, /auth/token-refresh/ token wydany
200 OK /create-order zamówienie producenckie już istnieje (already_exists: true)
201 Created /create-order żądanie przyjęte – sprawdź order_id
400 Bad Request /create-order błędny recipient_order_number (musi być tekstem lub liczbą) albo błędne pola zamówienia producenckiego
400 Bad Request /auth/token-refresh/ refresh token wygasł lub jest nieprawidłowy
401 Unauthorized /create-order brak lub nieprawidłowy nagłówek Authorization
403 Forbidden /auth/ błędny login lub hasło, konto wyłączone albo konto spoza tej instalacji
403 Forbidden /create-order token ważny, ale bez wymaganego zakresu (B2B lub TRANSLATOR)
403 Forbidden /auth/token-refresh/ brak pola refresh_token
404 Not Found /auth/ pusty login lub hasło
422 Unprocessable Entity /create-order instalacja nie jest skonfigurowana do zamówień producenckich – nic nie utworzono, wyślij zamówienie ponownie później

4. Pełny przepływ integracji

1. POST /auth/               → otrzymujesz access_token + refresh_token
         │
         ▼
2. POST /create-order        → zamówienie zostaje utworzone (sprawdź order_id)
   Authorization: Bearer <access_token>
         │
         ▼
3. Gdy access_token wygaśnie (expires_in sekund):
   POST /auth/token-refresh/ → otrzymujesz nowy access_token
   { "refresh_token": "..." }

Rekomendowane podejście w kliencie:

  • Przechowuj access_token i refresh_token w pamięci sesji.
  • Przed każdym żądaniem sprawdzaj, czy token nie wygasł (expires_in).
  • Po odpowiedzi 401 odśwież token przez /auth/token-refresh/ i ponów żądanie.
  • Gdy refresh_token również wygaśnie, ponownie pobierz token przez /auth/.
  • Przy ponawianiu zamówień producenckich wysyłaj ten sam producer_order_number – AMPER nie utworzy duplikatu.