# Leads og abonnementer

> Meld leads, salg efter et lead og abonnementsfornyelser fra jeres server – og hvilke integrationer der melder fornyelser af sig selv.

Betaler jeres program pr. lead, eller sælger I abonnementer, kan jeres egen server melde det hele til Affilyflow med [butikkens API med nøgle](https://www.affilyflow.com/docs/reference/konverterings-api#butikkens-api-med-noegle): leads, salget der kommer efter et lead, og hver betaling af et abonnement. Reglerne er de samme som for alle andre salg – cookie-periode, blokerede affiliates, programregler, selvhenvisning og salg til vurdering.

Alle kald kræver butikkens API-nøgle i `Authorization: Bearer afs_…`. Opret den under **Indstillinger → API-nøgler**, og læg den i en miljøvariabel, fx `AFFILYFLOW_API_KEY`. Send gerne `Idempotency-Key` med hvert `POST`, så et kald kan prøves igen efter en timeout uden at tælle to gange – se [Idempotens](https://www.affilyflow.com/docs/reference/konverterings-api#idempotens).

```http title="Endpoints"
POST https://app.affilyflow.com/api/v1/store/leads
GET  https://app.affilyflow.com/api/v1/store/leads/{lead_id}
POST https://app.affilyflow.com/api/v1/store/leads/{lead_id}/reject
POST https://app.affilyflow.com/api/v1/store/leads/{lead_id}/qualify
POST https://app.affilyflow.com/api/v1/store/conversions
```

## Hvem melder hvad?

| Integration | Leads | Fornyelser af abonnementer |
|---|---|---|
| Jeres server (API-nøgle) | Ja – `POST /leads` | Ja – `POST /conversions` med `"renewal": true` |
| Sporingskoden (`data-lead-url`) | Ja – når kunden når tak-siden | Nej – browseren ser ikke fornyelser |
| Stripe-webhooken | Nej | Ja – hver betaling af sig selv, se [Stripe](https://www.affilyflow.com/docs/butik/stripe) |
| WooCommerce Subscriptions | Nej | Ja – pluginnet fra version 1.14.0, se [WooCommerce](https://www.affilyflow.com/docs/butik/woocommerce#abonnementer) |
| Shopify-appen | Nej | Nej |
| Magento, PrestaShop, Shopware, Smartweb, DanDomain, Shoporama, Webflow | Via sporingskoden | Kun fra jeres server med API'et |

## Leads fra jeres server

Et lead fra serveren virker på tværs af enheder og kan kvalificeres eller afvises bagefter. Det er kun for lead-programmer – i et program, der betaler pr. salg, svares `422 not_lead_program`.

```bash title="POST /api/v1/store/leads"
curl -X POST https://app.affilyflow.com/api/v1/store/leads \
  -H "Authorization: Bearer $AFFILYFLOW_API_KEY" \
  -H "Idempotency-Key: LEAD-2026-0042" \
  -H "Content-Type: application/json" \
  -d '{"lead_id":"LEAD-2026-0042","afid":"c_AbC123xYz_-9","occurred_at":"2026-11-13T09:30:00Z"}'
```

| Felt | Påkrævet | Betydning |
|---|---|---|
| `lead_id` | Ja | Jeres eget id for leadet: 1–100 synlige ASCII-tegn uden mellemrum, fx et tal eller et UUID. Aldrig en e-mailadresse eller andre personoplysninger. |
| `afid` | Når der er et klik | Klik-id'et (`c_…`). Alias: `click_id`. |
| `coupons` | Nej | Kundens rabatkoder som en liste. Uden gyldigt klik tilskriver en [personlig rabatkode](https://www.affilyflow.com/docs/butik/personlige-rabatkoder) leadet. |
| `value`, `currency` | Nej | En værdi for leadet, fx en anslået ordreværdi, og dens valuta. Provisionen er altid programmets faste beløb pr. lead. |
| `occurred_at` | Anbefalet | Hvornår leadet opstod (ISO 8601). Cookie-perioden måles fra det. Ikke i fremtiden og højst 180 dage gammelt. |
| `buyer_hash`, `buyer_hash_n` | Anbefalet | Kundens fingeraftryk, som ved salg – se [Køberens fingeraftryk](https://www.affilyflow.com/docs/reference/konverterings-api#koeberens-fingeraftryk). |
| `test` | Nej | `true` = et testlead på butikkens testlink. Koster intet og tælles ikke med. |

- **Et lead pr. `lead_id`.** Samme `lead_id` igen giver `200 duplicate` og tæller ikke to gange.
- **Højst et lead pr. klik.** Et lead mere på samme klik giver `422 lead_per_click`. Kan samme besøgende blive flere leads (fx flere bookinger), så slå **Flere leads pr. klik** til under **Program → Vilkår → Leads og salg**. Et afvist lead tæller ikke med.
- **Programmets vilkår gælder.** Leadet får programmets faste beløb pr. lead og dets godkendelsesperiode og følger samme regler som et salg.

Svaret er `201` med `status: "ok"` og leadet, som `GET` viser det (`id`, `status`, `test`, `created_at`, `approval_due_at`, `commission`, `network_fee`, `attribution`, `confirmed_by_server`, `kind`, `lead_id`, `lead_qualified_at`, `awaiting_qualification` m.fl.). Et lead, der gav `422`, er ikke registreret – koderne står i [Statuskoder](https://www.affilyflow.com/docs/reference/statuskoder#leads-og-abonnementer).

### Slå et lead op

```bash title="GET /api/v1/store/leads/{lead_id}"
curl https://app.affilyflow.com/api/v1/store/leads/LEAD-2026-0042 \
  -H "Authorization: Bearer $AFFILYFLOW_API_KEY"
```

Et ukendt `lead_id` giver `404 not_found`. Slå et testlead op med `?test=true`.

### Afvis et ugyldigt lead

```bash title="POST /api/v1/store/leads/{lead_id}/reject"
curl -X POST https://app.affilyflow.com/api/v1/store/leads/LEAD-2026-0042/reject \
  -H "Authorization: Bearer $AFFILYFLOW_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"code":"duplicate","reason":"Samme kunde har allerede bestilt et tilbud"}'
```

- `code` er en af `duplicate`, `test_order`, `other_source`, `invalid_traffic`, `not_delivered` eller `other` (standard). `other` kræver en `reason` på mindst 3 tegn. `reason` er højst 300 tegn, og affiliaten ser den.
- Kun et afventende lead inden for godkendelsesperioden kan afvises – eller et lead, der er markeret til vurdering. Affiliaten får besked.
- Svaret er `200` med `status: "rejected"` (eller `already_rejected`) og leadet. Et godkendt lead giver `409 already_reviewed`, et lead, Affilyflow er ved at vurdere, `422 held_by_affilyflow`, og et lead efter godkendelsesperioden `422 reject_window`.

### Leads, der skal kvalificeres

Slår I **Leads skal kvalificeres** til under **Program → Vilkår → Leads og salg**, venter hvert nyt lead, til I har kvalificeret det – det godkendes aldrig automatisk før. Kvalificer det med API'et eller med **Godkend** under **Salg** i dashboardet.

```bash title="POST /api/v1/store/leads/{lead_id}/qualify"
curl -X POST https://app.affilyflow.com/api/v1/store/leads/LEAD-2026-0042/qualify \
  -H "Authorization: Bearer $AFFILYFLOW_API_KEY"
```

Svaret er `200` med `status: "qualified"` (eller `already_qualified`) og leadet. Et afvist lead giver `409 already_rejected`. Et kvalificeret lead følger derefter godkendelsesperioden som alle andre.

### Leads fra hjemmesiden

Sporingskoden kan også melde et lead uden kode, når kunden når jeres tak-side (`data-lead-url`, se [Lead uden kode](https://www.affilyflow.com/docs/reference/track-js#lead-uden-kode)). Den melder højst et lead pr. besøg, og samme regel om et lead pr. klik gælder.

## Lead og salg

Vælg under **Program → Vilkår → Leads og salg**, hvad et lead-program betaler for:

| Valg | Leadet | Et senere salg |
|---|---|---|
| **Kun leads** (standard) | Programmets faste beløb | Ingen provision |
| **Lead + salg** | Programmets faste beløb | Programmets salgsprovision (procent eller fast beløb) |
| **Kun salg** | Registreres uden provision | Programmets salgsprovision |

- Salget kobles til leadet via **samme klik** – uanset om salget meldes af sporingskoden, et plugin, Stripe eller jeres server – eller via `lead_id` på `POST /conversions`.
- Salgsprovisionen låses på klikket som programmets sats.
- Et salg efter et lead måles fra **leadet**: kommer salget inden for cookie-perioden efter leadet, giver det provision.

```bash title="Salget efter et lead"
curl -X POST https://app.affilyflow.com/api/v1/store/conversions \
  -H "Authorization: Bearer $AFFILYFLOW_API_KEY" \
  -H "Idempotency-Key: 1042" \
  -H "Content-Type: application/json" \
  -d '{"order":"1042","total":2400,"currency":"DKK","lead_id":"LEAD-2026-0042"}'
```

Med `lead_id` behøver I ikke sende klikket igen. Findes leadet ikke, svares `422 lead_not_found` (et testlead findes kun med `"test": true`), er det afvist `422 lead_rejected`, og betaler programmet kun pr. lead `422 lead_only_program`.

## Abonnementer fra jeres server

Sælger I abonnementer uden for Stripe, melder jeres server hver betaling til `POST /conversions`. Antallet af måneder, der giver provision, vælger I under **Recurring provision (abonnementer)** på **Program** (6, 12 eller 24 måneder eller livstid), og det låses på klikket.

**Første betaling** er et almindeligt salg med klikket (eller kundens rabatkoder) og abonnementets id:

```bash title="Første betaling"
curl -X POST https://app.affilyflow.com/api/v1/store/conversions \
  -H "Authorization: Bearer $AFFILYFLOW_API_KEY" \
  -H "Idempotency-Key: INV-5001" \
  -H "Content-Type: application/json" \
  -d '{"order":"INV-5001","total":199,"currency":"DKK","afid":"c_AbC123xYz_-9","subscription_id":"SUB-881","period":"2026-11"}'
```

**Hver fornyelse** sendes med `"renewal": true` og samme `subscription_id` – uden klik:

```bash title="Fornyelse"
curl -X POST https://app.affilyflow.com/api/v1/store/conversions \
  -H "Authorization: Bearer $AFFILYFLOW_API_KEY" \
  -H "Idempotency-Key: INV-5114" \
  -H "Content-Type: application/json" \
  -d '{"order":"INV-5114","total":199,"currency":"DKK","subscription_id":"SUB-881","renewal":true,"period":"2026-12"}'
```

| Felt | Betydning |
|---|---|
| `subscription_id` | Jeres eget id for abonnementet, højst 120 tegn. Aldrig en e-mailadresse. |
| `renewal` | `true` på en fornyelse. Kræver `subscription_id`, og en fornyelse kan ikke have `lead_id`. |
| `period` | Valgfri: perioden, betalingen dækker, fx `"2026-11"`. Højst 40 tegn. To fornyelser for samme periode med forskellige ordrenumre tælles ikke to gange. |

- Reglerne er de samme som for Stripe: antallet af måneder er låst på klikket, et abonnement giver provision til loftet er nået, og er første betaling afvist, giver fornyelserne heller ingen provision.
- Provisionen regnes af `total` – varerne efter rabat, uden moms og fragt – som ved et salg.
- Hver fornyelse er sit eget salg med sit eget ordrenummer. Den refunderes for sig med [refusions-endpointet](https://www.affilyflow.com/docs/reference/konverterings-api#refusioner-fra-jeres-server).
- Svaret på en registreret fornyelse er `201 ok` med `cycle` (hvilken betaling det er) og `cap` (loftet fra klikket).
- Med `"test": true` virker det hele som testsalg, også fornyelserne.

| `status` | Hvornår |
|---|---|
| `not_recurring` | Programmet betaler ikke provision på fornyelser. |
| `cap_reached` | Perioden med provision er slut for dette abonnement. |
| `first_rejected` | Abonnementets første betaling er afvist. |
| `unknown_subscription` | Ingen første betaling med dette `subscription_id` i jeres butik. Send første betaling med `subscription_id` og klikket først. |
| `duplicate_period` | Abonnementet har allerede en fornyelse for denne periode (med et andet ordrenummer). |
| `subscription_exists` | Abonnementet har allerede en første betaling. Send de næste med `"renewal": true`. |

## Kodestumper

Kodestumperne under **Specialbygget webshop** i Opsætning og i [Sporing fra jeres server](https://www.affilyflow.com/docs/butik/server-sporing) har funktionerne færdige: i PHP `affilyflow_lead(…)` og `affilyflow_sale(…)` med de navngivne argumenter `subscriptionId:`, `renewal:`, `period:` og `leadId:`, og i JavaScript/TypeScript `affilyflowLead({ leadId, click, coupons, email, value, currency, occurredAt })` og `affilyflowSale({ …, subscriptionId, renewal, period, leadId })`.

Se også [Konverterings-API](https://www.affilyflow.com/docs/reference/konverterings-api#butikkens-api-med-noegle), [Statuskoder](https://www.affilyflow.com/docs/reference/statuskoder) og [Godkendelse og refusioner](https://www.affilyflow.com/docs/butik/godkendelse-og-refusioner).

Kilde: https://www.affilyflow.com/docs/butik/leads-og-abonnementer
