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.

Następny poradnikRozwiązywanie problemów

UTKNĄŁEŚ?

Porozmawiajmy o Twojej integracji.

Napisz, co chcesz połączyć. Przy błędzie dołącz requestId i kod błędu, bez klucza API i danych klientów.

Napisz do nas