
# Zbuduj integrację od początku do końca

Ten przewodnik przeprowadzi Cię przez wszystko, czego potrzebujesz, aby uruchomić <span data-t="appName">Your AI Connector</span> z poziomu własnego kodu, bez konieczności otwierania panelu nawigacyjnego. Pod koniec zbudujesz minimalną integrację, która:

1. Uwierzytelnianie za pomocą klucza API
2. Tworzenie agenta AI i konfigurowanie jego zachowania jako asystenta
3. Podłączanie kanału komunikacji (jako przykładu używamy WhatsApp Web) i przypisywanie go do agenta
4. Importowanie kontaktów
5. Wysyłanie i odczytywanie wiadomości
6. Odczytywanie analityki
7. Subskrybowanie webhooków dla zdarzeń w czasie rzeczywistym

Każdy krok zawiera link do pełnego przewodnika po zasobach, dzięki czemu możesz zagłębić się w szczegóły, gdy będziesz tego potrzebować. Ta strona jest mapą; przewodniki po zasobach to teren.

> **Zanim zaczniesz.** Dostęp do API jest funkcją płatną. Jeśli Twój plan go nie obejmuje, każde żądanie zwróci `403`. Zobacz [Dostęp do API](../integrations/api-access.md), aby potwierdzić, że jest włączony, oraz [Uwierzytelnianie](authentication.md), aby poznać wszystkie sposoby przekazywania klucza.

Wszystkie poniższe ścieżki są względne względem podstawowego adresu URL:

```
https://api.youraiconnector.com/v1
```

---

## Krok 1 — Uzyskaj klucz API i wykonaj pierwsze żądanie

Twój klucz API znajduje się w aplikacji w sekcji **Ustawienia → Integracje → Klucz API** — jest to osobna sekcja w ramach Integracji, oddzielona od Webhooków, która pojawia się tylko wtedy, gdy plan obejmuje dostęp do API. Wygeneruj klucz, skopiuj go i przechowuj w bezpiecznym miejscu (w serwerowym magazynie sekretów lub zmiennej środowiskowej — nigdy w kodzie przeglądarki). Pełne instrukcje znajdują się w [Dostęp do API](../integrations/api-access.md).

Gdy już masz klucz, potwierdź jego działanie, wywołując punkt końcowy sprawdzania stanu (health endpoint). Istnieje kilka sposobów wysłania klucza; najprostszym jest parametr zapytania `?apiKey=`, ale w rzeczywistym kodzie preferuj nagłówek `X-API-Key`, aby klucz nigdy nie trafił do logów serwera ani historii przeglądarki.

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/health?apiKey=YOUR_API_KEY"
```

**JavaScript**

```javascript
const BASE = "https://api.youraiconnector.com/v1";
const headers = { "X-API-Key": "YOUR_API_KEY", "Content-Type": "application/json" };

const res = await fetch(`${BASE}/health`, { headers });
const data = await res.json();
console.log(data); // { "success": true, ... }
```

**Python**

```python
import requests

BASE = "https://api.youraiconnector.com/v1"
HEADERS = {"X-API-Key": "YOUR_API_KEY", "Content-Type": "application/json"}

res = requests.get(f"{BASE}/health", headers=HEADERS)
print(res.json())  # { "success": true, ... }
```

Każda udana odpowiedź jest zawinięta w tę samą kopertę — pole `success: true` oraz dane wynikowe. Błędy zwracają `success: false` z komunikatem `error` i kodem `error_code`. Zobacz [Błędy i stronicowanie](errors-and-pagination.md), aby uzyskać pełną listę oraz dowiedzieć się, jak punkty końcowe list stronicują dane za pomocą `?limit` i `?cursor`.

> **Limit szybkości.** Uwierzytelnione żądania są ograniczone do **300 na minutę** (z wyższym limitem 1200 na minutę na konto). Przekroczenie limitu zwraca `429`; wstrzymaj się i spróbuj ponownie.

---

## Krok 2 — Utwórz agenta AI

**Agent AI** to jednostka, która przechowuje zachowanie Twojego asystenta: jego instrukcje, cel, godziny pracy oraz sposób komunikacji z kontaktami. To on odpowiada na konwersacje, więc jest to naturalny pierwszy element do utworzenia.

Utwórz go za pomocą `POST /agents`. `name` to jedyne pole, które warto wysłać na początku; wszystko inne można ustawić za pomocą poniższego wywołania bot-config.

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/agents" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Inbound WhatsApp Leads",
    "language": "en"
  }'
```

**JavaScript**

```javascript
const res = await fetch(`${BASE}/agents`, {
  method: "POST",
  headers,
  body: JSON.stringify({
    name: "Inbound WhatsApp Leads",
    language: "en",
  }),
});
const { agent_id } = await res.json();
```

**Python**

```python
res = requests.post(
    f"{BASE}/agents",
    headers=HEADERS,
    json={"name": "Inbound WhatsApp Leads", "language": "en"},
)
agent_id = res.json()["agent_id"]
```

Pomyślne utworzenie zwraca `201` z nowym identyfikatorem:

```json
{
  "success": true,
  "agent_id": "abc123agent"
}
```

**Zapisz `agent_id`** — będziesz się do niego odwoływać podczas kierowania kanałów.

### Skonfiguruj asystenta

`PUT /agents/{agentId}/bot-config` ustawia zachowanie asystenta. *Scala* ono wysyłane pola z istniejącą konfiguracją, więc wszystko, co pominiesz, zostanie zachowane:

```bash
curl -X PUT "https://api.youraiconnector.com/v1/agents/abc123agent/bot-config" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "instructions": "Greet warmly, answer questions about our services, and offer to book a call.",
    "goal": "Book a discovery call.",
    "ai_speed": "balanced"
  }'
```

Ustaw godziny pracy za pomocą `PUT /agents/{agentId}/active-hours`, aby asystent odpowiadał tylko w godzinach pracy; poza tymi oknami nie odpowiada automatycznie.

> **Baza wiedzy.** Aby asystent odpowiadał na podstawie Twoich własnych treści, dołącz FAQ. Zobacz [przewodnik po FAQ](faqs.md).

> **Starsza wersja: klasyczne kampanie.** Konta, które nadal mają stronę **Kampanie**, tworzą to samo zachowanie asystenta w ramach kampanii (`POST /campaigns` z obiektem `type` i `bot`, a następnie `PUT /campaigns/{campaignId}/bot-config`). Pełna lista pól kampanii i kontrola cyklu życia znajdują się w [przewodniku po kampaniach](campaigns.md). Jeśli tworzysz coś nowego, utwórz agenta.

---

## Krok 3 — Połącz kanał

Agent potrzebuje sposobu na wysyłanie i odbieranie wiadomości. Z poziomu API można obsłużyć siedem przepływów połączeń: WhatsApp Business, WhatsApp Web, Instagram i Messenger razem (jeden wspólny przepływ Meta), konta osobiste na Instagramie, Telegram, LINE oraz Viber. Pozostałe kanały — w tym SMS, e-mail, widżet czatu i kanały niestandardowe — konfiguruje się w panelu, a nie przez REST. Po ich podłączeniu punkty końcowe dotyczące wiadomości, kontaktów i routingu działają na nich w dokładnie taki sam sposób. `GET /channels` to aktualne źródło informacji o tym, co faktycznie jest podłączone do danego konta:

```bash
curl "https://api.youraiconnector.com/v1/channels?apiKey=YOUR_API_KEY"
```

Pełny zestaw procesów łączenia/rozłączania dla każdego kanału został udokumentowany w [przewodniku po kanałach](channels.md). Poniżej przedstawiamy pełny proces dla **WhatsApp Web**, ponieważ pokazuje on najciekawszy schemat: proces parowania za pomocą kodu QR, który Twój wrapper musi wyrenderować i odpytywać.

### Przykład praktyczny: parowanie WhatsApp Web za pomocą kodu QR

Parowanie WhatsApp Web to taniec składający się z trzech wywołań — **start**, **pobranie kodu QR**, **odpytywanie do momentu połączenia**.

**1. Rozpocznij sesję parowania.** Podaj numer, który chcesz połączyć, w formacie E.164.

```bash
curl -X POST "https://api.youraiconnector.com/v1/channels/whatsapp-web/connections" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "phone_number": "+15551230000" }'
```

```javascript
await fetch(`${BASE}/channels/whatsapp-web/connections`, {
  method: "POST",
  headers,
  body: JSON.stringify({ phone_number: "+15551230000" }),
});
```

```python
requests.post(
    f"{BASE}/channels/whatsapp-web/connections",
    headers=HEADERS,
    json={"phone_number": "+15551230000"},
)
```

**2. Pobierz kod QR i pokaż go użytkownikowi.** Odpytuj o to co 10–15 sekund. Odpowiedź zawiera surowy ładunek `qr_code` (wyrenderuj go samodzielnie jako obraz QR) oraz gotowy do wyświetlenia `qr_data_url`.

```bash
curl "https://api.youraiconnector.com/v1/channels/whatsapp-web/connections/+15551230000/qr?apiKey=YOUR_API_KEY"
```

```json
{
  "success": true,
  "phone_number": "+15551230000",
  "status": "qr_pending",
  "qr_code": "2@abc...",
  "qr_data_url": "data:image/png;base64,iVBORw0KGgo..."
}
```

W interfejsie swojego wrappera wstaw `qr_data_url` bezpośrednio do `<img src="...">` i poproś użytkownika o zeskanowanie go z poziomu **WhatsApp → Połączone urządzenia** w telefonie. Jeśli kod QR wygaśnie (odpowiedź `410`), rozpocznij od kroku 1, aby uzyskać nowy.

**3. Odpytuj o status, aż do momentu połączenia.** Po zeskanowaniu przez użytkownika, kontynuuj odpytywanie punktu końcowego statusu, aż zgłosi on `connected` (usługa może również zgłosić `open`). Traktuj `disconnected` oraz `not_initialized` jako błędy krytyczne.

```python
import time

PHONE = "+15551230000"
while True:
    res = requests.get(
        f"{BASE}/channels/whatsapp-web/connections/{PHONE}/status",
        headers=HEADERS,
    )
    status = res.json()["status"]
    if status in ("connected", "open"):
        print("Connected!")
        break
    if status in ("disconnected", "not_initialized"):
        raise RuntimeError(f"Pairing failed: {status}")
    time.sleep(5)
```

```javascript
async function waitForConnection(phone) {
  while (true) {
    const res = await fetch(
      `${BASE}/channels/whatsapp-web/connections/${encodeURIComponent(phone)}/status`,
      { headers }
    );
    const { status } = await res.json();
    if (status === "connected" || status === "open") return;
    if (status === "disconnected" || status === "not_initialized") {
      throw new Error(`Pairing failed: ${status}`);
    }
    await new Promise((r) => setTimeout(r, 5000));
  }
}
```

> **Uwaga.** Każdy połączony numer WhatsApp Web wiąże się z cykliczną miesięczną opłatą za utrzymanie, dopóki go nie rozłączysz (`DELETE /channels/whatsapp-web/connections/{phoneNumber}`).

### Skieruj kanał do swojego agenta

Podłączenie kanału sprawia, że zaczyna on działać; skierowanie go informuje platformę, *który agent AI* powinien odpowiadać na zupełnie nowe przychodzące konwersacje. Ustaw domyślny punkt wejścia (Entry Point) dla kanału, podając nazwę agenta utworzonego w kroku 2:

```bash
curl -X PUT "https://api.youraiconnector.com/v1/entry-points/channel-defaults" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "channel": "whatsapp_web", "agent_id": "abc123agent" }'
```

Powtórz wywołanie dla każdego kanału — jeden domyślny punkt wejścia na kanał. Aby pozostawić kanał bez agenta, wywołaj `DELETE /entry-points/channel-defaults?channel=whatsapp_web`; aby sprawdzić, czy drabinka punktów wejścia jest aktywna dla konta, wywołaj `GET /entry-points/routing-status`. Starsza mapa `POST /channels/campaign` jest zachowana tylko w celu wycofania zmian i nie jest już używana do routingu przychodzącego. Zobacz [przewodnik po kanałach](channels.md), aby uzyskać informacje o innych typach kanałów oraz przepływie OAuth dla WhatsApp Business.

---

## Krok 4 — Import kontaktów

Gdy kanał jest aktywny, załaduj osoby, do których chcesz dotrzeć. Punkt końcowy importu przyjmuje do **500 rekordów na wywołanie**. Każdy rekord wymaga `phone_number` w formacie międzynarodowym; wszystko inne jest opcjonalne. Rekordy z błędnymi numerami, nieobsługiwanymi kanałami lub numerami, które już istnieją, są pomijane — każde pominięcie jest raportowane wraz z indeksem i powodem, dzięki czemu możesz ponowić próbę tylko dla nieudanych rekordów.

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/contacts/import" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "contacts": [
      { "phone_number": "+12025551234", "first_name": "Ann", "last_name": "Lee" },
      { "phone_number": "+12025551235", "first_name": "Bob" }
    ],
    "defaultChannel": "whatsapp_web"
  }'
```

**JavaScript**

```javascript
const res = await fetch(`${BASE}/contacts/import`, {
  method: "POST",
  headers,
  body: JSON.stringify({
    contacts: [
      { phone_number: "+12025551234", first_name: "Ann", last_name: "Lee" },
      { phone_number: "+12025551235", first_name: "Bob" },
    ],
    defaultChannel: "whatsapp_web",
  }),
});
const result = await res.json();
console.log(`${result.imported} imported, ${result.skipped.length} skipped`);
```

**Python**

```python
res = requests.post(
    f"{BASE}/contacts/import",
    headers=HEADERS,
    json={
        "contacts": [
            {"phone_number": "+12025551234", "first_name": "Ann", "last_name": "Lee"},
            {"phone_number": "+12025551235", "first_name": "Bob"},
        ],
        "defaultChannel": "whatsapp_web",
    },
)
result = res.json()
print(f"{result['imported']} imported, {len(result['skipped'])} skipped")
```

Odpowiedź informuje dokładnie, co się stało:

```json
{
  "success": true,
  "imported": 2,
  "contact_ids": ["contactId1", "contactId2"],
  "skipped": []
}
```

Aby uzyskać informacje na temat tworzenia pojedynczych rekordów, list/wyszukiwania, list, tagów i pól niestandardowych, zobacz [przewodnik po kontaktach](contacts.md).

---

## Krok 5 — Wysyłanie i odczytywanie wiadomości

### Wyślij wiadomość

Najprostszy sposób wysyłania jest **niezależny od kanału**: podaj tożsamość kontaktu oraz treść wiadomości, a platforma dostarczy ją za pośrednictwem kanału, z którego korzysta dany kontakt. Możesz kierować wiadomość według `contact_id` lub według `channel` oraz pasującego pola tożsamości (`phone_number` dla WhatsApp/WhatsApp Web/SMS, `instagram_id` dla Instagrama itd.).

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/contacts/send" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "channel": "whatsapp_web",
    "phone_number": "+12025551234",
    "body": "Hi Ann! Thanks for reaching out."
  }'
```

**JavaScript**

```javascript
const res = await fetch(`${BASE}/contacts/send`, {
  method: "POST",
  headers,
  body: JSON.stringify({
    channel: "whatsapp_web",
    phone_number: "+12025551234",
    body: "Hi Ann! Thanks for reaching out.",
  }),
});
const { message_id } = await res.json();
```

**Python**

```python
res = requests.post(
    f"{BASE}/contacts/send",
    headers=HEADERS,
    json={
        "channel": "whatsapp_web",
        "phone_number": "+12025551234",
        "body": "Hi Ann! Thanks for reaching out.",
    },
)
message_id = res.json()["message_id"]
```

Dostarczanie jest **asynchroniczne** — `201` oznacza, że wiadomość została *zaakceptowana i dodana do kolejki*, a nie jeszcze dostarczona. (Kontakty z włączonym trybem „nie przeszkadzać” lub trybem prywatnym są odrzucane z kodem `422`.)

```json
{
  "success": true,
  "message_id": "aB3dE5fG7hI9jK1lM2nO",
  "contact_id": "contact123",
  "channel": "whatsapp_web"
}
```

### Odczytaj konwersację

Aby odczytać wiadomości, wyświetl je według kontaktu, od najnowszych, korzystając z paginacji kursorem. Przekaż `next_cursor` z jednej odpowiedzi jako `cursor` w następnej, aby przeglądać historię wstecz.

```bash
curl "https://api.youraiconnector.com/v1/contacts/contact123/messages?limit=50&apiKey=YOUR_API_KEY"
```

```python
res = requests.get(
    f"{BASE}/contacts/contact123/messages",
    headers=HEADERS,
    params={"limit": 50},
)
page = res.json()
for msg in page["messages"]:
    print(msg)
next_cursor = page["next_cursor"]  # pass back as ?cursor= for the next page
```

Możesz również filtrować według typu zawartości (`?filter=text|media|tool_use`) lub kierunku (`?direction=inbound|outbound`). [Przewodnik po wiadomościach](messages.md) omawia załączniki multimedialne, oznaczanie wiadomości jako przeczytanych oraz widoki wiadomości w ramach sesji.

> **Nie odpytuj o odpowiedzi.** Wyświetlanie wiadomości w pętli czasowej działa, ale marnuje żądania i zwiększa opóźnienia. W przypadku wiadomości przychodzących użyj webhooków — to jest krok 7.

---

## Krok 6 — Odczyt analityki

Gdy wiadomości zaczną płynąć, podsumowanie analityczne dostarczy zagregowane liczby w wybranym zakresie dat: wysłane, dostarczone, odczytane, z odpowiedziami, zarezerwowane, utworzone kontakty oraz wydane/doładowane kredyty. Otrzymasz zarówno sumy dla zakresu, jak i szereg danych dziennych z wypełnionymi zerami — idealne do wykresu na pulpicie nawigacyjnym. Opcjonalnie możesz ograniczyć zakres do pojedynczej kampanii za pomocą `campaign_id` (poniższe przykłady używają przykładowego identyfikatora kampanii, `abc123campaign`); pomiń ten parametr, aby uzyskać sumy dla całego konta.

```bash
curl "https://api.youraiconnector.com/v1/analytics/summary?from=2026-05-01&to=2026-05-31&campaign_id=abc123campaign&apiKey=YOUR_API_KEY"
```

```javascript
const params = new URLSearchParams({
  from: "2026-05-01",
  to: "2026-05-31",
  campaign_id: "abc123campaign",
});
const res = await fetch(`${BASE}/analytics/summary?${params}`, { headers });
const { totals, by_date } = await res.json();
```

```python
res = requests.get(
    f"{BASE}/analytics/summary",
    headers=HEADERS,
    params={"from": "2026-05-01", "to": "2026-05-31", "campaign_id": "abc123campaign"},
)
data = res.json()
totals = data["totals"]
by_date = data["by_date"]
```

Domyślny zakres to ostatnie 30 dni, z limitem do 366 dni. Aby uzyskać szczegółowe rejestry zużycia kredytów oraz zestawienia kosztów AI, zapoznaj się z [przewodnikiem po analityce](analytics.md).

---

## Krok 7 — Subskrypcja webhooków dla zdarzeń w czasie rzeczywistym

Odpytywanie (polling) sprawdza się w prostych skryptach, ale profesjonalna integracja powinna być **oparta na modelu push**. Webhooki pozwalają platformie wywołać *Twój* serwer w momencie, gdy coś się wydarzy — pojawi się nowy kontakt, odpowiedź, umówione spotkanie lub zakończony czat.

Najpierw sprawdź dokładne nazwy zdarzeń, które możesz subskrybować:

```bash
curl "https://api.youraiconnector.com/v1/webhooks/events?apiKey=YOUR_API_KEY"
```

```json
{
  "success": true,
  "events": [
    "Contact Created",
    "Human Alerted",
    "Appointment Booked",
    "Replies",
    "New Message",
    "Chat Concluded",
    "Task Created",
    "Daily Summary Created"
  ]
}
```

Następnie utwórz subskrypcję wskazującą na adres HTTPS na Twoim serwerze. Użyj dokładnych ciągów znaków zdarzeń z powyższego wywołania.

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/webhooks" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://hooks.example.com/incoming",
    "subscribed_to": ["Contact Created", "Replies"],
    "name": "Lead updates hook"
  }'
```

**JavaScript**

```javascript
const res = await fetch(`${BASE}/webhooks`, {
  method: "POST",
  headers,
  body: JSON.stringify({
    url: "https://hooks.example.com/incoming",
    subscribed_to: ["Contact Created", "Replies"],
    name: "Lead updates hook",
  }),
});
const { webhook_id } = await res.json();
```

**Python**

```python
res = requests.post(
    f"{BASE}/webhooks",
    headers=HEADERS,
    json={
        "url": "https://hooks.example.com/incoming",
        "subscribed_to": ["Contact Created", "Replies"],
        "name": "Lead updates hook",
    },
)
webhook_id = res.json()["webhook_id"]
```

```json
{
  "success": true,
  "webhook_id": "1",
  "webhook": {
    "id": "1",
    "name": "Lead updates hook",
    "url": "https://hooks.example.com/incoming",
    "subscribed_to": ["Contact Created", "Replies"],
    "subscribed_to_tags": [],
    "created_at": "2026-06-09T12:00:00.000Z"
  }
}
```

Adres URL musi używać protokołu HTTPS i być publicznie dostępny. Od tego momentu Twój serwer będzie otrzymywał żądanie POST dla każdego subskrybowanego zdarzenia. Możesz wysłać testowe powiadomienie, sprawdzić stan subskrypcji oraz ponownie włączyć subskrypcję, która została automatycznie wyłączona po wielokrotnych błędach — zobacz [przewodnik po webhookach](webhooks.md) oraz stronę [Webhooki](../integrations/webhooks.md) na poziomie integracji, aby poznać formaty ładunków (payload) i weryfikację.

---

## Podsumowanie całości

Oto cały proces w skrócie:

| Krok | Cel | Kluczowe wywołanie |
|---|---|---|
| 1 | Uwierzytelnianie | `GET /health` |
| 2 | Utwórz i dostosuj asystenta | `POST /agents`, `PUT /agents/{id}/bot-config`, `PUT /agents/{id}/active-hours` |
| 3 | Połącz kanał i skonfiguruj trasowanie | `POST /channels/whatsapp-web/connections` → pobierz kod QR + status → `PUT /entry-points/channel-defaults` |
| 4 | Załaduj kontakty | `POST /contacts/import` |
| 5 | Wyślij i odczytaj | `POST /contacts/send`, `GET /contacts/{id}/messages` |
| 6 | Mierz wyniki | `GET /analytics/summary` |
| 7 | Reaguj w czasie rzeczywistym | `POST /webhooks` |

Minimalny wrapper to tylko te siedem wywołań zintegrowanych z Twoim własnym interfejsem. Następnie, w miarę potrzeb, możesz dodawać kolejne warstwy, korzystając z przewodników dla poszczególnych zasobów:

- [Kampanie](campaigns.md) · [Kontakty](contacts.md) · [FAQ](faqs.md) · [Wiadomości](messages.md) · [Spotkania](appointments.md)
- [Kanały](channels.md) · [Szablony](templates.md) · [Analityka](analytics.md) · [Webhooki](webhooks.md) · [Klucze API](api-keys.md)
- Jesteś tu nowy? [Wprowadzenie](getting-started.md) · [Uwierzytelnianie](authentication.md) · [Błędy i stronicowanie](errors-and-pagination.md)

Stuck on something this guide does not cover? Email [<span data-t="supportEmail">hi@youraiconnector.com</span>](mailto:hi@youraiconnector.com).
