APRESLY API V1
Połącz własny backend
Gotowy przykład w Node.js: autoryzacja, rejestracja leada, lookup i ponawianie żądań z obsługą Retry-After.
Sprawdzono z produkcyjnym API: 9 października 2026
Na tej stronie
Przygotuj backend
Ten przykład wymaga Node.js 22 lub nowszego i działa wyłącznie na serwerze. Zapisz klucz jako APRESLY_API_KEY w konfiguracji środowiska. Opublikuj kampanię i wybierz jej ID zgodnie z szybkim startem.
Pobierz moduł apresly-client.mjs i zapisz go obok swojego kodu. Moduł nie wysyła e-maili. Ponawia 429, 503 i brak odpowiedzi maksymalnie do trzech prób łącznie; dla 429 respektuje Retry-After.
Klient API
// Node.js 22+. Server-side only. Store the key in APRESLY_API_KEY.
const base = 'https://app.apresly.com/api/public/v1';
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
export class ApreslyApiError extends Error {
constructor(status, code, requestId) {
super(`Apresly API: ${code} (HTTP ${status})`);
this.status = status;
this.code = code;
this.requestId = requestId;
}
}
export async function apresly(path, body) {
const key = process.env.APRESLY_API_KEY;
if (!key) throw new Error('Set APRESLY_API_KEY on your server');
// Prevent accidentally sending credentials to a user-supplied URL.
if (!/^\/campaigns(?:\?(?:isDraft=false&)?limit=\d+(?:&afterId=\d+)?|\/[1-9]\d*\/leads(?:\/lookup)?)?$/.test(path)) {
throw new Error('Use a documented campaign path');
}
for (let attempt = 0; attempt < 3; attempt++) {
let response;
try {
response = await fetch(base + path, {
method: body === undefined ? 'GET' : 'POST',
headers: {
Authorization: `Bearer ${key}`,
...(body === undefined ? {} : { 'Content-Type': 'application/json' }),
},
...(body === undefined ? {} : { body: JSON.stringify(body) }),
signal: AbortSignal.timeout(10_000),
redirect: 'error',
});
} catch {
if (attempt === 2) {
// A lost response can follow successful registration. Reconcile before sending email.
throw new Error('API response unavailable; registration may have completed');
}
await sleep(1000 * 2 ** attempt);
continue;
}
if ([429, 503].includes(response.status) && attempt < 2) {
const rawRetryAfter = response.headers.get('Retry-After');
const retryAfter = rawRetryAfter === null ? NaN : Number(rawRetryAfter);
const delay = response.status === 429 && Number.isFinite(retryAfter) && retryAfter >= 0
? retryAfter * 1000
: 1000 * 2 ** attempt;
await response.body?.cancel();
await sleep(delay);
continue;
}
const requestId = response.headers.get('X-Request-Id');
let data;
try { data = await response.json(); }
catch { throw new ApreslyApiError(response.status, 'INVALID_RESPONSE', requestId); }
if (!response.ok) {
throw new ApreslyApiError(response.status, data.code || 'HTTP_ERROR', data.requestId || requestId);
}
return data;
}
}
Wywołanie po zapisie lub zakupie
Poniższy kod wykonuje prawdziwą rejestrację. Przed uruchomieniem zastąp ID kampanii, ID strony i testowy e-mail. Zapisz go jako integration.mjs, ustaw zmienną środowiskową klucza i uruchom node integration.mjs. Nie używaj tego przykładu jako publicznego endpointu bez własnej autoryzacji i walidacji.
import { apresly } from './apresly-client.mjs';
const campaigns = await apresly('/campaigns?isDraft=false&limit=50');
// Choose the intended campaign from campaigns.items, not blindly the first one.
const campaignId = 42; // Replace with your published campaign ID.
const email = '[email protected]'; // Replace with an email address you own.
const offer = await apresly(`/campaigns/${campaignId}/leads`, {
email,
language: 'pl',
});
// Select the intended page ID from your campaign configuration.
const pageId = 17; // Replace with your own page ID.
const offerUrl = offer.offerLinks.find(link => link.pageId === pageId)?.url;
// Map offerUrl, offer.deadline and offer.mailTimerUrl to your email tool.
// Check warnings and missing values before sending. Do not log this object.
// Before a reminder: read without registering again.
const reminder = await apresly(`/campaigns/${campaignId}/leads/lookup`, {
email,
language: 'pl',
});
const deadline = reminder.deadline === null ? null : Date.parse(reminder.deadline);
const canRemind = deadline !== null && Number.isFinite(deadline) && deadline > Date.now()
&& reminder.offerLinks.some(link => link.pageId === pageId);
// Only send when canRemind and your own delivery rules allow it.
Zadbaj o jednokrotną wysyłkę
Powiąż zdarzenie źródłowe, np. zakup, z jego stabilnym ID w swojej bazie. Zapisuj stan przetwarzania i wysyłki oraz wykorzystaj kolejkę lub outbox. Samo created nie gwarantuje jednokrotnej dostawy: pierwsza rejestracja może się udać, odpowiedź zaginąć, a ponowienie zwrócić created: false.
Gdy moduł zakończy się błędem braku odpowiedzi, sprawdź stan przez lookup przed dalszą wysyłką. Ponowna rejestracja nadal podlega ustawieniom resetu i cykli kampanii. Nie ponawiaj bez końca i nie traktuj każdego 404 jako powodu do nowej rejestracji.
Diagnostyka i prywatność
ApreslyApiError udostępnia status, code i requestId. Zapisuj te dane diagnostyczne, bez całej odpowiedzi, e-maila i linków. W panelu historii żądań wyszukaj ID. Przy błędach 400, 401, 409, 415 lub 422 popraw konfigurację, zamiast automatycznie ponawiać.
Kod pokazuje minimalnego klienta i warunki przed przypomnieniem. Obsługę triggera, magazyn deduplikacji, kolejkę i wysyłkę dopasuj do swojej aplikacji. Dokumentacja API opisuje wszystkie pola i ograniczenia.