Dokumentacja dla deweloperów
Dwa kroki: widżet w formularzu, a następnie sprawdzenie tokenu na serwerze, zanim cokolwiek przetworzysz. API odpowiada jak reCAPTCHA i Turnstile, dodatkowo z akcją i powodami.
Szybki start
1. Dodaj widżet do formularza. Zastąp klucz strony własnym kluczem z panelu.
<script src="https://formconfirmed.com/v1/widget.js" async defer></script>
<form method="post" action="/contact">
...
<div class="fcp-widget" data-sitekey="fcp_pub_..." data-purpose="contact"></div>
<button type="submit">Send</button>
</form>
2. Zanim wyślesz lub zapiszesz zgłoszenie, wyślij token ze swojego serwera do /v1/verify. Klucz tajny pozostaje na serwerze.
<?php
$ch = curl_init('https://formconfirmed.com/v1/verify');
curl_setopt_array($ch, [
CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 3,
CURLOPT_POSTFIELDS => http_build_query([
'secret' => getenv('FCP_SECRET'),
'response' => $_POST['fcp-response'] ?? '',
'remoteip' => $_SERVER['REMOTE_ADDR'] ?? '',
'content' => $_POST['message'] ?? '',
'expected_purpose' => 'contact',
]),
]);
$res = json_decode((string)curl_exec($ch), true);
if (!is_array($res) || !isset($res['success'], $res['action'])) {
$decision = 'hold'; // outage: never a pass
} elseif (!$res['success']) {
$decision = 'reject';
} else {
$decision = $res['action'] === 'flag' ? 'hold' : 'accept';
}
POST /v1/verify
https://formconfirmed.com/v1/verify
Wysyłaj pola jako dane formularza (application/x-www-form-urlencoded) lub jako JSON. Użyj krótkiego limitu czasu (3 sekundy).
| Pole | Znaczenie | |
|---|---|---|
secret | wymagane | Twój klucz tajny (fcp_sec_…). Nigdy nie umieszczaj go na stronie. |
response | wymagane | Token z pola formularza fcp-response. Wysyłaj go także wtedy, gdy jest pusty – nie odrzucaj brakującego tokenu samodzielnie. |
remoteip | opcjonalne | Adres IP odwiedzającego. Zaostrza sygnały częstotliwości i sieci. |
content | opcjonalne | Treść wiadomości. Filtr wstępny spamu w każdym planie, sprawdzenie treści przez AI zależnie od planu i ustawień. Sprawdzana tylko w pamięci, nie jest zapisywana. |
email | opcjonalne | Adres e-mail z formularza: rozpoznawane są skrzynki jednorazowe i domeny bez poczty. |
hp | opcjonalne | Wartość ukrytego pola fcp-website (honeypot). |
expected_purpose | opcjonalne | Cel, dla którego podpisano widżet, np. contact, login, register. Token wydany dla innego celu zostanie odrzucony. |
operation_id | opcjonalne | Stały identyfikator operacji (16–128 znaków) – powtórzenia nie liczą się podwójnie. Tylko razem z expected_purpose. |
recipient | opcjonalne | Odbiorca wiadomości akcji (np. reset hasła) na potrzeby limitów na odbiorcę. |
form_mode | opcjonalne | interactive (domyślnie) lub deferred dla formularzy wysyłanych później. |
Odpowiedź
{ "success": true, "score": 0.92, "action": "allow", "reasons": [],
"error-codes": [], "challenge_ts": "2026-11-06T09:41:12Z", "hostname": "example.com" }
success | false, gdy akcja to block lub żądanie jest nieprawidłowe. |
score | 0,0 (bot) do 1,0 (człowiek). |
action | allow, flag lub block – zalecane postępowanie. |
reasons | Sygnały, które doprowadziły do wyniku, np. too_fast, honeypot_filled. |
error-codes | Błędy techniczne, patrz niżej. |
challenge_ts | Czas rozwiązania zadania (UTC). |
hostname | Host, na którym działał widżet. |
content | Tylko przy sprawdzaniu treści: kategoria i pewność. |
Postępowanie z akcją
- allow: przetwórz zgłoszenie normalnie.
- flag: nie przetwarzaj po cichu – dostarcz z oznaczeniem (folder spam, moderacja).
- block: odrzuć i pokaż neutralny komunikat o błędzie.
Gdy usługa jest nieosiągalna
Limit czasu, błąd sieci, 5xx lub nieprawidłowa odpowiedź nigdy nie są zgodą. Zatrzymaj wiadomość z oznaczeniem do moderacji albo pokaż błąd z prośbą o ponowienie. Przyjmij ją normalnie tylko po własnym, niezależnym sprawdzeniu, np. istniejącej weryfikacji konta. W panelu można ustawić zachowanie przy awarii dla każdej witryny.
Kody błędów
missing-input-secret | Nie wysłano klucza tajnego. |
invalid-input-secret | Klucz tajny nieznany lub wycofany. |
missing-input-response | Nie wysłano tokenu. |
invalid-input-response | Token nieprawidłowy, wygasły lub już użyty. |
purpose-mismatch | Token wydano dla innego celu. |
purpose-not-allowed | Ten cel nie jest dozwolony dla witryny (ustawienie w panelu). |
site-paused | Witryna jest wstrzymana w panelu. |
service-disabled | Usługa jest tymczasowo wyłączona. |
bad-request | Brakujące pola, za długie lub w złym formacie. |
service-unavailable | Widżet nie dotarł do usługi – traktuj to jak awarię. |
Formularze wysyłane przez JavaScript
W formularzach wysyłanych przez fetch lub XMLHttpRequest najpierw pobierz token i wyślij go w polu fcp-response:
form.addEventListener('submit', async (e) => {
e.preventDefault();
const data = new FormData(form);
data.set('fcp-response', await window.__fcpWidget.token(form));
await fetch(form.action, { method: 'POST', body: data });
});
WordPress
Wtyczka formexposed (od wersji 1.8) automatycznie dodaje widżet i sprawdzenie na serwerze do Contact Form 7, WPForms i komentarzy. Wpisz klucz strony i klucz tajny w Wtyczki → formexposed → Ochrona formularzy.
Ochrona danych
Bez plików cookie, nic nie jest zapisywane na urządzeniu, bez fingerprintu. Przetwarzane są: rozwiązane zadanie, czas wypełniania, czy ukryte pole zostało wypełnione oraz – jeśli ją wyślesz – treść wiadomości, sprawdzana tylko w pamięci. Adresy IP tylko skrócone i jako codziennie zmieniany hash. Tekst do polityki prywatności znajdziesz w panelu.