Conversion API
Die Conversion API ermöglicht es Ihnen, Nicht-Stripe-Konversionen an Selgeo zu melden – Anmeldungen, Formulareinreichungen, kostenlose Testversionen, Upgrades oder beliebige benutzerdefinierte Ereignisse. Sie rufen sie von Ihrem Server nach einer Konversion auf, und Selgeo ordnet sie dem empfehlenden Partner basierend auf einer click_id oder einem promo_code zu.
API-Version: v1
Endpunkt: POST /api/v1/conversions
Voraussetzungen
- Das Selgeo-Snippet ist auf Ihrer Website installiert (Snippet-Setup), um
click_id-Werte zu erfassen - Ein geheimer API-Schlüssel (
sk_test_*odersk_live_*) aus dem Selgeo-Dashboard (Einstellungen > API-Schlüssel)
Authentifizierung
Die Conversion API verwendet geheime API-Schlüssel, die als Bearer-Token im Authorization-Header übergeben werden:
Authorization: Bearer sk_test_YOUR_KEY
| Schlüsselpräfix | Modus | Beschreibung |
|---|---|---|
sk_test_* | Test | Testmodus – Konversionen werden verfolgt, aber keine echten Provisionen |
sk_live_* | Live | Live-Modus – Konversionen erzeugen echte Provisionen |
Geheime Schlüssel (sk_*) dürfen nur in server-seitigem Code verwendet werden. Fügen Sie sie niemals in JavaScript ein, das im Browser, in mobilen Apps oder in einem anderen client-seitigen Code ausgeführt wird. Verwenden Sie öffentliche Schlüssel (pk_*) für das Tracking-Snippet.
Anforderungsformat
POST /api/v1/conversions
Content-Type: application/json
Authorization: Bearer sk_test_YOUR_KEY
Anforderungskörper
| Feld | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
click_id | string (UUID) | Bedingt | Die Klick-ID vom Tracking-Snippet. Erforderlich, wenn promo_code nicht angegeben ist. |
promo_code | string | Bedingt | Ein Promo-Code für die Attribution. Erforderlich, wenn click_id nicht angegeben ist. |
external_transaction_id | string | Ja | Ihr eindeutiger Bezeichner für diese Konversion (z. B. Bestell-ID, Anmelde-ID). Wird für die Deduplizierung verwendet. Max. 255 Zeichen. |
event_type | string | Ja | Der Typ des Konversionsereignisses (z. B. signup, purchase, upgrade, trial_start). Max. 100 Zeichen. |
amount_cents | integer | Nein | Der Konversionswert in Cent. Standard: 0. |
currency | string | Bedingt | ISO 4217 3-Buchstaben-Währungscode (z. B. EUR, USD). Erforderlich wenn amount_cents > 0. |
occurred_at | string (ISO 8601) | Nein | Zeitpunkt der Konversion. Standardmäßig die aktuelle Zeit. |
prospect_email | string (E-Mail) | Nein | Die E-Mail-Adresse des konvertierenden Benutzers. Wird für die Selbst-Empfehlungs-Betrugserkennung verwendet. |
metadata | object | Nein | Beliebige nicht-personenbezogene Schlüssel-Wert-Paare für Ihren eigenen Gebrauch. Keine personenbezogenen Daten oder besonderen Kategorien personenbezogener Daten aufnehmen. Max. 4 KB. |
Sie müssen entweder click_id oder promo_code (oder beides) angeben. Wenn keines angegeben ist, gibt die API einen 422-Fehler zurück.
metadataSenden Sie keine unnötigen personenbezogenen Daten und niemals besondere Kategorien personenbezogener Daten (Art. 9 DSGVO — z. B. Daten über Gesundheit, ethnische Herkunft, Religion oder politische Meinungen) im Feld metadata. Selgeo verarbeitet besondere Kategorien personenbezogener Daten nicht absichtlich und kann sie in Freitextfeldern nicht zuverlässig erkennen; sie herauszuhalten liegt daher in Ihrer Verantwortung als Verantwortlicher. Beachten Sie, dass prospect_email ein personenbezogenes Datum ist: Sie übermitteln es ausschließlich zur Erkennung von Selbstempfehlungsbetrug, und es wird unter Ihrer Verantwortung als Verantwortlicher verarbeitet.
Antwortformat
Eine erfolgreiche Antwort gibt 201 Created mit den Konversionsdetails und der Attributionsentscheidung zurück:
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"source": "conversion_api",
"event_type": "signup",
"external_transaction_id": "signup_12345",
"amount_cents": 0,
"currency": null,
"occurred_at": "2026-04-02T10:30:00.000Z",
"is_test": true,
"attributed": true,
"attribution": {
"attribution_event_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"attribution_source": "link",
"participant_id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
"explanation": "Attributed to partner via tracking link click"
},
"created_at": "2026-04-02T10:30:01.000Z"
}
Antwortfelder
| Feld | Typ | Beschreibung |
|---|---|---|
id | string (UUID) | Die Konversionsdatensatz-ID. null wenn die Attribution fehlgeschlagen ist. |
source | string | Immer "conversion_api" für diesen Endpunkt. |
event_type | string | Gibt Ihren event_type zurück. |
external_transaction_id | string | Gibt Ihre Transaktions-ID zurück. |
amount_cents | integer | Der Konversionswert. |
currency | string | null | Der Währungscode. |
occurred_at | string | Zeitpunkt der Konversion. |
is_test | boolean | true wenn ein Testschlüssel verwendet wird, false wenn ein Live-Schlüssel. |
attributed | boolean | true wenn die Konversion einem Partner zugeordnet wurde. |
attribution.attribution_event_id | string | null | Die Attributionsereignis-ID. null wenn nicht attributiert. |
attribution.attribution_source | string | null | "link" (klick-basiert) oder "code" (Promo-Code). null wenn nicht attributiert. |
attribution.participant_id | string | null | Die Teilnehmer-ID des Partners. null wenn nicht attributiert. |
attribution.explanation | string | Eine menschenlesbare Erklärung der Attributionsentscheidung. |
Interpretation der Attributionsentscheidung
attributed | attribution_source | Bedeutung |
|---|---|---|
true | "link" | Konversion wurde einem Partner über einen Tracking-Link-Klick zugeordnet. |
true | "code" | Konversion wurde einem Partner über einen Promo-Code zugeordnet. |
false | null | Keine Attribution. Das explanation-Feld beschreibt warum (z. B. abgelaufener Klick, ungültiger Promo-Code, Partner nicht aktiv). |
Attributionspriorität
Wenn sowohl click_id als auch promo_code in derselben Anfrage angegeben werden, hat der Promo-Code Priorität:
- Selgeo versucht zunächst die Attribution via
promo_code. - Wenn der Promo-Code gültig und mit einem aktiven Partner verknüpft ist, wird die Konversion via
"code"attributiert. - Wenn der Promo-Code ungültig oder inaktiv ist, fällt Selgeo auf die
click_id-Attribution zurück.
Diese Prioritätsreihenfolge stellt sicher, dass Partner, die Promo-Codes verteilen, Gutschriften erhalten, auch wenn der Kunde auch über den Tracking-Link eines anderen Partners angekommen ist.
Beispiele
Einfache Konversion mit click_id
- curl
- JavaScript (Node.js)
- Python
- PHP
curl -X POST https://app.selgeo.com/api/v1/conversions \
-H "Authorization: Bearer sk_test_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"click_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"external_transaction_id": "signup_12345",
"event_type": "signup",
"amount_cents": 0
}'
const response = await fetch('https://app.selgeo.com/api/v1/conversions', {
method: 'POST',
headers: {
'Authorization': 'Bearer sk_test_YOUR_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
click_id: 'f47ac10b-58cc-4372-a567-0e02b2c3d479',
external_transaction_id: 'signup_12345',
event_type: 'signup',
amount_cents: 0,
}),
});
const conversion = await response.json();
console.log('Attributiert:', conversion.attributed);
console.log('Partner:', conversion.attribution.participant_id);
import requests
response = requests.post(
"https://app.selgeo.com/api/v1/conversions",
headers={
"Authorization": "Bearer sk_test_YOUR_KEY",
"Content-Type": "application/json",
},
json={
"click_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"external_transaction_id": "signup_12345",
"event_type": "signup",
"amount_cents": 0,
},
)
conversion = response.json()
print(f"Attributiert: {conversion['attributed']}")
print(f"Partner: {conversion['attribution']['participant_id']}")
$ch = curl_init('https://app.selgeo.com/api/v1/conversions');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer sk_test_YOUR_KEY',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'click_id' => 'f47ac10b-58cc-4372-a567-0e02b2c3d479',
'external_transaction_id' => 'signup_12345',
'event_type' => 'signup',
'amount_cents' => 0,
]),
]);
$response = curl_exec($ch);
$conversion = json_decode($response, true);
echo "Attributiert: " . ($conversion['attributed'] ? 'ja' : 'nein') . "\n";
echo "Partner: " . $conversion['attribution']['participant_id'] . "\n";
curl_close($ch);
Bezahlte Konversion mit Betrag
- curl
- JavaScript (Node.js)
- Python
- PHP
curl -X POST https://app.selgeo.com/api/v1/conversions \
-H "Authorization: Bearer sk_test_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"click_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"external_transaction_id": "order_67890",
"event_type": "purchase",
"amount_cents": 9900,
"currency": "EUR"
}'
const response = await fetch('https://app.selgeo.com/api/v1/conversions', {
method: 'POST',
headers: {
'Authorization': 'Bearer sk_test_YOUR_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
click_id: 'f47ac10b-58cc-4372-a567-0e02b2c3d479',
external_transaction_id: 'order_67890',
event_type: 'purchase',
amount_cents: 9900,
currency: 'EUR',
}),
});
const conversion = await response.json();
import requests
response = requests.post(
"https://app.selgeo.com/api/v1/conversions",
headers={
"Authorization": "Bearer sk_test_YOUR_KEY",
"Content-Type": "application/json",
},
json={
"click_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"external_transaction_id": "order_67890",
"event_type": "purchase",
"amount_cents": 9900,
"currency": "EUR",
},
)
conversion = response.json()
$ch = curl_init('https://app.selgeo.com/api/v1/conversions');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer sk_test_YOUR_KEY',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'click_id' => 'f47ac10b-58cc-4372-a567-0e02b2c3d479',
'external_transaction_id' => 'order_67890',
'event_type' => 'purchase',
'amount_cents' => 9900,
'currency' => 'EUR',
]),
]);
$response = curl_exec($ch);
$conversion = json_decode($response, true);
curl_close($ch);
Promo-Code-Attribution
- curl
- JavaScript (Node.js)
- Python
- PHP
curl -X POST https://app.selgeo.com/api/v1/conversions \
-H "Authorization: Bearer sk_test_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"promo_code": "PARTNER20",
"external_transaction_id": "order_99999",
"event_type": "purchase",
"amount_cents": 4900,
"currency": "EUR"
}'
const response = await fetch('https://app.selgeo.com/api/v1/conversions', {
method: 'POST',
headers: {
'Authorization': 'Bearer sk_test_YOUR_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
promo_code: 'PARTNER20',
external_transaction_id: 'order_99999',
event_type: 'purchase',
amount_cents: 4900,
currency: 'EUR',
}),
});
const conversion = await response.json();
// conversion.attribution.attribution_source === "code"
import requests
response = requests.post(
"https://app.selgeo.com/api/v1/conversions",
headers={
"Authorization": "Bearer sk_test_YOUR_KEY",
"Content-Type": "application/json",
},
json={
"promo_code": "PARTNER20",
"external_transaction_id": "order_99999",
"event_type": "purchase",
"amount_cents": 4900,
"currency": "EUR",
},
)
conversion = response.json()
# conversion["attribution"]["attribution_source"] == "code"
$ch = curl_init('https://app.selgeo.com/api/v1/conversions');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer sk_test_YOUR_KEY',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'promo_code' => 'PARTNER20',
'external_transaction_id' => 'order_99999',
'event_type' => 'purchase',
'amount_cents' => 4900,
'currency' => 'EUR',
]),
]);
$response = curl_exec($ch);
$conversion = json_decode($response, true);
// $conversion['attribution']['attribution_source'] === 'code'
curl_close($ch);
Sowohl click_id als auch promo_code
Wenn beide angegeben werden, hat der Promo-Code Priorität:
curl -X POST https://app.selgeo.com/api/v1/conversions \
-H "Authorization: Bearer sk_test_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"click_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"promo_code": "PARTNER20",
"external_transaction_id": "order_55555",
"event_type": "purchase",
"amount_cents": 4900,
"currency": "EUR"
}'
Wenn PARTNER20 gültig ist, wird attribution_source "code" sein. Wenn PARTNER20 ungültig oder inaktiv ist, fällt Selgeo auf click_id zurück und attribution_source wird "link" sein.
click_id vom Frontend ans Backend übergeben
Ein häufiges Muster ist es, die click_id aus dem Snippet im Frontend zu lesen und sie mit der Formulareinreichung oder dem API-Aufruf zu senden:
// Frontend: click_id in Ihre Formulareinreichung einschließen
const form = document.getElementById('signup-form');
form.addEventListener('submit', (event) => {
event.preventDefault();
const clickId = __selgeo.getClickId();
const formData = new FormData(form);
fetch('/api/signup', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
email: formData.get('email'),
name: formData.get('name'),
clickId: clickId, // kann null sein
}),
});
});
Dann auf Ihrem Backend, nach der Verarbeitung der Anmeldung, rufen Sie die Conversion API auf:
// Backend: Konversion an Selgeo melden
app.post('/api/signup', async (req, res) => {
const { email, name, clickId } = req.body;
// 1. Anmeldung in Ihrem System verarbeiten
const user = await createUser({ email, name });
// 2. An Selgeo melden (nur wenn clickId vorhanden ist)
if (clickId) {
await fetch('https://app.selgeo.com/api/v1/conversions', {
method: 'POST',
headers: {
'Authorization': 'Bearer sk_test_YOUR_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
click_id: clickId,
external_transaction_id: `signup_${user.id}`,
event_type: 'signup',
amount_cents: 0,
}),
});
}
res.json({ success: true });
});
Wenn Sie traditionelle Formulareinreichungen (kein AJAX) verwenden, fügen Sie ein verstecktes Input-Feld hinzu, das das Snippet befüllt:
<form action="/api/signup" method="POST">
<input type="email" name="email" required />
<input type="hidden" name="clickId" id="selgeo-click-id" />
<button type="submit">Registrieren</button>
</form>
<script>
// Das versteckte Feld beim Laden des Formulars setzen
document.addEventListener('DOMContentLoaded', () => {
const clickId = typeof __selgeo !== 'undefined'
? __selgeo.getClickId()
: null;
if (clickId) {
document.getElementById('selgeo-click-id').value = clickId;
}
});
</script>
Fehlerbehandlung
HTTP-Statuscodes
| Status | Bedeutung | Aktion |
|---|---|---|
201 | Konversion erfolgreich erstellt | Lesen Sie das attributed-Feld, um zu prüfen, ob sie attributiert wurde |
400 | Validierungsfehler (fehlende/ungültige Felder) | Korrigieren Sie den Anforderungskörper gemäß den Fehlerdetails |
401 | Ungültiger oder fehlender API-Schlüssel | Prüfen Sie Ihren Authorization-Header und Schlüssel |
409 | Doppelte external_transaction_id | Diese Konversion wurde bereits gemeldet. Dies ist idempotent – keine Aktion erforderlich |
422 | Kein Attributionssignal oder Test/Live-Modus-Mismatch | Geben Sie entweder click_id/promo_code an, oder stellen Sie sicher, dass der Schlüsselmodus übereinstimmt (Test-click_id mit Testschlüssel) |
429 | Rate-Limit überschritten | Zurückhalten und wiederholen. Prüfen Sie den Retry-After-Header |
Fehler-Antwortformat
{
"statusCode": 400,
"message": "Validation failed",
"error": "Bad Request",
"code": "VALIDATION_ERROR"
}
Rate-Limits
Die Conversion API ist auf 120 Anfragen pro Minute pro geheimem Schlüsselpräfix begrenzt. Wenn Sie dieses Limit überschreiten, gibt die API 429 Too Many Requests mit einem Retry-After-Header zurück, der angibt, wie viele Sekunden zu warten sind.
Für Hochvolumen-Integrationen stapeln Sie Ihre Konversionen oder verteilen Sie sie über die Zeit. Wenn Sie konsequent höhere Limits benötigen, kontaktieren Sie den Support.
Deduplizierung
Das external_transaction_id-Feld wird zur Deduplizierung verwendet. Wenn Sie dieselbe external_transaction_id zweimal mit demselben geheimen Schlüssel senden, gibt die zweite Anfrage 409 Conflict zurück. Dies macht die API sicher für Wiederholungsversuche bei Netzwerkfehlern – Sie erstellen keine doppelten Konversionen.
Modus-Mismatch
Test-Modus-Schlüssel (sk_test_*) können Konversionen nur click_id-Werten zuordnen, die durch öffentliche Test-Modus-Schlüssel (pk_test_*) generiert wurden. Ebenso funktionieren Live-Modus-Schlüssel nur mit Live-Modus-Klick-IDs. Bei einem Mismatch gibt die API 422 mit dem Code MODE_MISMATCH zurück.
Testen
- Richten Sie ein Testprogramm und einen Partner ein. Erstellen Sie das Programm im Händler-Dashboard und laden Sie einen Testpartner ein, melden Sie sich dann als dieser Partner im Partner-Portal an und erstellen Sie einen Empfehlungslink (unter Links).
- Besuchen Sie Ihre Website über den Tracking-Link, um einen Klick zu registrieren.
- Lesen Sie die click_id aus der Browser-Konsole:
__selgeo.getClickId()
- Senden Sie eine Testkonversion von Ihrem Terminal:
curl -X POST https://app.selgeo.com/api/v1/conversions \-H "Authorization: Bearer sk_test_YOUR_KEY" \-H "Content-Type: application/json" \-d '{"click_id": "CLICK_ID_HIER_EINFÜGEN","external_transaction_id": "test_001","event_type": "signup","amount_cents": 0}'
- Prüfen Sie die Antwort –
attributedsolltetrueundattribution_sourcesollte"link"sein. - Überprüfen Sie im Dashboard – die Konversion sollte in Analytics erscheinen, dem Testpartner zugeordnet.
Nächste Schritte
- Webhooks – Benachrichtigungen erhalten, wenn Konversionen attributiert und Provisionen erstellt werden
- Stripe Metadata – wenn Sie auch Stripe für einige Konversionen verwenden
- Testmodus – detaillierter Leitfaden zum Testen Ihrer Integration
- Fehlerbehebung – häufige Probleme und Lösungen