Webhookok
A webhookok segítségével valós időben értesülhetsz a nyugtáid és beküldéseid állapotváltozásairól, anélkül hogy folyamatosan lekérdezéseket kellene indítanod.
Végpont regisztrálása
curl -X POST https://api.fiscon.hu/v1/webhooks \
-H "Authorization: Bearer fis_live_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{ "url": "https://example.com/webhooks/fiscon" }'$curl = curl_init('https://api.fiscon.hu/v1/webhooks');
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode(['url' => 'https://example.com/webhooks/fiscon']),
CURLOPT_HTTPHEADER => [
'Authorization: Bearer fis_live_xxxxxxxxxxxxxxxx',
'Content-Type: application/json',
],
]);
$response = curl_exec($curl);
curl_close($curl);use Illuminate\Support\Facades\Http;
$webhook = Http::withToken(config('services.fiscon.key'))
->post('https://api.fiscon.hu/v1/webhooks', [
'url' => 'https://example.com/webhooks/fiscon',
])
->json();const response = await fetch('https://api.fiscon.hu/v1/webhooks', {
method: 'POST',
headers: {
Authorization: 'Bearer fis_live_xxxxxxxxxxxxxxxx',
'Content-Type': 'application/json',
},
body: JSON.stringify({ url: 'https://example.com/webhooks/fiscon' }),
});
const webhook = await response.json();{
"id": "whk_01hz3k9c8v0000000000000000",
"url": "https://example.com/webhooks/fiscon",
"active": true,
"created_at": "2026-09-02T14:00:00+02:00"
}Végpontok kezelése
A regisztrált webhook-végpontok listája kurzor alapú lapozást használ — lásd a Lapozás szakaszt.
Listázás
curl https://api.fiscon.hu/v1/webhooks \
-H "Authorization: Bearer fis_live_xxxxxxxxxxxxxxxx"$curl = curl_init('https://api.fiscon.hu/v1/webhooks');
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer fis_live_xxxxxxxxxxxxxxxx',
],
]);
$response = curl_exec($curl);
curl_close($curl);use Illuminate\Support\Facades\Http;
$webhooks = Http::withToken(config('services.fiscon.key'))
->get('https://api.fiscon.hu/v1/webhooks')
->json();const response = await fetch('https://api.fiscon.hu/v1/webhooks', {
headers: {
Authorization: 'Bearer fis_live_xxxxxxxxxxxxxxxx',
},
});
const webhooks = await response.json();Frissítés
curl -X PATCH https://api.fiscon.hu/v1/webhooks/whk_01hz3k9c8v0000000000000000 \
-H "Authorization: Bearer fis_live_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{ "active": false }'$curl = curl_init('https://api.fiscon.hu/v1/webhooks/whk_01hz3k9c8v0000000000000000');
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'PATCH',
CURLOPT_POSTFIELDS => json_encode(['active' => false]),
CURLOPT_HTTPHEADER => [
'Authorization: Bearer fis_live_xxxxxxxxxxxxxxxx',
'Content-Type: application/json',
],
]);
$response = curl_exec($curl);
curl_close($curl);use Illuminate\Support\Facades\Http;
Http::withToken(config('services.fiscon.key'))
->patch('https://api.fiscon.hu/v1/webhooks/whk_01hz3k9c8v0000000000000000', [
'active' => false,
]);await fetch('https://api.fiscon.hu/v1/webhooks/whk_01hz3k9c8v0000000000000000', {
method: 'PATCH',
headers: {
Authorization: 'Bearer fis_live_xxxxxxxxxxxxxxxx',
'Content-Type': 'application/json',
},
body: JSON.stringify({ active: false }),
});Törlés
curl -X DELETE https://api.fiscon.hu/v1/webhooks/whk_01hz3k9c8v0000000000000000 \
-H "Authorization: Bearer fis_live_xxxxxxxxxxxxxxxx"$curl = curl_init('https://api.fiscon.hu/v1/webhooks/whk_01hz3k9c8v0000000000000000');
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'DELETE',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer fis_live_xxxxxxxxxxxxxxxx',
],
]);
$response = curl_exec($curl);
curl_close($curl);use Illuminate\Support\Facades\Http;
Http::withToken(config('services.fiscon.key'))
->delete('https://api.fiscon.hu/v1/webhooks/whk_01hz3k9c8v0000000000000000');await fetch('https://api.fiscon.hu/v1/webhooks/whk_01hz3k9c8v0000000000000000', {
method: 'DELETE',
headers: {
Authorization: 'Bearer fis_live_xxxxxxxxxxxxxxxx',
},
});Teszt esemény küldése
curl -X POST https://api.fiscon.hu/v1/webhooks/whk_01hz3k9c8v0000000000000000/test \
-H "Authorization: Bearer fis_live_xxxxxxxxxxxxxxxx"$curl = curl_init('https://api.fiscon.hu/v1/webhooks/whk_01hz3k9c8v0000000000000000/test');
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer fis_live_xxxxxxxxxxxxxxxx',
],
]);
$response = curl_exec($curl);
curl_close($curl);use Illuminate\Support\Facades\Http;
Http::withToken(config('services.fiscon.key'))
->post('https://api.fiscon.hu/v1/webhooks/whk_01hz3k9c8v0000000000000000/test');await fetch('https://api.fiscon.hu/v1/webhooks/whk_01hz3k9c8v0000000000000000/test', {
method: 'POST',
headers: {
Authorization: 'Bearer fis_live_xxxxxxxxxxxxxxxx',
},
});Aláírás ellenőrzése
Minden webhook-kérés tartalmaz egy Fiscon-Signature fejlécet, amivel ellenőrizheted, hogy a kérés valóban a Fisconból érkezett:
Fiscon-Signature: t=1735826400,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd
Az aláírás számítása: hash_hmac('sha256', "{t}.{nyers_kérés_törzs}", webhook_secret), ahol t az aláírásban szereplő Unix időbélyeg. A webhook_secret-et a végpont regisztrálásakor kapod meg — csak egyszer jelenítjük meg.
[$t, $v1] = array_map(
fn (string $part): string => explode('=', $part, 2)[1],
explode(',', request()->header('Fiscon-Signature'))
);
$expected = hash_hmac('sha256', "{$t}.".request()->getContent(), $webhookSecret);
if (! hash_equals($expected, $v1)) {
abort(401);
}use Illuminate\Http\Request;
Route::post('/webhooks/fiscon', function (Request $request) {
$webhookSecret = config('services.fiscon.webhook_secret');
[$t, $v1] = array_map(
fn (string $part): string => explode('=', $part, 2)[1],
explode(',', $request->header('Fiscon-Signature'))
);
$expected = hash_hmac('sha256', "{$t}.".$request->getContent(), $webhookSecret);
abort_unless(hash_equals($expected, $v1), 401);
// ... esemény feldolgozása ...
});import { createHmac, timingSafeEqual } from 'node:crypto';
function verifyFisconSignature(rawBody, signatureHeader, webhookSecret) {
const parts = Object.fromEntries(
signatureHeader.split(',').map((part) => part.split('=')),
);
const expected = createHmac('sha256', webhookSecret)
.update(`${parts.t}.${rawBody}`)
.digest('hex');
return timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1));
}Az ellenőrzés helyességéhez mindig a nyers (feldolgozatlan) kérés-törzset használd, és időzítés-alapú visszafejtés elleni védelemhez konstans idejű összehasonlítást (pl. PHP hash_equals()) alkalmazz.
A Fiscon nem kényszerít ki tolerancia-ablakot az aláírásban szereplő t időbélyegre — ez kizárólag a fogadó fél felelőssége. Javasolt egy néhány perces (pl. 5 perces) toleranciát is ellenőrizni a t és a jelenlegi idő között, hogy egy lejárt, esetlegesen újrajátszott kérést el tudj utasítani.
Esemény payload
{
"id": "evt_01hz3k9c8v0000000000000000",
"type": "submission.accepted",
"created_at": "2026-09-02T23:59:10+02:00",
"data": {
"submission_id": "sub_01hz3k9c8v0000000000000000",
"report_id": "rpt_01hz3k9c8v0000000000000000",
"status": "accepted"
}
}Események lekérdezése
A kiküldött eseményeket az API-n keresztül is visszakeresheted, ha egy webhook-kézbesítés kimaradt volna. A lista type szerint szűrhető, kurzor alapú lapozással — lásd a Lapozás szakaszt.
curl https://api.fiscon.hu/v1/events \
-H "Authorization: Bearer fis_live_xxxxxxxxxxxxxxxx"
curl https://api.fiscon.hu/v1/events/evt_01hz3k9c8v0000000000000000 \
-H "Authorization: Bearer fis_live_xxxxxxxxxxxxxxxx"$curl = curl_init('https://api.fiscon.hu/v1/events');
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer fis_live_xxxxxxxxxxxxxxxx',
],
]);
$response = curl_exec($curl);
curl_close($curl);use Illuminate\Support\Facades\Http;
$events = Http::withToken(config('services.fiscon.key'))
->get('https://api.fiscon.hu/v1/events')
->json();
$event = Http::withToken(config('services.fiscon.key'))
->get('https://api.fiscon.hu/v1/events/evt_01hz3k9c8v0000000000000000')
->json();const events = await fetch('https://api.fiscon.hu/v1/events', {
headers: { Authorization: 'Bearer fis_live_xxxxxxxxxxxxxxxx' },
}).then((response) => response.json());