API

PrestaBlog udostępnia REST API, które pozwala narzędziom zewnętrznym (skryptom, aplikacjom firm trzecich lub agentom AI) tworzyć i zarządzać artykułami oraz kategoriami bloga bez korzystania z panelu administracyjnego. Funkcja dostępna od PrestaShop 8 jest przeznaczona zarówno dla osób nietechnicznych (przez agenta AI), jak i dla programistów, którzy potrzebują bezpośredniej integracji.

Konfiguracja API

Na początek API musi zostać włączone i skonfigurowane w panelu administracyjnym.

Otwórz konfigurację:
Modules > PrestaBlog > Configuration > Tools > API

Dostępne ustawienia:

  • Włącz API: główny przełącznik. Gdy jest wyłączony, API nie odpowiada na żadne żądania.
  • Klucz API: kliknij „Wygeneruj nowy klucz”. Klucz jest wyświetlany tylko raz — skopiuj go od razu, później nie będzie dostępny. Zapisywany jest jedynie jego odcisk kryptograficzny (SHA-256). Jeśli zgubisz klucz, wygeneruj nowy.
  • Automatycznie aktywuj nowe artykuły: określa, czy artykuły tworzone przez API mają być publikowane od razu, czy zapisywane jako szkice, gdy żądanie nie podaje tego parametru.
  • Limit zapytań: maksymalna liczba zapytań na minutę dla jednego adresu IP (domyślnie: 60).
  • Zabezpieczenia obrazów: blokuje pobieranie obrazów z prywatnych/wewnętrznych zakresów IP. Zalecane dla instalacji wystawionych do Internetu.
  • Za proxy: włącz, jeśli sklep działa za Cloudflare, reverse proxy lub CDN, aby poprawnie wykrywać IP klienta.
  • Poziom logów: Brak wyłącza logowanie. Bezpieczeństwo zapisuje nieudane próby uwierzytelnienia i blokady. Debug zapisuje wszystkie żądania (używaj tymczasowo do diagnostyki).
  • Dozwolone źródła CORS: tylko jeśli aplikacja webowa na innej domenie ma wywoływać API z poziomu przeglądarki. W większości przypadków pozostaw puste.

Uprawnienia API

Sekcja Uprawnienia API pozwala precyzyjnie ograniczyć, co może robić klucz API. Każdą operację można włączyć lub wyłączyć niezależnie — zarówno dla artykułów, jak i kategorii.

  • Zezwól na tworzenie artykułów / kategorii: pozwala na żądania POST tworzące nowe treści.
  • Zezwól na modyfikację artykułów / kategorii: pozwala na żądania PUT aktualizujące istniejące treści.
  • Zezwól na usuwanie artykułów / kategorii: pozwala na żądania DELETE. Wyłącz, jeśli chcesz zapobiec przypadkowym usunięciom przez agenta AI lub skrypt zewnętrzny.
Dobra praktyka Nadaj tylko te uprawnienia, które są absolutnie potrzebne. Jeśli używasz API wyłącznie do publikowania artykułów, wyłącz modyfikację i usuwanie, aby zmniejszyć ryzyko w przypadku przejęcia klucza.
Bezpieczeństwo

API wymaga HTTPS. W przypadku HTTP wszystkie żądania są odrzucane (z wyjątkiem localhost do testów lokalnych). Nigdy nie udostępniaj klucza API.

Użycie przez agenta AI (zalecane)

Nie jesteś programistą albo nie chcesz pisać kodu? Najprostsza metoda to użycie agenta AI, np. Claude, poprzez protokół MCP (Model Context Protocol). Agent wie, jakie wywołania wykonać, obsługuje uwierzytelnianie i rozumie polecenia w języku naturalnym.

Uwaga: Claude i Windsurf to przykłady integracji MCP. Istnieje wiele innych kompatybilnych narzędzi i środowisk, ale nie da się opisać wszystkich w tym miejscu.

1. Włącz API i wygeneruj klucz

W panelu administracyjnym PrestaBlog: Tools > API. Włącz API, kliknij „Wygeneruj nowy klucz” i skopiuj wyświetlony klucz — później nie będzie już dostępny.

2. Zbuduj URL połączenia MCP

URL połączenia ma format:

https://prestablog-mcp.prestablog.workers.dev/mcp?key=YOUR_KEY&shop=https://your-shop.com

Zastąp YOUR_KEY wygenerowanym kluczem, a https://your-shop.com adresem URL Twojego sklepu.

Nie myl tego z „API URL”, która jest innym adresem używanym do bezpośrednich wywołań.

Ważne

URL zawiera klucz API. Traktuj go jak hasło: nie udostępniaj i nie publikuj.

3. Konfiguracja w Claude

W Claude kliknij w lewym górnym rogu Customize, następnie Connectors,
u góry kolumny, która się pojawi, kliknij przycisk +, a potem Add a custom connector.

Uzupełnij:

  • Name: dowolna nazwa (np. PrestaBlog API)
  • URL: URL połączenia MCP z kroku 2

Zatwierdź. Claude ma teraz dostęp do Twojego bloga i może tworzyć, edytować oraz usuwać artykuły i kategorie bezpośrednio.

Przykłady poleceń dla Claude:

  • „Utwórz artykuł o letnich butach w kategorii Moda”
  • „Wyświetl 10 ostatnio opublikowanych artykułów”
  • „Zmień tytuł artykułu 42”
  • „Utwórz nową kategorię Aktualności z tym opisem”
  • „Usuń kategorię 5”

Wbudowana dokumentacja

Pełna dokumentacja jest wbudowana w konektor MCP. Claude odczytuje ją automatycznie — nie trzeba nic więcej konfigurować.

4. Konfiguracja w Windsurf

W Windsurf otwórz panel Cascade, kliknij ... w prawym górnym rogu panelu, a następnie ikonę MCPs (ostatnia ikona w prawym dolnym rogu menu). Otworzy się okno edycji. Dodaj poniższą konfigurację po poprawnym wygenerowaniu URL (zobacz krok 2):

{
  "mcpServers": {
    "prestablog": {
      "serverUrl": "https://prestablog-mcp.prestablog.workers.dev/mcp?key=YOUR_KEY&shop=https://your-shop.com"
    }
  }
}

Zapisz. Cascade wyświetli na dole panelu 1 MCP, co potwierdza aktywne połączenie.

Przykłady poleceń dla Cascade:

  • „Utwórz artykuł o letnich butach w kategorii Moda”
  • „Wyświetl 10 ostatnio opublikowanych artykułów”
  • „Zmień tytuł artykułu 42”
  • „Utwórz nową kategorię Aktualności z tym opisem”
  • „Usuń kategorię 5”

Wbudowana dokumentacja

Pełna dokumentacja jest wbudowana w konektor MCP. Cascade odczytuje ją automatycznie — nie trzeba nic więcej konfigurować.

Uwierzytelnianie (REST)

Każde żądanie musi zawierać klucz API w nagłówku HTTP. Obsługiwane są dwa formaty:

Authorization: Bearer YOUR_API_KEY

lub

X-Api-Key: YOUR_API_KEY

Dobra praktyka

Nigdy nie przesyłaj klucza jako parametru URL, aby nie pojawiał się w logach serwera.

Automatyczna blokada: po 5 nieudanych próbach uwierzytelnienia z tego samego IP, adres zostaje zablokowany na 1 godzinę. Czas ten można zmienić w ustawieniach API.

Artykuły

Lista artykułów

GET /prestablog-api/articles

Zwraca stronicowaną listę artykułów. Dostępne parametry: lang (ID języka), page, per_page (max 100), active (1 = tylko opublikowane), category (ID kategorii), search (wyszukiwanie w tytule), sort (date, title, id), order (asc, desc).

curl -X GET "https://your-shop.com/prestablog-api/articles?lang=1&page=1&per_page=10" \
  -H "Authorization: Bearer YOUR_KEY"

Szczegóły artykułu

GET /prestablog-api/articles/{id}

Zwraca wszystkie dane artykułu: pola wielojęzyczne, kategorie, powiązane produkty, powiązane artykuły oraz spis treści.

curl -X GET "https://your-shop.com/prestablog-api/articles/18" \
  -H "Authorization: Bearer YOUR_KEY"

Tworzenie artykułu

POST /prestablog-api/articles

Minimalny przykład:

curl -X POST "https://your-shop.com/prestablog-api/articles" \
  -H "Authorization: Bearer YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "languages": {
      "1": {
        "title": "Mój artykuł",
        "content": "<h2>Wprowadzenie</h2><p>Treść artykułu.</p>"
      }
    },
    "categories": [1],
    "active": true
  }'

Pełny przykład z obrazem, wielojęzycznością i metadanymi:

{
  "languages": {
    "1": {
      "title": "Mój artykuł",
      "introduction": "Krótki tekst wyświetlany na listach",
      "content": "<h2>Sekcja</h2><p>Pełna treść HTML.</p>",
      "meta_title": "Mój artykuł - tytuł SEO",
      "meta_description": "Opis dla wyszukiwarek",
      "meta_keywords": "słowo1, słowo2",
      "link_rewrite": "moj-artykul"
    },
    "2": {
      "title": "My article",
      "introduction": "Short text displayed in listings",
      "content": "<h2>Section</h2><p>Full HTML content.</p>"
    }
  },
  "categories": [2, 5],
  "active": true,
  "date": "2026-06-15 09:00:00",
  "enable_toc": true,
  "author_id": 1,
  "image": {
    "url": "https://example.com/image.jpg"
  }
}

Dostępne pola:

PoleTypOpis
languagesobjectTreść per język, indeksowana ID języka PrestaShop. Wymagane przy tworzeniu
languages.{id}.titletextTytuł artykułu. Wymagane dla każdego języka
languages.{id}.introductionHTMLKrótki tekst wyświetlany na listach oraz na początku artykułu
languages.{id}.contentHTMLTreść artykułu
languages.{id}.meta_titletextTag title SEO (max 500 znaków)
languages.{id}.meta_descriptiontextMeta description (max 500 znaków)
languages.{id}.meta_keywordstextSłowa kluczowe SEO
languages.{id}.link_rewritetextSlug URL. Jeśli brak, generowany automatycznie z tytułu
categoriesarray of IDsKategorie PrestaBlog do powiązania
productsarray of IDsPowiązane produkty PrestaShop
related_articlesarray of IDsPowiązane artykuły
activebooleanNatychmiastowa publikacja. Jeśli brak, używa ustawienia „Automatycznie aktywuj”
datedatetimeData publikacji w formacie YYYY-MM-DD HH:MM:SS. Przyszła data planuje publikację
enable_tocbooleanWłącza spis treści generowany z tagów h2/h3 w treści
author_idintegerID autora PrestaBlog
image.urlURLGłówny obraz do pobrania z zewnętrznego URL
id_shopintegerID sklepu (tylko multishop). Domyślnie: bieżący sklep

Edycja artykułu

PUT /prestablog-api/articles/{id}

Aktualizacja częściowa: modyfikowane są wyłącznie pola obecne w żądaniu. Pola nieprzesłane zachowują dotychczasowe wartości. W przypadku języków aktualizowane są tylko te uwzględnione w payload.

curl -X PUT "https://your-shop.com/prestablog-api/articles/18" \
  -H "Authorization: Bearer YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "active": false,
    "languages": {
      "1": {
        "title": "New title"
      }
    }
  }'

Usuwanie artykułu

DELETE /prestablog-api/articles/{id}

Usuwa artykuł i wszystkie powiązane dane: obrazy (wszystkie warianty), kategorie, powiązane produkty i powiązane artykuły.

curl -X DELETE "https://your-shop.com/prestablog-api/articles/18" \
  -H "Authorization: Bearer YOUR_KEY"

Obraz artykułu

POST /prestablog-api/articles/{id}/image

Dostępne są trzy metody — w zależności od Twojego kontekstu:

Zdalny URL (obraz hostowany w Internecie):

curl -X POST "https://your-shop.com/prestablog-api/articles/18/image" \
  -H "Authorization: Bearer YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com/image.jpg"}'

Plik lokalny (upload multipart):

curl -X POST "https://your-shop.com/prestablog-api/articles/18/image" \
  -H "Authorization: Bearer YOUR_KEY" \
  -F "file=@/path/to/image.jpg"

Base64 (awaryjnie):

Uwaga: base64 jest bardzo duże i może być trudne w użyciu dla złożonych obrazów. Jeśli to możliwe, preferuj upload przez zdalny URL.

curl -X POST "https://your-shop.com/prestablog-api/articles/18/image" \
  -H "Authorization: Bearer YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"base64": "/9j/4AAQSkZJRg...", "filename": "photo.jpg"}'

Przez MCP (Claude)

Przez MCP dostępne są tylko metody URL i base64. Aby wysłać plik lokalny przez Claude, najpierw zakoduj go do base64.

Kategorie

API pozwala tworzyć, przeglądać, edytować i usuwać kategorie tak samo jak w przypadku artykułów.

Lista kategorii

GET /prestablog-api/categories

Domyślnie zwraca kategorie w formie drzewa. Użyj flat=1 dla listy płaskiej, active=1 tylko dla aktywnych, lang dla języka.

curl -X GET "https://your-shop.com/prestablog-api/categories?lang=1" \
  -H "Authorization: Bearer YOUR_KEY"

Szczegóły kategorii

GET /prestablog-api/categories/{id}

Zwraca wszystkie dane kategorii: pola wielojęzyczne, liczbę artykułów oraz powiązane grupy klientów.

Tworzenie kategorii

POST /prestablog-api/categories

Minimalny przykład:

curl -X POST "https://your-shop.com/prestablog-api/categories" \
  -H "Authorization: Bearer YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "languages": {
      "1": {
        "title": "Aktualności"
      }
    },
    "active": true
  }'

Pełny przykład:

{
  "languages": {
    "1": {
      "title": "Aktualności",
      "description": "<p>Wszystkie aktualności z naszego sklepu.</p>",
      "meta_title": "Aktualności - tytuł SEO",
      "meta_description": "Opis SEO kategorii",
      "meta_keywords": "aktualności",
      "link_rewrite": "news"
    },
    "2": {
      "title": "News",
      "description": "<p>All the latest news from our shop.</p>",
      "link_rewrite": "news"
    }
  },
  "parent": 0,
  "position": 1,
  "active": true,
  "image": {
    "url": "https://example.com/category.jpg"
  }
}

Dostępne pola:

PoleTypOpis
languagesobjectTreść per język. Wymagane przy tworzeniu
languages.{id}.titletextTytuł kategorii. Wymagane dla każdego języka
languages.{id}.descriptionHTMLOpis kategorii
languages.{id}.meta_titletextTag title SEO (max 500 znaków)
languages.{id}.meta_descriptiontextMeta description (max 500 znaków)
languages.{id}.meta_keywordstextSłowa kluczowe SEO
languages.{id}.link_rewritetextSlug URL. Jeśli brak, generowany automatycznie z tytułu
parentintegerID kategorii nadrzędnej. 0 = root
positionintegerKolejność wyświetlania
activebooleanKategoria widoczna na froncie
image.urlURLObraz kategorii do pobrania z zewnętrznego URL

Edycja kategorii

PUT /prestablog-api/categories/{id}

Aktualizacja częściowa: modyfikowane są tylko pola obecne w żądaniu.

curl -X PUT "https://your-shop.com/prestablog-api/categories/1" \
  -H "Authorization: Bearer YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "languages": {
      "1": {
        "title": "New category name",
        "description": "<p>New description.</p>"
      }
    }
  }'

Usuwanie kategorii

DELETE /prestablog-api/categories/{id}

Usuwa kategorię i wszystkie powiązane dane: obraz, powiązania z artykułami i grupy klientów.

Uwaga

Artykuły powiązane z tą kategorią nie są usuwane, ale tracą powiązanie z kategorią.

curl -X DELETE "https://your-shop.com/prestablog-api/categories/1" \
  -H "Authorization: Bearer YOUR_KEY"

Obraz kategorii

POST /prestablog-api/categories/{id}/image

Te same trzy metody co dla artykułów: zdalny URL, plik lokalny (multipart) lub base64.

Uwaga: base64 jest bardzo duże i może być trudne w użyciu dla złożonych obrazów. Jeśli to możliwe, preferuj upload przez zdalny URL.

curl -X POST "https://your-shop.com/prestablog-api/categories/1/image" \
  -H "Authorization: Bearer YOUR_KEY" \
  -F "file=@/path/to/category.jpg"

Autorzy

Autorzy są dostępni w API tylko do odczytu. Muszą zostać utworzeni w panelu administracyjnym PrestaBlog.

  • GET /prestablog-api/authors - lista wszystkich autorów
  • GET /prestablog-api/authors/{id} - szczegóły autora wraz z wielojęzycznymi biogramami
curl -X GET "https://your-shop.com/prestablog-api/authors?lang=1" \
  -H "Authorization: Bearer YOUR_KEY"

Kody błędów

Wszystkie odpowiedzi błędów mają format:

{
  "success": false,
  "error": {
    "code": "validation_error",
    "message": "Human readable error message",
    "details": { "field": "languages.1.title" }
  }
}
KodHTTPZnaczenie
unauthorized401Brak klucza API lub klucz nieprawidłowy
api_disabled503API wyłączone w konfiguracji
https_required426Żądanie musi być wykonane przez HTTPS
rate_limited429Przekroczony limit zapytań lub IP zablokowane po nieudanych próbach uwierzytelnienia
invalid_json400Nieprawidłowe lub brakujące body JSON
validation_error422Nieprawidłowa wartość pola (szczegóły w error.details)
conflict409Konflikt sluga: artykuł lub kategoria z takim linkiem już istnieje
not_found404Nie znaleziono zasobu
method_not_allowed405Metoda HTTP nieobsługiwana dla tego endpointu
payload_too_large413Zbyt duże body żądania (limit: 10 MB)
internal_error500Wewnętrzny błąd serwera

Limit zapytań: po przekroczeniu limitu odpowiedź 429 zawiera nagłówek Retry-After, który wskazuje ile sekund należy odczekać przed ponowną próbą. Każda odpowiedź zawiera też nagłówki X-RateLimit-Limit i X-RateLimit-Remaining.

Integracja z Pythonem

Dla programistów Pythona biblioteka requests pozwala w kilku linijkach komunikować się z API.

pip install requests
import requests

BASE = "https://your-shop.com/prestablog-api"
KEY = "YOUR_KEY"
headers = {"Authorization": f"Bearer {KEY}"}

# Lista artykułów
r = requests.get(f"{BASE}/articles", headers=headers, params={"lang": 1, "per_page": 10})
print(r.json())

# Utworzenie artykułu
r = requests.post(f"{BASE}/articles", headers=headers, json={
    "languages": {"1": {"title": "Mój artykuł", "content": "<p>Treść</p>"}},
    "categories": [1],
    "active": True
})
print(r.json())

# Wysłanie obrazu z pliku lokalnego
with open("image.jpg", "rb") as f:
    r = requests.post(f"{BASE}/articles/18/image", headers=headers, files={"file": f})
print(r.json())