# Postbacks

> Få salget i din tracker eller på din server, når det sker – og igen ved godkendelse, afvisning og refusion. Med makroer, signatur, genforsøg og log.

En postback er en adresse i din tracker (fx Voluum, RedTrack, Binom eller Keitaro) eller på din egen server, som Affilyflow kalder, når der sker noget med et salg på dine links. Så kan din tracker optimere kampagnerne på rigtige salg – og du ser det samme som i dashboardet, uden at hente noget.

- Salget sendes, når det kommer ind – og igen, når det **godkendes**, **afvises** eller **refunderes**.
- Hvert kald er **signeret**, og et kald uden svar 2xx **prøves igen** i op til 24 timer.
- Hvert kald står i en **log** med svarkode og svar, og du kan sende det igen.
- Vi sender aldrig kundens data, ordrens beløb eller butikkens fulde ordrenummer – kun de sidste tegn.

## Opret en postback

1. Gå til **AI og API** i affiliate-dashboardet, og find **Postbacks**.
2. Tryk **Ny postback**, og indsæt adressen fra din tracker med makroer (se nedenfor).
3. Vælg **GET** (det de fleste trackere bruger) eller **POST med JSON**, og vælg hændelserne.
4. Kopier hemmeligheden, hvis din egen server skal tjekke signaturen. Den vises kun en gang.
5. Tryk **Send test**, og tjek, at din tracker har modtaget den.

Du kan have op til 5 postbacks. Adressen skal starte med `https://` eller `http://` og må kun bruge port 443, 80, 8080 eller 8443.

## Din trackers klik-id

Din tracker har sit eget klik-id. Send det med i Affilyflow-linket som sub-ID, så kommer det tilbage i postbacken:

```text title="Linket i din tracker"
https://app.affilyflow.com/go/DIT_LINK?sid={clickid}
```

`{clickid}` er din trackers egen makro (den hedder noget forskelligt fra tracker til tracker). I postbacken bruger du så `{sub_id}`:

```text title="Postback i Affilyflow"
https://din-tracker.dk/postback?cid={sub_id}&payout={commission}&currency={currency}&status={status}&txid={sale_id}
```

Navnene på din trackers parametre (`cid`, `payout`, `txid` …) står i trackerens egen vejledning. Du har fem sub-ID'er (`sid`, `sid2` … `sid5`) – se [Links og sub-ID](https://www.affilyflow.com/docs/affiliate/links-og-sub-id).

## Makroer

| Makro | Indhold |
|---|---|
| `{click_id}` | Affilyflows klik-id (`c_…`). |
| `{sub_id}` | Sub-ID 1 fra linket (`?sid=`). |
| `{sub_id2}` … `{sub_id5}` | Sub-ID 2–5 (`?sid2=` … `?sid5=`). `{sub2}` … `{sub5}` virker også. |
| `{commission}` | Din provision efter hændelsen, med punktum og to decimaler (`75.92`). Efter en delvis refusion: provisionen efter refusionen. Ved et afvist salg `0.00`. |
| `{currency}` | Valutaen for provisionen (fx `DKK`). |
| `{status}` | `pending`, `approved` eller `rejected`. |
| `{event}` | Hændelsen, fx `sale.approved`. |
| `{order_ref_masked}` | De sidste tegn af butikkens ordrenummer (fx `••82`) – til at tale med butikken om det samme salg. |
| `{sale_id}` | Salgets id hos Affilyflow – det samme for alle hændelser på salget. |
| `{event_id}` | Hændelsens id (`evt_…`) – det samme, hvis kaldet prøves igen. |
| `{program_id}` | Programmets id. |

Hver værdi URL-kodes. Et tomt felt bliver tomt (fx `{sub_id3}`, når linket ikke har et tredje sub-ID). Andre makroer afvises, når du gemmer.

## Hændelser

| Hændelse | Sendes når |
|---|---|
| `sale.created` | Butikken melder et salg på dit link (afventer godkendelse). |
| `sale.approved` | Salget er godkendt og tæller med i din saldo. |
| `sale.rejected` | Salget er afvist – fx returneret, annulleret eller brud på programmets regler. |
| `sale.refunded` | Salget er refunderet helt eller delvist. `{commission}` er provisionen efter refusionen. |
| `sale.updated` | Provisionen er ændret på anden vis, fx en refusion, der fortrydes. |
| `click.created` | Hvert klik på dine links, cirka 2 minutter efter klikket. Valgfri – mange kald. Et klik, vi sorterer fra som bot inden da, sendes ikke. |

Et salg, der afvises allerede ved registreringen (fx brud på programmets regler), kommer som `sale.created` med `{status}` = `rejected` – tjek altid `{status}`. Et salg via en personlig rabatkode har intet klik, så klikmakroerne er tomme.

## GET eller POST

- **GET:** adressen kaldes med makroerne udfyldt. Det er det, trackere forventer.
- **POST med JSON:** makroerne i adressen udfyldes også, og kroppen er hele hændelsen:

```json title="POST · sale.approved"
{
  "id": "evt_6f1c2d0e8b9a4c3d9e7f1a2b3c4d5e6f",
  "type": "sale.approved",
  "created_at": "2026-11-12T10:14:03.512+00:00",
  "test": false,
  "data": {
    "sale": {
      "id": "0b6b2d8e-3f1a-4c55-9d2e-7a1b2c3d4e5f",
      "order_ref_masked": "••82",
      "status": "approved",
      "previous_status": "pending",
      "commission": 75.92,
      "currency": "DKK",
      "created_at": "2026-10-13T18:22:41.087+00:00",
      "approved_at": "2026-11-12T10:14:03.512+00:00",
      "approval_due_at": "2026-11-12T18:22:41.087+00:00",
      "rejection_reason": null,
      "attribution": "click",
      "recurring": false,
      "refund": null
    },
    "click": {
      "click_id": "c_8Kq2mXo1Tz9w",
      "clicked_at": "2026-10-13T17:58:02.114+00:00",
      "link_id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
      "sub_id": "fb-kampagne-12",
      "sub_id2": "annonce-3",
      "sub_id3": null,
      "sub_id4": null,
      "sub_id5": null,
      "landing_path": "/produkter/uldplaid",
      "device": "mobile",
      "country": "DK"
    },
    "program": { "id": "5d1e2f3a-4b5c-4d6e-8f70-819a2b3c4d5e", "store": "Nordlys Bolig" }
  }
}
```

Ved en refusion står `refund` med `type` (`partial` eller `full`), `refunded_ratio`, `commission_before_refund` og `refunded_at`. Ved et afvist salg viser `commission` den provision, salget havde – den udbetales ikke (makroen `{commission}` er `0.00`).

## Signaturen

Hvert kald har headeren `Affilyflow-Signature: t=…,v1=…`. `v1` er en HMAC-SHA256 med din hemmelighed over `t`, et punktum og:

- ved **POST**: den rå krop,
- ved **GET**: hele adressen, som den blev kaldt (med makroerne udfyldt).

Trackere ignorerer headeren, og det er fint. På din egen server bør du tjekke den og afvise kald, hvor `t` er mere end 5 minutter fra dit ur. Lige efter en ny hemmelighed kan der stå to `v1=` (ny og gammel) – godtag kaldet, hvis en af dem passer. Kodeeksempler i Node.js og PHP står under [Webhooks](https://www.affilyflow.com/docs/butik/webhooks#tjek-signaturen) – det er samme signatur.

## Genforsøg, pause og log

- Svar med en status **2xx** inden for 10 sekunder. Alt andet prøves igen efter cirka 1, 5, 15 og 30 minutter og derefter efter 1, 2, 4, 6 og 8 timer – i op til 24 timer.
- Efter **20 mislykkede forsøg i træk** sættes postbacken på pause, og det står i dashboardet. Ret fejlen, send en test, og tryk **Slå til**. Kald fra de seneste 24 timer bliver så sendt.
- **Log** viser de seneste 20 kald: hændelse, ordre, status, svarkode, forsøg og de første 500 tegn af svaret. **Send igen** sender et kald igen. Loggen gemmes i 30 dage.
- **Send test** sender eksempeldata (`c_test0000000000`, sub-ID `test`, provision `39.92`) og viser svaret med det samme. I POST-kroppen står `"test": true`.
- Samme hændelse kan komme mere end en gang. Brug `{event_id}` (eller `{sale_id}` + `{status}`) til at ignorere dubletter.

## Postbacks eller API?

Postbacks kommer til dig, når noget sker. Vil du selv hente salg, klik og tal, så brug [REST-API'et](https://www.affilyflow.com/docs/affiliate/rest-api) eller [MCP-serveren](https://www.affilyflow.com/docs/affiliate/mcp).

Kilde: https://www.affilyflow.com/docs/affiliate/postbacks
