oddzwon.pl
Funkcje Aplikacja Jak działa Integracje API MCP AI Cennik Zaloguj się do panelu Wypróbuj 14 dni za darmo
Dla developerów

API oddzwon.pl

Proste REST API: przyjmuj zgłoszenia z dowolnego źródła, zarządzaj konsultantami i kolejką, czytaj statystyki, odbieraj zdarzenia webhookami. JSON, HTTPS, klucz w nagłówku.

Baza: https://api.oddzwon.pl Format: JSON Integracje: MCP · Zapier/n8n Pobierz specyfikację OpenAPI (YAML)

Szybki start

1

Weź klucze z panelu

Publiczny (pk_) do widgetu i formularzy, zarządczy do reszty API.

2

Wyślij pierwsze zgłoszenie

Jeden POST na /v1/callback. Odpowiedź 202 znaczy, że routing ruszył.

3

Podepnij webhooki

Dodaj swój adres w panelu i odbieraj zdarzenia podpisane HMAC.

Autoryzacja

Dwa poziomy dostępu:

Klucz publiczny

public_key (pk_…) w ciele żądania. Tylko do tworzenia zgłoszeń callback z Twojej strony/widgetu. Bezpieczny do umieszczenia w kodzie front-endu.

Klucz zarządczy

Nagłówek Authorization: Bearer <klucz zarządczy>. Pełen dostęp do danych tenanta (statystyki, konsultanci, kolejka, webhooki). Trzymaj po stronie serwera.

Utwórz zgłoszenie (callback)

POST /v1/callback, publiczny, wymaga public_key. Odpowiedź 202.

# Klient zostawia numer, trafia do routingu i dzwoni handlowiec curl -X POST https://api.oddzwon.pl/v1/callback \ -H 'content-type: application/json' \ -d '{ "public_key": "pk_...", "phone": "512 908 314", "consent": true, "consent_text": "Zgoda na kontakt telefoniczny", "consent_version": "1", "mode": "immediate" }' # => 202 {"request_id":"...","status":"ringing","dedup":false}

Pola opcjonalne: name, mode (immediate/scheduled), preferred_slot, utm, gclid, idempotency_key. Dedup po naturalnym kluczu (tenant + numer + okno czasowe).

Zarządzanie (Bearer)

Wszystkie pod /v1/manage/* z nagłówkiem Authorization: Bearer <klucz zarządczy>.

MetodaŚcieżkaOpis
GET/v1/manage/statsStatystyki dnia (zamówione, odebrane, skuteczność, śr. czas reakcji)
GET/v1/manage/usageZużycie w bieżącym miesiącu (metryka-prawdy)
GET/v1/manage/planPlan, limit seatów, status subskrypcji
GET/POST/v1/manage/consultantsLista / dodanie konsultanta (limit wg planu)
GET/PUT/v1/manage/hoursGodziny pracy zespołu
GET/v1/manage/queueKolejka nieodebranych (+ requeue / resolve)
GET/v1/manage/historyHistoria oddzwonień (statusy FSM)
GET/POST/v1/manage/webhooksWebhooki wychodzące per tenant
POST/v1/manage/eraseRODO: usunięcie danych numeru
curl https://api.oddzwon.pl/v1/manage/stats \ -H 'authorization: Bearer <klucz zarządczy>'

Webhooki wychodzące

Zdarzenia wysyłamy POST-em na Twój URL (dodaj w panelu → Integracje), podpisane HMAC-SHA256.

Nagłówki

X-Oddzwon-Event: typ zdarzenia
X-Oddzwon-Delivery: id dostawy
X-Oddzwon-Signature: sha256=<hmac> surowego body

Zdarzenia

callback.requested, callback.scheduled, call.ringing, call.answered, call.connected, call.missed, call.completed, lead.created, disposition.set

# Przykład payloadu dostawy (POST na Twój URL) { "id": "...", "event": "call.answered", "data": { "request_id": "...", "consultant_id": "...", "disposition": "answered", "duration_seconds": 123 }, "timestamp": "..." }

Zestaw pól w data zależy od typu zdarzenia: inne pola niesie callback.requested, a inne call.answered.

Nieudane dostawy ponawiamy z rosnącym odstępem (backoff), a po kilku próbach zdarzenie trafia do kolejki błędów (dead-letter). Weryfikuj podpis surowego body sekretem z panelu. Gotowe szablony n8n i przewodnik: Integracje.

Weryfikacja podpisu w Twoim języku

Policz HMAC-SHA256 z surowego body (bajty przed parsowaniem JSON!) sekretem z panelu i porównaj z nagłówkiem X-Oddzwon-Signature w stałym czasie. Wszystkie przykłady dają identyczny podpis (sprawdzone przeciw naszej implementacji).

Node.js

const { createHmac, timingSafeEqual } = require("node:crypto"); function verify(rawBody, header, secret) { const expected = "sha256=" + createHmac("sha256", secret) .update(rawBody).digest("hex"); return header.length === expected.length && timingSafeEqual(Buffer.from(header), Buffer.from(expected)); }

PHP

function verify(string $rawBody, string $header, string $secret): bool { $expected = "sha256=" . hash_hmac("sha256", $rawBody, $secret); return hash_equals($expected, $header); } // $rawBody = file_get_contents("php://input");

Python

import hmac, hashlib def verify(raw_body: bytes, header: str, secret: str) -> bool: expected = "sha256=" + hmac.new( secret.encode(), raw_body, hashlib.sha256).hexdigest() return hmac.compare_digest(expected, header)

Ruby

require "openssl" def verify(raw_body, header, secret) expected = "sha256=" + OpenSSL::HMAC.hexdigest( "SHA256", secret, raw_body) Rack::Utils.secure_compare(expected, header) end

Java

import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import java.security.MessageDigest; boolean verify(byte[] rawBody, String header, String secret) throws Exception { Mac mac = Mac.getInstance("HmacSHA256"); mac.init(new SecretKeySpec(secret.getBytes("UTF-8"), "HmacSHA256")); StringBuilder sb = new StringBuilder("sha256="); for (byte b : mac.doFinal(rawBody)) sb.append(String.format("%02x", b)); return MessageDigest.isEqual(sb.toString().getBytes(), header.getBytes()); }

Czy klucz publiczny w kodzie strony jest bezpieczny?

Tak. Klucz pk_ jest z założenia jawny, tak jak identyfikator Google Analytics czy klucz publiczny Stripe. Służy wyłącznie do identyfikacji Twojej firmy przy zostawianiu numeru przez klienta. Nie da się nim odczytać żadnych danych: kolejka, historia i dane osobowe wymagają osobnego klucza zarządczego albo tokenu sparowanego urządzenia.

Przed nadużyciami (zgłoszenia spoza Twojej strony) chroni origin lock: w panelu, w zakładce Widget, wpisz domeny na których działa widget, a zgłoszenia z innych stron będą odrzucane. Do tego działają limity zapytań, pole-pułapka na boty i deduplikacja numerów.

Kody odpowiedzi

API zwraca standardowe kody HTTP. Najważniejsze:

KodZnaczenie
202Zgłoszenie przyjęte i skierowane do routingu. Duplikat w oknie dedup zwraca 202 z dedup:true.
200Żądanie zarządcze wykonane poprawnie.
422Błąd walidacji: invalid_payload, consent_required, invalid_phone, invalid_slot.
401Brak lub zły token Bearer (klucz zarządczy lub sesja panelu).
403invalid_tenant (zły klucz publiczny) albo brak uprawnień roli.
429Za dużo żądań, zadziałał limit anty-spam.

Agenci AI też to potrafią

Ten sam backend wystawiamy jako serwer MCP. Twój asystent (Claude, ChatGPT, Cursor) czyta leady i umawia oddzwonienia bez pisania kodu.

Zobacz MCP →