Server-side postback (S2S)

Najwyższa accuracy. Twój backend wysyła POST na Affily zaraz po finalizacji zamówienia.

Polecane dla: SaaS, fintech, ubezpieczenia, OZE, każdy biznes z silnym backendem. Niewrażliwe na ad-blockery, ITP (Safari), cookie clearing.

1. Pobierz click_id z cookie

Affily ustawia cookie affily_click_id przy kliknięciu w link. Twój checkout musi zapisać tę wartość razem z zamówieniem.

// Na stronie checkout (przed wysłaniem formularza zamówienia):
const affilyClickId = document.cookie
  .split('; ')
  .find(c => c.startsWith('affily_click_id='))
  ?.split('=')[1];

// Wyślij do swojego backendu razem z zamówieniem
fetch('/api/orders', {
  method: 'POST',
  body: JSON.stringify({
    ...orderData,
    affily_click_id: affilyClickId, // <- TO
  }),
});

2. Po finalizacji zamówienia - POST do Affily

Z backendu, po sukcesie płatności / podpisania umowy / wysłaniu leada:

POST https://api.affily.pl/v1/conversions
Authorization: Bearer aff_pk_live_xxxxxxxx
Content-Type: application/json

{
  "click_id": "click_xxxxxxxx",         // z cookie zapisanego przy checkout
  "offer_id": "off_xxxxxxxx",            // ID Twojej oferty
  "order_id": "ORDER-2026-00123",        // unikalny ID transakcji
  "amount": 1499.00,                     // wartość transakcji w PLN
  "currency": "PLN",
  "metadata": {                          // opcjonalne, dowolne pary klucz-wartość
    "product": "Premium subscription",
    "customer_country": "PL"
  }
}

// Response 201:
{
  "id": "conv_xxxxxxxx",
  "status": "pending",
  "commission": 149.90,
  "hold_until": "2026-06-17T12:34:56Z"
}

3. Przykłady — różne języki

Node.js / TypeScript

await fetch('https://api.affily.pl/v1/conversions', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${process.env.AFFILY_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    click_id: order.affily_click_id,
    offer_id: 'off_xxxxxxxx',
    order_id: order.id,
    amount: order.total,
    currency: 'PLN',
  }),
});

PHP

<?php
$ch = curl_init('https://api.affily.pl/v1/conversions');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('AFFILY_API_KEY'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'click_id' => $order->affily_click_id,
        'offer_id' => 'off_xxxxxxxx',
        'order_id' => $order->id,
        'amount'   => $order->total,
        'currency' => 'PLN',
    ]),
]);
$response = curl_exec($ch);
curl_close($ch);

Python

import requests, os

requests.post(
    'https://api.affily.pl/v1/conversions',
    headers={
        'Authorization': f'Bearer {os.environ["AFFILY_API_KEY"]}',
        'Content-Type': 'application/json',
    },
    json={
        'click_id': order.affily_click_id,
        'offer_id': 'off_xxxxxxxx',
        'order_id': order.id,
        'amount': float(order.total),
        'currency': 'PLN',
    },
    timeout=10,
)

4. Outbound webhooks (eventy zwrotne)

Affily może wysyłać POST do Twojego endpointa kiedy konwersja zmienia status. Ustaw URL webhook w panelu → Settings.

POST https://your-app.com/affily-webhook
X-Affily-Signature: <hmac-sha256-hex>
X-Affily-Timestamp: <unix-timestamp>
X-Affily-Event: conversion.approved

{
  "event": "conversion.approved",
  "timestamp": "2026-06-17T12:34:56Z",
  "data": {
    "conversion_id": "conv_xxxxxxxx",
    "offer_id": "off_xxxxxxxx",
    "publisher_id": "pub_xxxxxxxx",
    "order_id": "ORDER-2026-00123",
    "amount": 1499.00,
    "currency": "PLN",
    "commission": 149.90,
    "status": "approved",
    "occurred_at": "2026-06-17T12:34:56Z"
  }
}

Weryfikacja HMAC

// Node.js
import crypto from 'crypto';

const isValid = (req) => {
  const timestamp = req.headers['x-affily-timestamp'];
  const signature = req.headers['x-affily-signature'];
  const payload = JSON.stringify(req.body);

  const expected = crypto
    .createHmac('sha256', process.env.AFFILY_WEBHOOK_SECRET)
    .update(`${timestamp}.${payload}`)
    .digest('hex');

  return signature === expected;
};
Bezpieczeństwo: Affily używa HMAC-SHA256 + 5 min tolerance window (timestamp różnica). Odrzucaj requesty starsze niż 5 min nawet z poprawnym podpisem - ochrona przed replay attacks.

Statusy konwersji

StatusZnaczenie
pendingCzeka na zatwierdzenie (hold period 30 dni)
approvedZatwierdzona, prowizja dla wydawcy
rejectedOdrzucona (zwrot, chargeback, fraud)
disputedWydawca zgłosił sprzeciw wobec odrzucenia