Przewodniki
Uwierzytelnianie, klucze testowe i produkcyjne
Każde żądanie niesie tajny klucz w nagłówku Authorization. Prefiks klucza decyduje, czy faktura trafi do KSeF TEST, czy do produkcyjnego KSeF.
Klucze testowe i produkcyjne
| Prefiks klucza | Tryb | Dokąd idą faktury | Limit | Skutki prawne |
|---|---|---|---|---|
sk_test_ |
testowy | KSeF TEST Ministerstwa Finansów | brak | brak |
sk_live_ |
produkcyjny | produkcyjny KSeF | limit planu | prawdziwe faktury |
Dane obu trybów są całkowicie rozdzielone: faktury, numeracja, webhooki, zdarzenia, dane sprzedawcy i połączenie z KSeF ustawiasz osobno dla każdego trybu. Każdy obiekt ma pole livemode, a obiekt z drugiego trybu zwraca resource_missing albo livemode_mismatch.
Jak wysłać klucz
Klucz idzie w nagłówku Authorization jako token Bearer, zawsze przez HTTPS. Najprostszy test to pobranie konta:
curl https://app.ksefshop.pl/v1/account \
-H "Authorization: Bearer $KSEF_API_KEY"<?php
$ch = curl_init('https://app.ksefshop.pl/v1/account');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('KSEF_API_KEY'),
],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
$data = json_decode($body, true);
if ($status >= 400) {
throw new RuntimeException($data['error']['code'] . ': ' . $data['error']['message']);
}
echo var_export($data['seller_configured'], true), ' ', var_export($data['ksef_connected'], true), PHP_EOL;const res = await fetch("https://app.ksefshop.pl/v1/account", {
headers: {
Authorization: `Bearer ${process.env.KSEF_API_KEY}`,
},
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);
console.log(data.seller_configured, data.ksef_connected);import os
import requests
resp = requests.get(
"https://app.ksefshop.pl/v1/account",
headers={
"Authorization": f"Bearer {os.environ['KSEF_API_KEY']}",
},
timeout=30,
)
data = resp.json()
if not resp.ok:
raise RuntimeError(f"{data['error']['code']}: {data['error']['message']}")
print(data["seller_configured"], data["ksef_connected"])Odpowiedź pokazuje, czy dane sprzedawcy są kompletne (seller_configured) i czy działa połączenie z KSeF (ksef_connected). Ten sam endpoint wywołuje przycisk „Sprawdź połączenie” we wtyczce WooCommerce.
Tryb produkcyjny we wczesnym dostępie
We wczesnym dostępie działa tryb testowy. Klucz sk_live_ zwraca 403 live_mode_disabled, dopóki nie włączymy trybu produkcyjnego dla Twojego konta. Zrobimy to po starcie, razem z cennikiem i dokumentami dla klientów API.
Połączenie z KSeF
Faktury wysyłamy do KSeF w imieniu sprzedawcy, jego własnym certyfikatem KSeF (pliki .crt i .key z hasłem) albo tokenem KSeF. Wgrywasz je w panelu klienta osobno dla trybu testowego i produkcyjnego; przechowujemy je w postaci zaszyfrowanej. W trybie testowym certyfikat dla KSeF TEST tworzy się jednym kliknięciem.
Jak przygotować certyfikat do produkcji: certyfikat KSeF krok po kroku i token KSeF.
Przechowywanie i wymiana kluczy
- Klucz widać tylko raz, przy utworzeniu. U nas zostaje wyłącznie jego skrót SHA-256, więc nie odzyskamy go za Ciebie.
- Trzymaj klucz po stronie serwera: w zmiennej środowiskowej albo w menedżerze sekretów. Nigdy w przeglądarce, aplikacji mobilnej ani w publicznym repozytorium.
- Gdy klucz mógł wyciec, wymień go w panelu. Stary przestaje działać od razu.
- Nie podpisujemy żądań: tak jak w Stripe wystarcza TLS i tajny klucz, a bezpieczne ponawianie zapewnia idempotencja. Podpisane są za to webhooki.
Błędy uwierzytelniania
| Kod | HTTP | Znaczenie |
|---|---|---|
api_key_missing |
401 | Brak nagłówka Authorization. |
api_key_invalid |
401 | Klucz błędny, wymieniony albo konto wyłączone. |
live_mode_disabled |
403 | Tryb produkcyjny nie jest jeszcze włączony. |