Webhooks
Получайте события в реальном времени о жизненном цикле изображений, изменениях квот и отзыве ключей.
FastPic доставляет webhook-события на URL, настроенный в дашборде. События приходят как JSON через POST с HMAC-подписью, которую необходимо проверить перед обработкой payload.
События
FastPic отправляет следующие типы событий:
| Event | Description |
|---|---|
| image.created | A new image was uploaded via POST /v1/images. |
| image.deleted | An image was soft-deleted via DELETE or dashboard. |
| api_key.revoked | An API key was revoked. |
| quota.warned | Storage quota crossed 80% of the plan limit. |
| quota.exceeded | Storage quota was exceeded; uploads are blocked. |
Формат доставки
Каждое событие доставляется как POST-запрос на настроенный URL:
POST /your/webhook HTTP/1.1Host: example.comContent-Type: application/jsonX-FastPic-Event: image.createdX-FastPic-Delivery: 8a4c6f12-aabb-4c1f-9d5b-aaaaaaaaaaaaX-FastPic-Signature: t=1730476800,v1=5257a8... { "id": "evt_a1b2c3", "type": "image.created", "created": 1730476800, "data": { "object": { ... } }}Проверка подписи
Проверяйте каждый webhook перед обработкой. Заголовок X-FastPic-Signature содержит timestamp и HMAC-SHA256 строки `{timestamp}.{rawBody}`, подписанной секретом signing secret вашего endpoint'а.
import { createHmac } from 'crypto' export const verify = (header: string, body: string, secret: string) => { const [ts, sig] = header.split(',').map(p => p.split('=')[1]) const expected = createHmac('sha256', secret).update(`${ts}.${body}`).digest('hex') return sig === expected}Повторные попытки
FastPic считает webhook доставленным, если endpoint вернул 2xx в течение 10 секунд. В противном случае выполняются повторные попытки с экспоненциальной задержкой: 1 мин, 5 мин, 30 мин, 2 ч, 6 ч, 24 ч. После 6 неудачных попыток endpoint автоматически отключается, и вы получаете email-уведомление.
Настройка endpoint'а
Добавьте webhook endpoint в дашборде: app.fastpic.pro/keys → Webhooks. Каждый endpoint получает собственный signing secret. Протестируйте подписи через кнопку тестового события в дашборде, прежде чем полагаться на интеграцию.