Your AI Connector Docs

API kontaktów

Kontakt to pojedyncza osoba, do której wysyłasz wiadomości — obejmuje jej imię, numer telefonu, adres e-mail, kanał komunikacji, tagi, pola niestandardowe oraz listy i kampanie, do których należy. API kontaktów umożliwia tworzenie kontaktów, wyszukiwanie ich, aktualizowanie, tagowanie, importowanie masowe oraz usuwanie, a wszystko to bez konieczności korzystania z panelu nawigacyjnego.

Wszystkie ścieżki na tej stronie są względne względem bazowego adresu URL:

https://api.youraiconnector.com/v1

Zatem /contacts oznacza https://api.youraiconnector.com/v1/contacts.

Dopiero zaczynasz pracę z API? Najpierw przeczytaj Dostęp do API — zawiera informacje o tym, jak wygenerować klucz API, trzy sposoby uwierzytelniania, limity zapytań oraz format błędów. Wszystkie informacje na tej stronie zakładają, że masz już działający klucz API.


Informacje o identyfikatorach kontaktów

Każdy kontakt ma unikalny identyfikator (ID). Identyfikator, który otrzymujesz podczas tworzenia kontaktu (w data.contactId), jest tym samym identyfikatorem, którego używasz wszędzie indziej — do pobierania, aktualizowania, tagowania, wysyłania wiadomości lub usuwania tego kontaktu. Zapisz go raz i używaj ponownie.

Nie musisz tworzyć kontaktu, aby uzyskać jego identyfikator. Możesz go również wyszukać według numeru telefonu lub adresu e-mail (zobacz Pobierz kontakt) lub przeglądać wszystkie swoje kontakty (zobacz Lista kontaktów). Każda z tych metod zwraca ten sam identyfikator.


Tworzenie kontaktu

POST /contacts

Dodaje nowy kontakt do Twojego konta. Wymagany jest numer telefonu z kodem kraju — sam adres e-mail nie wystarczy. Wszystkie pozostałe pola są opcjonalne.

Możesz opcjonalnie dodać nowy kontakt bezpośrednio do jednej lub wielu list za pomocą listId (pojedyncza lista) lub listIds (tablica). Jeśli wysłane zostaną oba, listIds ma pierwszeństwo.

Każde pole, które wyślesz, a które nie jest jednym ze standardowych pól tworzenia wymienionych w poniższej tabeli pól Tworzenie kontaktu (phoneNumber, firstName, lastName, email, channel, is_bot_active, is_private, lead_profile, listId, listIds, custom_fields), jest automatycznie zapisywane jako pole niestandardowe — dzięki czemu płaska struktura danych z narzędzi takich jak Make czy Zapier działa bez konieczności zagnieżdżania. Możesz również przekazać jawny obiekt custom_fields.

Pole Wymagane Opis
phoneNumber Tak Numer telefonu kontaktu z kodem kraju (np. +15551234567).
firstName Nie Imię.
lastName Nie Nazwisko.
email Nie Adres e-mail.
channel Nie Kanał komunikacji. Jedna z wartości: whatsapp, sms, whatsapp_web. Domyślnie whatsapp.
is_bot_active Nie Czy asystent AI odpowiada na wiadomości tego kontaktu. Domyślnie true.
is_private Nie Oznacz kontakt jako prywatny. Gdy true, asystent AI jest dla niego wyłączony. Domyślnie false.
lead_profile Nie Notatki tekstowe dotyczące leada.
listId Nie Identyfikator pojedynczej listy, do której ma zostać dodany kontakt.
listIds Nie Tablica identyfikatorów list, do których ma zostać dodany kontakt (ma pierwszeństwo przed listId).
custom_fields Nie Obiekt zawierający własne pola klucz/wartość. Możesz je również przekazać jako klucze najwyższego poziomu.

cURL

curl -X POST "https://api.youraiconnector.com/v1/contacts?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "phoneNumber": "+15551234567",
    "firstName": "Jane",
    "lastName": "Smith",
    "email": "jane@example.com",
    "is_bot_active": true,
    "listIds": ["list123", "list456"]
  }'

JavaScript

const res = await fetch("https://api.youraiconnector.com/v1/contacts", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    phoneNumber: "+15551234567",
    firstName: "Jane",
    lastName: "Smith",
    email: "jane@example.com",
    is_bot_active: true,
    listIds: ["list123", "list456"],
  }),
});
const data = await res.json();
console.log(data.data.contactId);

Python

import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/contacts",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "phoneNumber": "+15551234567",
        "firstName": "Jane",
        "lastName": "Smith",
        "email": "jane@example.com",
        "is_bot_active": True,
        "listIds": ["list123", "list456"],
    },
)
print(res.json()["data"]["contactId"])

Odpowiedź

{
  "success": true,
  "data": {
    "message": "Successfully created new contact",
    "contactId": "contact_abc123",
    "listsAdded": ["list123", "list456"]
  }
}

Identyfikator nowego kontaktu znajduje się w data.contactId. Listy, do których został dodany, są zwracane w data.listsAdded.

Duplikaty nie są tworzone. Jeśli kontakt o tym samym numerze telefonu już istnieje, wywołanie tworzenia nie utworzy go ani nie zwróci. Odpowiedź wraca z kodem statusu HTTP 200 oraz error_code o wartości 409 w treści, dlatego należy rozgałęziać logikę na podstawie error_code, a nie statusu HTTP:

{ "success": false, "error_code": 409, "error": "A contact with this phone number already exists for the current user." }

Aby pracować z istniejącym kontaktem po otrzymaniu error_code o wartości 409, wyszukaj go za pomocą Pobierz kontakt według numeru telefonu lub adresu e-mailGET /contacts?phoneNumber=... — i użyj ponownie zwróconego identyfikatora.

Równoważne zapisy numerów WhatsApp są traktowane jako ten sam numer. Niektóre kraje mają dwa poprawne sposoby zapisu tego samego numeru telefonu komórkowego, a WhatsApp może zgłaszać dowolny z nich: Meksyk (+52… i starszy +521…), Brazylia (z dziewiątą cyfrą lub bez) oraz Argentyna (z 9 po +54 lub bez). Sprawdzanie duplikatów podczas tworzenia i GET /contacts?phoneNumber= działa dla obu zapisów, więc otrzymasz istniejący kontakt niezależnie od tego, w jakiej formie go wyślesz. phone_number zapisany w kontakcie nigdy nie jest nadpisywany.


Pobierz kontakt według numeru telefonu lub adresu e-mail

GET /contacts?phoneNumber=... lub GET /contacts?email=...

Wyszukuje pojedynczy kontakt i zwraca pełny, wzbogacony obiekt kontaktu — w tym jego listy, tagi i kampanie rozwiązane do par { id, name }, a także ostatnią wymienioną wiadomość.

Przekaż albo phoneNumber (w formacie międzynarodowym), albo email. Jeśli nie przekażesz żadnego z nich, ten sam punkt końcowy przełączy się w tryb Listowania kontaktów.

cURL

curl "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts?phoneNumber=%2B15551234567&apiKey=YOUR_API_KEY"

JavaScript

const phone = encodeURIComponent("+15551234567");
const res = await fetch(`https://api.youraiconnector.com/v1/contacts?phoneNumber=${phone}`, {
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
console.log(data.contact);

Python

import requests

res = requests.get(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts",
    headers={"X-API-Key": "YOUR_API_KEY"},
    params={"phoneNumber": "+15551234567"},
)
print(res.json()["contact"])

Odpowiedź

{
  "success": true,
  "contactId": "contact_abc123",
  "contact": {
    "id": "contact_abc123",
    "firstName": "Jane",
    "lastName": "Smith",
    "email": "jane@example.com",
    "phoneNumber": "+15551234567",
    "channel": "whatsapp",
    "isBotActive": true,
    "isPrivate": false,
    "doNotDisturb": false,
    "lead_profile": null,
    "avatarUrl": "https://example.com/photo.jpg",
    "customFields": {},
    "lists": [{ "id": "list123", "name": "VIP customers" }],
    "tags": [{ "id": "tagHotLead", "name": "Hot lead" }],
    "campaigns": [{ "id": "campaign789", "name": "Spring promo" }],
    "currentCampaign": { "id": "campaign789", "name": "Spring promo" },
    "lastMessage": {
      "direction": "inbound",
      "body": "Sounds good, thanks!",
      "status": "received",
      "timestamp": "2026-06-09T10:21:00.000Z"
    }
  }
}

Identyfikator kontaktu jest zwracany zarówno na najwyższym poziomie (contactId), jak i wewnątrz obiektu (contact.id). Jeśli nic nie pasuje, otrzymasz 404 z { "success": false, "message": "Contact not found" }.

avatarUrl to zdjęcie profilowe kontaktu, pobrane z WhatsApp lub Meta, gdy użytkownik wyśle do Ciebie wiadomość. Jest ono tylko do odczytu: nie możesz go ustawić i jest ono null dla kontaktów, które nie mają zdjęcia lub kontaktują się przez kanał, który go nie udostępnia. Traktuj ten link jako tymczasowy, zamiast go przechowywać, ponieważ niektóre z tych linków do zdjęć wygasają i są odświeżane automatycznie. (W poniższym punkcie końcowym listy ta sama wartość nazywa się avatar_url.)

Numery telefonów w adresach URL. Znak + w ciągu zapytania musi być zakodowany jako %2B, w przeciwnym razie zostanie odczytany jako spacja. Powyższe przykłady robią to za Ciebie.


Pobierz kontakt według identyfikatora

GET /contacts/{contactId}

Jeśli masz już identyfikator kontaktu, pobierz go bezpośrednio. Struktura odpowiedzi jest identyczna jak w przypadku wyszukiwania powyżej.

cURL

curl "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123?apiKey=YOUR_API_KEY"

JavaScript

const res = await fetch("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123", {
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
console.log(data.contact);

Python

import requests

res = requests.get(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
print(res.json()["contact"])

Identyfikator kontaktu, który nie istnieje na Twoim koncie, zwraca 404.


Pobierz statystyki kontaktu

GET /contacts/{contactId}/stats

Zwraca zagregowane statystyki wiadomości dla jednego kontaktu: sumy, odpowiedzi AI kontra ludzkie, zużyte kredyty oraz znaczniki czasu pierwszej i ostatniej wiadomości.

cURL

curl "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/stats?apiKey=YOUR_API_KEY"

JavaScript

const res = await fetch("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/stats", {
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
console.log(data.totalMessages, data.creditsUsed);

Python

import requests

res = requests.get(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/stats",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
print(data["totalMessages"], data["creditsUsed"])

Odpowiedź

{
  "success": true,
  "totalMessages": 48,
  "sent": 21,
  "received": 27,
  "aiReplies": 18,
  "humanReplies": 3,
  "creditsUsed": 34,
  "botMessageCount": 18,
  "firstMessageAt": "2026-05-01T09:00:00.000Z",
  "lastMessageAt": "2026-06-09T10:21:00.000Z"
}

botMessageCount to ten sam licznik wiadomości AI, który zeruje przycisk „reset” w aplikacji dla danego kontaktu. creditsUsed to bieżąca suma kredytów dla tego kontaktu, a nie tylko liczby z tej odpowiedzi. Identyfikator kontaktu, który nie istnieje na Twoim koncie, zwraca 404.


Listowanie kontaktów

GET /contacts

Wywołaj GET /contacts bez phoneNumber ani email, aby przeglądać wszystkie kontakty, zaczynając od najnowszych. Każda strona zwraca skrócone podsumowania kontaktów (listy, tagi i kampanie są zwracane jako tablice identyfikatorów, a nie pełne obiekty) oraz next_cursor.

Parametr zapytania Opis
limit Rozmiar strony. Domyślnie 50, maksymalnie 100.
cursor Wartość next_cursor z poprzedniej strony. Pomiń ją na pierwszej stronie.
listId Opcjonalne. Zwróć tylko kontakty należące do tej listy.

Aby przejść przez wszystkie strony: wykonaj pierwsze wywołanie bez kursora, a następnie przekazuj zwrócony next_cursor jako cursor. Zatrzymaj się, gdy next_cursor będzie null — oznacza to, że nie ma więcej wyników.

cURL

curl "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts?limit=50&apiKey=YOUR_API_KEY"

# next page:
curl "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts?limit=50&cursor=contact_abc123&apiKey=YOUR_API_KEY"

JavaScript

async function listAllContacts() {
  const all = [];
  let cursor = null;
  do {
    const url = new URL("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts");
    url.searchParams.set("limit", "100");
    if (cursor) url.searchParams.set("cursor", cursor);
    const res = await fetch(url, { headers: { "X-API-Key": "YOUR_API_KEY" } });
    const data = await res.json();
    all.push(...data.contacts);
    cursor = data.next_cursor;
  } while (cursor);
  return all;
}

Python

import requests

def list_all_contacts():
    all_contacts = []
    cursor = None
    while True:
        params = {"limit": 100}
        if cursor:
            params["cursor"] = cursor
        res = requests.get(
            "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts",
            headers={"X-API-Key": "YOUR_API_KEY"},
            params=params,
        )
        data = res.json()
        all_contacts.extend(data["contacts"])
        cursor = data["next_cursor"]
        if not cursor:
            break
    return all_contacts

Odpowiedź

{
  "success": true,
  "contacts": [
    {
      "id": "contact_abc123",
      "first_name": "Jane",
      "last_name": "Smith",
      "email": "jane@example.com",
      "phone_number": "+15551234567",
      "channel": "whatsapp",
      "is_bot_active": true,
      "is_private": false,
      "do_not_disturb": false,
      "avatar_url": "https://example.com/photo.jpg",
      "custom_fields": {},
      "created_at": "2026-06-01T09:00:00.000Z",
      "list_ids": ["list123"],
      "tag_ids": ["tagHotLead"],
      "campaign_ids": ["campaign789"],
      "current_campaign_id": "campaign789"
    }
  ],
  "next_cursor": "contact_abc123"
}

Uwaga: Filtrowanie według listId, który nie istnieje na Twoim koncie, zwraca 404. Nieprawidłowy cursor zwraca 400.


Liczba kontaktów

GET /contacts/count

Zwraca liczbę kontaktów pasujących do filtra oraz podział na kanały, bez konieczności stronicowania. Jest to właściwe wywołanie dla każdego pytania typu „ile” — kafelka na pulpicie nawigacyjnym, automatyzacji lub zapytania do Champa. Wszystkie filtry są opcjonalne, a łączenie kilku z nich zawęża wynik (kontakt musi spełniać każdy z nich).

Parametr zapytania Opis
agentId Tylko kontakty przypisane do tego agenta AI. Przekaż none dla kontaktów bez przypisanego agenta (są one obsługiwane przez domyślnego agenta kanału).
channel Tylko kontakty na tym kanale, np. whatsapp, messenger, instagram, sms, email, chat_widget.
tag Tylko kontakty z tą etykietą, według nazwy etykiety (wielkość liter nie ma znaczenia). Nazwa etykiety, której nie posiadasz, zwróci 404.
listId Tylko kontakty na tej liście.
botActive true lub false — tylko kontakty, których asystent AI jest włączony lub wyłączony.
status Tylko kontakty o tym statusie, np. Lead.
rules Obiekt reguł JSON zakodowany w formacie URL, używający tego samego kształtu co lista inteligentna (zobacz Kształt smart_rules poniżej). Nie można łączyć z innymi filtrami.

Jeśli nie wyślesz żadnego filtra, otrzymasz całkowitą liczbę kontaktów na swoim koncie.

cURL

# everything
curl "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/count?apiKey=YOUR_API_KEY"

# only the contacts one agent handles on Messenger
curl "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/count?agentId=agent_xyz789&channel=messenger&apiKey=YOUR_API_KEY"

JavaScript

const url = new URL("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/count");
url.searchParams.set("agentId", "agent_xyz789");
url.searchParams.set("channel", "messenger");

const res = await fetch(url, { headers: { "X-API-Key": "YOUR_API_KEY" } });
const data = await res.json();
console.log(data.total);

Python

import requests

res = requests.get(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/count",
    headers={"X-API-Key": "YOUR_API_KEY"},
    params={"agentId": "agent_xyz789", "channel": "messenger"},
)
data = res.json()
print(data["total"])

Odpowiedź

{
  "success": true,
  "total": 3423,
  "by_channel": { "messenger": 2744, "instagram": 667, "none": 12 },
  "filters": { "agentId": "agent_xyz789" }
}

by_channel dzieli tę samą sumę według kanałów; kontakty, które nie znajdują się na żadnym kanale, są liczone w none. filters zwraca zastosowane filtry, dzięki czemu możesz sprawdzić, czy wywołanie zadziałało zgodnie z oczekiwaniami.

Uwaga: Wysłanie rules wraz z jakimkolwiek innym filtrem lub wartością rules, która nie jest poprawnym kodem JSON, zwróci 400. Nazwa etykiety lub identyfikator listy, które nie istnieją na Twoim koncie, zwrócą 404.


Aktualizacja kontaktu

PUT /contacts/{contactId}

Aktualizuje istniejący kontakt. Zmieniane są tylko uwzględnione pola — pomiń wszystko, czego nie chcesz zmieniać. Musisz wysłać co najmniej jedno pole, w przeciwnym razie otrzymasz 400 („Brak pól do aktualizacji”).

Pole Opis
firstName Imię.
lastName Nazwisko.
email Adres e-mail.
is_bot_active Czy asystent AI odpowiada na wiadomości od tego kontaktu.
is_private Oznacz jako prywatny. Ustawienie tej wartości na true powoduje również wyłączenie asystenta AI.
do_not_disturb Wstrzymaj zautomatyzowaną komunikację z tym kontaktem. Powoduje również zatrzymanie odpowiedzi AI.
follow_ups_disabled Zatrzymaj wszystkie zautomatyzowane działania następcze dla tego kontaktu (szybkie, cykliczne i zimne leady), podczas gdy AI nadal odpowiada na wysyłane przez niego wiadomości. Przydatne po dokonaniu zakupu. Pozostaje wyłączone, dopóki nie ustawisz tego z powrotem na false.
lead_profile Notatki dotyczące leada w formie dowolnego tekstu.
custom_fields Obiekt pól niestandardowych. Scalane według klucza — zapisywane są tylko przesłane klucze, reszta istniejących pól niestandardowych zostaje zachowana. Możesz również przekazać klucze pól niestandardowych na najwyższym poziomie.

cURL

curl -X PUT "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "firstName": "Jane", "do_not_disturb": true }'

JavaScript

const res = await fetch("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123", {
  method: "PUT",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ firstName: "Jane", do_not_disturb: true }),
});
const data = await res.json();
console.log(data.message);

Python

import requests

res = requests.put(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"firstName": "Jane", "do_not_disturb": True},
)
print(res.json()["message"])

Odpowiedź

{
  "success": true,
  "message": "Contact updated successfully"
}

Pola niestandardowe są scalane, a nie zastępowane. Wysłanie { "custom_fields": { "tier": "gold" } } ustawia tylko tier — wszelkie inne pola niestandardowe w kontakcie pozostają bez zmian. Aby całkowicie usunąć pole niestandardowe ze wszystkich kontaktów, użyj Usuń pole niestandardowe.


Dodawanie lub usuwanie tagów

POST /contacts/{contactId}/tags

Dodaje i/lub usuwa tagi dla pojedynczego kontaktu w jednym wywołaniu. Przekaż identyfikatory tagów w addTagIds i removeTagIds. Co najmniej jedno z tych pól musi być niepuste.

Tagi muszą już istnieć na Twoim koncie — utwórz je najpierw za pomocą punktu końcowego tagów. Jeśli kontakt lub jakikolwiek powiązany tag nie istnieje, otrzymasz 404.

Pole Opis
addTagIds Tablica identyfikatorów tagów do dodania do kontaktu.
removeTagIds Tablica identyfikatorów tagów do usunięcia z kontaktu.

cURL

curl -X POST "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/tags?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "addTagIds": ["tagHotLead"], "removeTagIds": ["tagColdLead"] }'

JavaScript

const res = await fetch("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/tags", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    addTagIds: ["tagHotLead"],
    removeTagIds: ["tagColdLead"],
  }),
});
const data = await res.json();
console.log(data.added, data.removed);

Python

import requests

res = requests.post(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/tags",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"addTagIds": ["tagHotLead"], "removeTagIds": ["tagColdLead"]},
)
data = res.json()
print(data["added"], data["removed"])

Odpowiedź

{
  "success": true,
  "contact_id": "contact_abc123",
  "added": 1,
  "removed": 1
}

Zarządzaj biblioteką tagów

Te punkty końcowe służą do zarządzania samym tagiem — jego zmianą nazwy lub usunięciem z Twojego konta — w przeciwieństwie do przypisywania lub usuwania tagu u konkretnego kontaktu (zobacz Dodawanie lub usuwanie tagów powyżej). Każdy tag na Twoim koncie ma identyfikator (tagId): ten widoczny w menedżerze tagów w panelu nawigacyjnym oraz ten zwracany jako data.tag_id podczas tworzenia tagu za pomocą POST /tags i treści JSON { "name": "..." } (bez phoneNumber, email lub contactId).

Aktualizuj tag

PUT /tags/{tagId}

Wyślij tylko te pola, które zmieniasz.

Pole Opis
name Nazwa tagu.
curl -X PUT "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/tags/tagHotLead?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Hot lead (Q3)" }'

Odpowiedź

{ "success": true, "tag_id": "tagHotLead" }

tagId, który nie istnieje na Twoim koncie, zwraca 404.

Usuń tag

DELETE /tags/{tagId}

Usuwa jeden tag według identyfikatora. Tej operacji nie można cofnąć — kontakty posiadające ten tag po prostu go tracą. Usunięcie tagu, którego już nie ma (lub nigdy nie istniał), zwraca 200 z deleted: 0 zamiast 404, ponieważ nie ma czego wyliczać.

curl -X DELETE "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/tags/tagColdLead?apiKey=YOUR_API_KEY"

Odpowiedź

{ "success": true, "deleted": 1 }

Usuń kilka tagów jednocześnie

DELETE /tags

Pole Opis
tagIds Tablica identyfikatorów tagów do usunięcia (maks. 1000).
curl -X DELETE "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/tags?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "tagIds": ["tagColdLead", "tagUnsubscribed"] }'

Odpowiedź

{ "success": true, "deleted": 2 }

Identyfikatory, które nie istnieją lub należą do innego konta, są pomijane bez powiadomienia i nie są wliczane do deleted.


Masowe ustawianie flagi

POST /contacts/bulk-flag

Ustawia jedną flagę logiczną dla wielu kontaktów jednocześnie. Maksymalnie 500 identyfikatorów kontaktów na żądanie. Identyfikatory, które nie istnieją na Twoim koncie, są pomijane i zliczane w skipped.

Pole Opis
contactIds Tablica identyfikatorów kontaktów do zaktualizowania (maks. 500).
field Flaga do ustawienia. Jedna z bot_active (asystent AI włączony/wyłączony), dnd (wstrzymaj zautomatyzowany kontakt), spam, private.
value Wartość logiczna, na którą ma zostać ustawiona flaga.

cURL

curl -X POST "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/bulk-flag?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "contactIds": ["contactId1", "contactId2"],
    "field": "bot_active",
    "value": false
  }'

JavaScript

const res = await fetch("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/bulk-flag", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    contactIds: ["contactId1", "contactId2"],
    field: "bot_active",
    value: false,
  }),
});
const data = await res.json();
console.log(data.updated, data.skipped);

Python

import requests

res = requests.post(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/bulk-flag",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "contactIds": ["contactId1", "contactId2"],
        "field": "bot_active",
        "value": False,
    },
)
data = res.json()
print(data["updated"], data["skipped"])

Odpowiedź

{
  "success": true,
  "updated": 2,
  "skipped": 0
}

Masowy import kontaktów

POST /contacts/import

Tworzy do 500 kontaktów w jednym wywołaniu z tablicy JSON. Każdy rekord wymaga phone_number w formacie międzynarodowym; wszystko inne jest opcjonalne. Rekordy z nieprawidłowymi numerami telefonów lub nieobsługiwanymi kanałami są pomijane (nie są tworzone), a każdy pominięty rekord jest raportowany wraz z indeksem i powodem — dzięki temu możesz poprawić tylko te, które nie zostały przetworzone, i ponowić próbę.

Numery telefonów, które już istnieją na Twoim koncie, są domyślnie pomijane jako duplicate. Wyślij updateExisting: true, aby zamiast tego zaktualizować te kontakty: pola obecne w rekordzie nadpisują dane kontaktu (first_name, last_name, email, lead_profile i custom_fields są scalane klucz po kluczu), tags są dodawane, a kontakt jest dodawany do listId. Kanał, numer telefonu oraz flagi bota nigdy nie są zmieniane w istniejącym kontakcie.

Możesz opcjonalnie dodać każdy zaimportowany (lub zaktualizowany) kontakt do listy za pomocą listId, ustawić defaultChannel dla rekordów, które go nie określają, oraz otagować rekordy za pomocą tags (nazwy tagów — brakujące tagi są tworzone, istniejące są dopasowywane bez uwzględniania wielkości liter).

Pola najwyższego poziomu

Pole Wymagane Opis
contacts Tak Tablica rekordów kontaktów (maks. 500).
listId Nie Lista, do której ma zostać dodany każdy zaimportowany (i zaktualizowany) kontakt. Musi być listą na Twoim koncie.
defaultChannel Nie Kanał zastosowany do rekordów, które pomijają channel. Jeden z whatsapp, sms, whatsapp_web. Domyślnie whatsapp.
updateExisting Nie true, aby zaktualizować kontakty, których numer telefonu już istnieje, zamiast pomijać je jako duplicate. Domyślnie false.

Pola dla poszczególnych rekordów

Pole Wymagane Opis
phone_number Tak Numer telefonu w formacie międzynarodowym (wiodący + jest dodawany, jeśli go brakuje).
first_name Nie Imię.
last_name Nie Nazwisko.
email Nie Adres e-mail.
channel Nie Jeden z whatsapp, sms, whatsapp_web. W razie braku używa defaultChannel.
is_bot_active Nie Czy asystent AI odpowiada. Domyślnie true.
is_private Nie Oznacz jako prywatny. Domyślnie false.
lead_profile Nie Notatki o leadzie w formie dowolnego tekstu.
custom_fields Nie Obiekt z kluczami i wartościami pól niestandardowych.
tags Nie Tablica nazw tagów (działa również pojedynczy ciąg "a; b"). Tagi, które nie istnieją, są tworzone; istniejące są dopasowywane bez uwzględniania wielkości liter. Maks. 25 na rekord.

cURL

curl -X POST "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/import?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "contacts": [
      { "phone_number": "+12025551234", "first_name": "Ann", "last_name": "Lee", "tags": ["vip", "newsletter"] },
      { "phone_number": "+12025551235", "first_name": "Bob" }
    ],
    "listId": "list123",
    "defaultChannel": "whatsapp_web",
    "updateExisting": true
  }'

JavaScript

const res = await fetch("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/import", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    contacts: [
      { phone_number: "+12025551234", first_name: "Ann", last_name: "Lee", tags: ["vip", "newsletter"] },
      { phone_number: "+12025551235", first_name: "Bob" },
    ],
    listId: "list123",
    defaultChannel: "whatsapp_web",
    updateExisting: true,
  }),
});
const data = await res.json();
console.log(`Imported ${data.imported}, updated ${data.updated}, skipped ${data.skipped.length}`);

Python

import requests

res = requests.post(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/import",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "contacts": [
            {"phone_number": "+12025551234", "first_name": "Ann", "last_name": "Lee", "tags": ["vip", "newsletter"]},
            {"phone_number": "+12025551235", "first_name": "Bob"},
        ],
        "listId": "list123",
        "defaultChannel": "whatsapp_web",
        "updateExisting": True,
    },
)
data = res.json()
print(f"Imported {data['imported']}, updated {data['updated']}, skipped {len(data['skipped'])}")

Odpowiedź

{
  "success": true,
  "imported": 2,
  "contact_ids": ["contact_abc123", "contact_def456"],
  "updated": 0,
  "updated_contact_ids": [],
  "skipped": []
}

Jeśli niektóre rekordy nie mogą zostać utworzone, pojawią się w skipped wraz z powodem (tutaj bez updateExisting, więc istniejący numer jest pomijany):

{
  "success": true,
  "imported": 1,
  "contact_ids": ["contact_abc123"],
  "updated": 0,
  "updated_contact_ids": [],
  "skipped": [
    { "index": 1, "phone_number": "+12025551235", "reason": "duplicate" }
  ]
}

Z updateExisting: true to samo żądanie raportuje istniejący kontakt w sekcji updated / updated_contact_ids.

Możliwe przyczyny pominięcia: invalid_record, missing_phone_number, invalid_phone_number, invalid_channel, duplicate_in_request, duplicate, contact_limit_reached, create_failed.

Limity planu. Jeśli limit kontaktów w Twoim planie nie pozwala na dodanie tak dużej liczby nowych kontaktów, całe żądanie zostanie odrzucone na wstępie z kodem 403. Jeśli limit zostanie osiągnięty w trakcie przetwarzania, pozostałe rekordy zostaną zwrócone jako pominięte z przyczyną contact_limit_reached.


Importowanie kontaktów z pliku CSV

W przypadku importów większych niż obsługuje import masowy (do około 50 000 wierszy), należy dodać asynchroniczne zadanie importu dla pliku CSV znajdującego się już w pamięci masowej konta, a następnie odpytywać o jego status do momentu zakończenia.

Rozpoczęcie importu

POST /contacts/import-csv

Pole Wymagane Opis
csvStoragePath Tak Ścieżka w pamięci masowej do pliku CSV, w ramach users/{your account id}/imports/, kończąca się na .csv.
listName Tak Tworzy (lub ponownie wykorzystuje) listę o tej nazwie i dodaje do niej każdy zaimportowany kontakt.
existingListRefs Nie Tablica identyfikatorów istniejących list, do których również należy dodać każdy zaimportowany kontakt.
defaultChannel Nie Kanał przypisany do wierszy, które go nie określają.
curl -X POST "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/import-csv?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "csvStoragePath": "users/abc123/imports/leads.csv",
    "listName": "Webinar signups"
  }'

JavaScript

const res = await fetch("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/import-csv", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    csvStoragePath: "users/abc123/imports/leads.csv",
    listName: "Webinar signups",
  }),
});
const data = await res.json();
console.log(data.job_id);

Python

import requests

res = requests.post(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/import-csv",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "csvStoragePath": "users/abc123/imports/leads.csv",
        "listName": "Webinar signups",
    },
)
job_id = res.json()["job_id"]

Odpowiedź (202 — import został dodany do kolejki, jeszcze nie zakończony)

{
  "success": true,
  "job_id": "csvimp_abc123",
  "status": "queued"
}

Umieszczanie pliku w pamięci masowej. Ten punkt końcowy uruchamia i śledzi zadanie importu; sam w sobie nie przyjmuje przesyłanego pliku. Plik CSV musi już znajdować się w csvStoragePath przed wywołaniem tego punktu — własny importer CSV w panelu nawigacyjnym wykonuje to jako pierwszy krok.

Odpytywanie zadania importu

GET /contacts/import-csv/{jobId}

curl "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/import-csv/csvimp_abc123?apiKey=YOUR_API_KEY"

Odpowiedź

{
  "success": true,
  "job_id": "csvimp_abc123",
  "status": "completed",
  "imported": 812,
  "updated": 0,
  "skipped": 14,
  "errors": [],
  "error_message": null
}

status przechodzi przez etapy queuedprocessingcompleted lub failed z podaniem przyczyny w error_message. jobId, który nie istnieje na Twoim koncie, zwraca 404.


Eksportowanie kontaktów

Uruchamia asynchroniczny eksport kontaktów do pliku CSV i zwraca zadanie, którego status należy sprawdzać w celu potwierdzenia zakończenia.

Rozpocznij eksport

POST /contacts/export

Pole Wymagane Opis
listId Nie Eksportuj tylko kontakty należące do tej listy.
contactIds Nie Eksportuj tylko te konkretne identyfikatory kontaktów.

Pozostawienie obu pól pustych spowoduje wyeksportowanie wszystkich kontaktów na Twoim koncie.

curl -X POST "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/export?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "listId": "list123" }'

JavaScript

const res = await fetch("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/export", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ listId: "list123" }),
});
const data = await res.json();
console.log(data.job_id);

Python

import requests

res = requests.post(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/export",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"listId": "list123"},
)
job_id = res.json()["job_id"]

Odpowiedź (202 — eksport został dodany do kolejki)

{
  "success": true,
  "job_id": "export_abc123",
  "status": "queued"
}

Sprawdź status zadania eksportu

GET /contacts/export/{jobId}

curl "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/export/export_abc123?apiKey=YOUR_API_KEY"

Odpowiedź

{
  "success": true,
  "job_id": "export_abc123",
  "status": "completed",
  "export_id": "exp_xyz789",
  "contact_count": 812,
  "error_message": null
}

Gdy status będzie "completed", otrzymasz export_id oraz contact_count. Pobraniu wygenerowanego pliku CSV odbywa się ze strony Eksporty w Twoim panelu nawigacyjnym.


Wyślij wiadomość do kontaktu

POST /contacts/{contactId}/send-message

Wysyła wiadomość do istniejącego kontaktu za pośrednictwem kanału, z którego już korzysta. Wiadomość jest kolejkowana i dostarczana w tle — odpowiedź potwierdza jedynie przyjęcie żądania, a nie fakt dostarczenia wiadomości.

Pole Wymagane Opis
body Tak Treść wysyłanej wiadomości.
mediaUrl Nie URL pliku multimedialnego do załączenia.
mediaContentType Nie Typ MIME załączonych mediów (np. image/jpeg).

cURL

curl -X POST "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/send-message?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "body": "Hi! Your appointment is confirmed." }'

JavaScript

const res = await fetch("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/send-message", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ body: "Hi! Your appointment is confirmed." }),
});
const data = await res.json();
console.log(data.messageId);

Python

import requests

res = requests.post(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/send-message",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"body": "Hi! Your appointment is confirmed."},
)
print(res.json()["messageId"])

Odpowiedź

{
  "success": true,
  "messageId": "aB3dE5fG7hI9jK1lM2nO",
  "contactId": "contact_abc123",
  "channel": "whatsapp",
  "message": "Message created successfully. Delivery is being processed."
}

Nie można teraz wysłać? Jeśli kontakt ma włączony tryb „nie przeszkadzać” lub tryb prywatny, albo nie korzysta z kanału, który może odbierać wiadomości wychodzące, żądanie zostanie odrzucone z kodem 422 oraz wyjaśnieniem w polu error.

Aby wysłać wiadomość za pomocą numeru telefonu, identyfikatora Instagram lub innego identyfikatora kanału zamiast identyfikatora kontaktu — oraz aby dowiedzieć się więcej o przesyłaniu wiadomości — zobacz Messages API.


Przypisz agenta AI do kontaktu

POST /contacts/{contactId}/assign-agent

Przenosi istniejącą konwersację do innego agenta AI, począwszy od następnej wiadomości. Jest to to samo, co Przypisz agenta AI w menu czatu, oraz ten sam krok, którego używa akcja Przypisz agenta AI lub kampanię w Automatyzacjach.

Pole Wymagane Opis
agentId Tak Identyfikator agenta AI, który ma przejąć konwersację, lub null, aby usunąć przypisanie, dzięki czemu konwersacja wróci do skrzynki odbiorczej zespołu.
triggerAIResponse Nie true sprawia, że nowo przypisany agent natychmiast odpowiada na ostatnie nieodebrane wiadomości kontaktu. Wartość domyślna to false.

Zachowaj ostrożność przy triggerAIResponse: true — wysyła on wiadomość do kontaktu natychmiast, więc używaj go tylko wtedy, gdy chcesz, aby wiadomość została dostarczona teraz. W przypadku Messengera i Instagrama wiadomość nie zostanie wysłana, jeśli kontakt ostatnio napisał do Ciebie ponad 24 godziny temu.

cURL

curl -X POST "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/assign-agent?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "agentId": "agent_xyz789" }'

JavaScript

const res = await fetch("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/assign-agent", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ agentId: "agent_xyz789" }),
});
const data = await res.json();
console.log(data.data.agentId);

Python

import requests

res = requests.post(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/assign-agent",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"agentId": "agent_xyz789"},
)
print(res.json()["data"]["agentId"])

Odpowiedź

{
  "success": true,
  "data": {
    "contactId": "contact_abc123",
    "agentId": "agent_xyz789",
    "aiResponseTriggered": false
  }
}

Agent musi należeć do tego samego konta co kontakt; w przeciwnym razie żądanie zostanie odrzucone z błędem 404 lub 403. Identyfikatory agentów można znaleźć na stronie Agentów AI (adres URL każdego agenta kończy się jego identyfikatorem).


Przypisz agenta AI do wielu kontaktów

POST /contacts/bulk-assign-agent

Przenosi wiele konwersacji do innego agenta AI w jednym wywołaniu — lub usuwa przypisanie dla nich wszystkich za pomocą null. Jest to czysta zmiana routingu: żadna wiadomość nie jest wysyłana, a agent nikomu nie odpowiada. Każdy kontakt po prostu otrzymuje nowego agenta, gdy napisze następnym razem. (Dlatego nie ma tutaj triggerAIResponse).

Pole Wymagane Opis
agentId Tak Agent AI, który powinien przejąć obsługę, lub null, aby usunąć przypisanie.
contactIds Jedno z trzech Do 500 identyfikatorów kontaktów do przeniesienia.
filter Jedno z trzech Wybierz kontakty na serwerze zamiast ich wypisywania, od najnowszych. Przyjmuje te same klucze co filtry punktu końcowego liczby: agentId (lub none), channel, tag, listId, botActive, status.
rules Jedno z trzech Obiekt reguł listy inteligentnej — zobacz Kształt smart_rules.
limit Nie Ile kontaktów przenieść w tym wywołaniu przy wyborze za pomocą filter lub rules. Od 1 do 500, domyślnie 500.

Wyślij dokładnie jeden z parametrów contactIds, filter lub rules.

cURL

curl -X POST "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/bulk-assign-agent?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "agentId": "agent_xyz789",
    "filter": { "agentId": "agent_abc123", "channel": "messenger" }
  }'

JavaScript

const res = await fetch("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/bulk-assign-agent", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    agentId: "agent_xyz789",
    filter: { agentId: "agent_abc123", channel: "messenger" },
  }),
});
const data = await res.json();
console.log(data.updated, data.remaining);

Python

import requests

res = requests.post(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/bulk-assign-agent",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "agentId": "agent_xyz789",
        "filter": {"agentId": "agent_abc123", "channel": "messenger"},
    },
)
data = res.json()
print(data["updated"], data["remaining"])

Odpowiedź

{
  "success": true,
  "agentId": "agent_xyz789",
  "matched": 3415,
  "updated": 500,
  "skipped": 0,
  "remaining": 2915,
  "filters": { "agentId": "agent_abc123" }
}

matched to liczba kontaktów znalezionych w sumie, updated to liczba kontaktów przeniesionych tym wywołaniem, skipped to liczba przesłanych identyfikatorów, których nie znaleziono na koncie, a remaining to liczba kontaktów, które nadal pasują do kryteriów po zakończeniu wywołania.

Przenoszenie wszystkich. Ponieważ jedno wywołanie przenosi maksymalnie 500 kontaktów, duża grupa wymaga kilku wywołań. Użyj filtra, który przestaje pasować do kontaktu po jego przeniesieniu — na przykład filter: { "agentId": "agent_abc123" } podczas przypisywania do agent_xyz789 — i powtarzaj to samo wywołanie, aż remaining zwróci 0. Gdy zamiast tego przekażesz contactIds, remaining zawsze wynosi 0.


Przypisz kontakt do działu

POST /contacts/{contactId}/department

„Przypisz ten lead do działu sprzedaży” — przypisuje kontakt do nazwanego działu i domyślnie przekazuje go osobie w tym dziale, która ma obecnie najmniej kontaktów. Jest to oddzielne działanie od przypisywania agenta AI: dział odpowiada na pytanie „który zespół jest właścicielem tego kontaktu”, agent odpowiada na pytanie „który agent AI odpowiada za ten kontakt”, a ustawienie jednego nigdy nie usuwa drugiego.

Pole Wymagane Opis
department_id Tak Dział, do którego ma zostać przypisany kontakt. Przekaż null, aby wyczyścić to pole.
hand_to_member Nie Dodatkowo przekaż kontakt osobie z najmniejszą liczbą zadań w tym dziale. Wartość domyślna to true. Nigdy nie zmienia przypisania kontaktu, który ma już właściciela.

cURL

curl -X POST "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/department?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "department_id": "dept_sales" }'

JavaScript

const res = await fetch("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/department", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ department_id: "dept_sales" }),
});
const data = await res.json();
console.log(data.assigned_to);

Python

import requests

res = requests.post(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/department",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"department_id": "dept_sales"},
)
print(res.json()["assigned_to"])

Odpowiedź

{
  "success": true,
  "department_id": "dept_sales",
  "assigned_to": "member_uid_123"
}

assigned_to jest null, gdy kontakt miał już właściciela lub przekazano hand_to_member: false.


Połącz kontakt między kanałami

„Kontynuuj na WhatsApp” (lub SMS) znajduje lub tworzy kontakt tej osoby w innym kanale opartym na numerze telefonu i łączy je ze sobą, dzięki czemu reszta aplikacji rozpoznaje je jako tę samą osobę.

Łączenie z innym kanałem

POST /contacts/{contactId}/link-channel

Pole Wymagane Opis
channel Tak Kanał, z którym należy nawiązać połączenie. Jeden z whatsapp, whatsapp_web, sms.
phoneNumber Nie Numer telefonu używany w nowym kanale. Domyślnie jest to własny numer kontaktu źródłowego.
curl -X POST "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/link-channel?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "channel": "sms" }'

Odpowiedź

{
  "success": true,
  "data": {
    "contact_id": "contact_def456",
    "person_id": "person_xyz789",
    "created": true
  }
}

created informuje, czy dla kanału docelowego utworzono nowy kontakt, czy znaleziono i połączono istniejący. Ponowne wywołanie tej metody jest bezpieczne — zwraca ten sam contact_id z created: false zamiast tworzyć duplikat.

422 oznacza, że konto nie może obecnie wykonać tego połączenia: kontakt znajduje się już w tej rodzinie kanałów, nie ma numeru telefonu do użycia lub nie ma połączonego nadawcy dla kanału docelowego. 409 oznacza, że oba kontakty są już powiązane z dwiema różnymi osobami — najpierw należy rozłączyć jeden z nich.

Wyświetlanie listy połączonych konwersacji kontaktu

GET /contacts/{contactId}/linked

Zwraca pozostałe konwersacje, które należą do tej samej osoby co dany kontakt. Rozłączony kontakt zwraca pustą tablicę, a nie 404 — „ta osoba nie ma innych kanałów” jest normalnym stanem.

curl "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/linked?apiKey=YOUR_API_KEY"

Odpowiedź

{
  "success": true,
  "data": [
    {
      "contact_id": "contact_def456",
      "channel": "sms",
      "custom_channel": null,
      "first_name": "Jane",
      "last_name": "Smith",
      "phone_number": "+15551234567",
      "last_message": "Sounds good, thanks!",
      "last_message_timestamp": "2026-06-09T10:21:00.000Z",
      "linked_from": {
        "contact_id": "contact_abc123",
        "channel": "whatsapp",
        "linked_at": "2026-06-01T09:00:00.000Z",
        "reason": "continue_on_channel"
      }
    }
  ]
}

Rozłączanie kontaktu

DELETE /contacts/{contactId}/link

Usuwa ten kontakt z jego osoby jednostronnie — wszelkie inne kontakty nadal powiązane z tą osobą zachowują swoje połączenie, więc rozłączenie jednego z trzech nie powoduje rozwiązania grupy.

curl -X DELETE "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/link?apiKey=YOUR_API_KEY"

Odpowiedź

{ "success": true }

Pobieranie zdjęcia profilowego kontaktu

POST /contacts/{contactId}/profile-pic

Pobiera (i buforuje) zdjęcie profilowe kontaktu z WhatsApp lub Meta na żądanie — to samo zdjęcie, które jest zwracane jako avatarUrl w Pobierz kontakt, po odświeżeniu.

curl -X POST "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/profile-pic?apiKey=YOUR_API_KEY"

Odpowiedź

{
  "success": true,
  "avatar_url": "https://example.com/photo.jpg",
  "cached": false
}

cached: true oznacza, że adres URL pochodzi z niedawnego pobrania, a nie ze świeżego wyszukiwania u dostawcy — zdjęcia są buforowane przez 7 dni, a kontakt, dla którego dostawca zgłasza brak dostępnego zdjęcia, jest buforowany jako niedostępny przez 24 godziny. Gdy nie ma zdjęcia do pobrania, avatar_url jest pomijane, a message wyjaśnia przyczynę.


Automatyczne tagowanie kontaktów za pomocą AI

Uruchamia reguły tagowania Twojego konta dla pełnej historii konwersacji jednego lub większej liczby kontaktów i stosuje (lub usuwa) tagi dokładnie tak samo, jak tagowanie w czasie rzeczywistym podczas czatu na żywo — te same reguły, ten sam koszt kredytów za tag.

Rozpocznij uruchomienie

POST /contacts/auto-tag

Pole Wymagane Opis
scope Tak "contacts", aby otagować określone kontakty, lub "agent", aby otagować każdą konwersację obsługiwaną obecnie przez jednego agenta AI.
contact_ids Wymagane, gdy scope to "contacts" Tablica identyfikatorów kontaktów, od 1 do 500.
agent_id Wymagane, gdy scope to "agent" Agent AI, którego konwersacje mają zostać otagowane. Gdy scope to "contacts", jest to opcjonalne i jedynie zawęża zakres reguł tagowania agenta, które zostaną uruchomione.
curl -X POST "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/auto-tag?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "scope": "contacts", "contact_ids": ["contact_abc123", "contact_def456"] }'

Dla pojedynczego kontaktu uruchomienie następuje w trybie inline i zwraca wynik natychmiast:

{ "success": true, "result": { "tags_applied": 2, "tags_removed": 0 } }

Dwa lub więcej kontaktów (lub scope: "agent") uruchamianych jest jako zadanie w tle i zwraca 202 natychmiast:

{ "success": true, "run_id": "m1x2y3-a1b2c3d4", "total": 214 }

Odpytywanie o stan uruchomienia

GET /contacts/auto-tag/run

Zwraca bieżące (lub ostatnie) uruchomienie konta, dzięki czemu możesz odpytywać o postęp bez samodzielnego śledzenia run_id.

curl "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/auto-tag/run?apiKey=YOUR_API_KEY"

Odpowiedź

{
  "success": true,
  "run": {
    "run_id": "m1x2y3-a1b2c3d4",
    "status": "running",
    "total": 214,
    "processed": 58,
    "tagged_contacts": 12,
    "tags_applied": 15,
    "tags_removed": 2,
    "credits_charged": 15
  }
}

run to null, gdy konto nigdy nie rozpoczęło żadnego uruchomienia. status zmienia się z "running" na "completed" lub "failed".

Na koncie może trwać tylko jedno uruchomienie masowe jednocześnie — rozpoczęcie drugiego, gdy inne jest w toku, zwraca 409 z error_code: "auto_tag_run_in_progress". Brak kredytów przy uruchomieniu dla pojedynczego kontaktu zwraca 402 z error_code: "insufficient_credits"; uruchomienie masowe natomiast zatrzymuje się wcześniej i raportuje postęp w run.


Usuwanie kontaktu

DELETE /contacts/{contactId}

Trwale usuwa jeden kontakt według identyfikatora, wraz z jego historią wiadomości. Tej operacji nie można cofnąć. Aby usunąć kilka kontaktów w jednym wywołaniu, użyj Usuń kontakty poniżej.

cURL

curl -X DELETE "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123?apiKey=YOUR_API_KEY"

JavaScript

const res = await fetch("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123", {
  method: "DELETE",
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
console.log(data.success);

Python

import requests

res = requests.delete(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
print(res.json()["success"])

Odpowiedź

{
  "success": true
}

Identyfikator kontaktu, który nie istnieje na Twoim koncie lub należy do innego konta, zwraca 404.


Usuń kontakty

DELETE /contacts

Trwale usuwa jeden lub więcej kontaktów według identyfikatora w jednym wywołaniu (do 500 identyfikatorów). Identyfikatory, które nie istnieją na Twoim koncie, zostaną pominięte i uwzględnione w skipped. Tej operacji nie można cofnąć.

Pole Opis
contactIds Tablica identyfikatorów kontaktów do usunięcia (maks. 500).

cURL

curl -X DELETE "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "contactIds": ["contactId1", "contactId2"] }'

JavaScript

const res = await fetch("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts", {
  method: "DELETE",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ contactIds: ["contactId1", "contactId2"] }),
});
const data = await res.json();
console.log(`Deleted ${data.deleted}, skipped ${data.skipped}`);

Python

import requests

res = requests.delete(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"contactIds": ["contactId1", "contactId2"]},
)
data = res.json()
print(f"Deleted {data['deleted']}, skipped {data['skipped']}")

Odpowiedź

{
  "success": true,
  "deleted": 2,
  "skipped": 0
}

Usuwanie pola niestandardowego

DELETE /contacts/custom-fields/{fieldKey}

Usuwa jeden klucz pola niestandardowego z każdego kontaktu na Twoim koncie. Użyj tej funkcji, aby posprzątać po zmianie nazwy lub wycofaniu pola niestandardowego. Klucz może zawierać tylko litery, cyfry, podkreślniki i myślniki. Zwraca liczbę zaktualizowanych kontaktów. Tej operacji nie można cofnąć.

cURL

curl -X DELETE "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/custom-fields/webinar_date_nh?apiKey=YOUR_API_KEY"

JavaScript

const res = await fetch("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/custom-fields/webinar_date_nh", {
  method: "DELETE",
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
console.log(`Removed from ${data.updated} contacts`);

Python

import requests

res = requests.delete(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/custom-fields/webinar_date_nh",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
print(f"Removed from {res.json()['updated']} contacts")

Odpowiedź

{
  "success": true,
  "updated": 42
}

Uwaga: Klucz pola zawierający niedozwolone znaki zwróci 400.


Listy

Listy grupują kontakty. Lista może być statyczna (sam decydujesz, kto się na niej znajduje) lub inteligentna (członkostwo jest obliczane na podstawie reguł i automatycznie aktualizowane — zobacz Organizowanie list i kontaktów).

Pole Opis
name Wymagane przy tworzeniu. Maksymalnie 100 znaków.
status live (domyślnie) lub draft. Małe litery.
contact_ids Tablica identyfikatorów kontaktów do umieszczenia na liście. Tylko listy statyczne.
type static (domyślnie) lub smart.
smart_rules Zestaw reguł — wymagany, gdy type to smart. Zobacz poniżej.

Tworzenie listy

POST /lists

curl -X POST "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/lists?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
        "name": "Hot leads (active)",
        "type": "smart",
        "smart_rules": {
          "match": "all",
          "conditions": [
            { "field": "tags", "op": "has_any", "value": ["tagHotLead"] },
            { "field": "last_activity_at", "op": "within_last", "value": { "amount": 90, "unit": "days" } }
          ]
        }
      }'

Odpowiedź

{
  "success": true,
  "list_id": "list_abc123",
  "evaluation": { "added": 3, "removed": 0, "total": 3 }
}

Lista inteligentna jest oceniana wewnątrz tego samego żądania, więc evaluation informuje dokładnie, kto się na niej znalazł. W przypadku listy statycznej evaluation to null.

Aktualizacja listy

PUT /lists/{listId}

Prześlij tylko te pola, które zmieniasz. Zmiana smart_rules powoduje natychmiastową ponowną ocenę listy i zwraca ten sam obiekt evaluation.

curl -X PUT "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/lists/list_abc123?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "smart_rules": { "match": "any", "conditions": [ { "field": "tags", "op": "has_any", "value": ["tagHotLead", "tagWebinar"] } ] } }'

Możesz przełączać listę między dwoma rodzajami:

  • Statyczna → inteligentna: wyślij { "type": "smart", "smart_rules": { … } }. Reguły zaczną działać natychmiast.
  • Inteligentna → statyczna: wyślij { "type": "static" }. Reguły zostaną usunięte, a osoby znajdujące się na liście pozostaną na niej.

Struktura smart_rules

{
  "match": "all",
  "conditions": [
    { "field": "tags", "op": "has_any", "value": ["tagHotLead"] },
    { "field": "channel", "op": "is_any", "value": ["whatsapp", "sms"] },
    { "field": "last_incoming_message_at", "op": "not_within_last", "value": { "amount": 7, "unit": "days" } },
    { "field": "created_at", "op": "after", "value": "2026-01-01" },
    { "field": "is_bot_active", "op": "is", "value": true },
    { "field": "email", "op": "is_set" },
    { "field": "custom_field", "key": "Plan", "op": "eq", "value": "pro" }
  ]
}
  • matchall (każdy warunek musi być spełniony) lub any (przynajmniej jeden).
  • conditions — od 1 do 20 warunków, każdy z maksymalnie 100 wartościami, ciągi znaków do 200 znaków.
field op value
tags has_any, has_all, has_none tablica identyfikatorów tagów
lists in_any, not_in_any tablica identyfikatorów list (tylko listy statyczne — inteligentna lista nie może być utworzona na podstawie innej inteligentnej listy)
channel is_any, is_none tablica kanałów
status is_any, is_none tablica statusów kontaktu
created_at, last_activity_at, last_incoming_message_at, last_outgoing_message_at, first_ai_interaction_at, last_ai_interaction_at within_last, not_within_last { "amount": 1–3650, "unit": "hours" | "days" }
te same pola daty before, after data ISO ("2026-01-01", porównywana jako pełne dni) lub pełna data i godzina ISO ("2026-01-01T14:30:00Z", porównywana z dokładnym momentem)
te same pola daty is_set, not_set
has_interacted_with_ai is true / falsetrue dopasowuje kontakty, do których AI wysłało wiadomość przynajmniej raz (kiedykolwiek)
is_bot_active, do_not_disturb, is_private, has_ever_responded is true / false
email, phone_number, first_name, last_name is_set, not_set, contains, not_contains ciąg znaków dla formularzy contains
current_campaign_id, assigned_agent is_any, is_none, is_set, not_set tablica identyfikatorów dla formularzy is_any / is_none
custom_field (plus key) eq, neq, contains, not_contains, is_set, not_set ciąg znaków dla formularzy wartości

not_within_last dopasowuje również kontakty, dla których data nigdy nie została ustawiona („więcej niż N temu, lub nigdy”), a porównania tekstowe ignorują wielkość liter.

Zaangażowanie AI. has_interacted_with_ai to flaga dożywotnia: true dla każdego kontaktu, do którego Twoje AI wysłało przynajmniej jedną wiadomość, false dla wszystkich pozostałych (w tym kontaktów, na które odpowiadał tylko Twój zespół). Jest ona nadawana przy pierwszej wiadomości AI do kontaktu i nigdy nie jest usuwana, więc wyłączenie odpowiedzi AI dla kontaktu lub przeniesienie go do innej kampanii nie resetuje jej. W przypadku okresu — „kontakty, którymi moje AI zajmowało się w tym miesiącu”, co jest typowym pytaniem rozliczeniowym — należy użyć zakresu last_ai_interaction_at:

{ "field": "last_ai_interaction_at", "op": "within_last", "value": { "amount": 30, "unit": "days" } }

Nie należy mylić żadnego z nich z is_bot_active (AI może odpowiadać, co nie oznacza, że to zrobiło) ani has_ever_responded (kontakt odpisał, komukolwiek). Te same dwa znaczniki są zwracane przy każdym kontakcie jako first_ai_interaction_at / last_ai_interaction_at, a cały zestaw reguł działa również na GET /contacts?rules=, więc możesz zliczać dopasowania bez tworzenia listy.

Podgląd zestawu reguł

POST /lists/preview

Zlicza i pobiera próbki kontaktów, które pasowałyby do zestawu reguł, bez tworzenia ani zmieniania czegokolwiek. Użyj tego, aby sprawdzić poprawność reguł przed ich zapisaniem.

curl -X POST "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/lists/preview?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "smart_rules": { "match": "all", "conditions": [ { "field": "tags", "op": "has_any", "value": ["tagHotLead"] } ] } }'

Odpowiedź

{
  "success": true,
  "count": 3,
  "sample": [
    {
      "id": "contact_abc123",
      "first_name": "Sofia",
      "last_name": "Martinez",
      "phone_number": "+31600000000",
      "email": "sofia@example.com",
      "channel": "whatsapp"
    }
  ]
}

sample przechowuje do 10 kontaktów, zaczynając od tych najbardziej aktywnych.

Ponowne uruchomienie listy inteligentnej

POST /lists/{listId}/evaluate

Wymusza natychmiastową ponowną ocenę (to samo, co robi przycisk Odśwież teraz w panelu). Listy inteligentne są aktualizowane automatycznie po zmianie kontaktu oraz co 15 minut w przypadku reguł opartych na czasie, więc jest to potrzebne tylko wtedy, gdy chcesz uzyskać wynik natychmiast.

Odpowiedź

{
  "success": true,
  "list_id": "list_abc123",
  "evaluation": { "added": 2, "removed": 1, "total": 4 }
}

evaluation.skipped: true oznacza, że inna ocena tej samej listy była już w toku i to wywołanie nie przyniosło żadnego efektu.

Listy inteligentne nie akceptują ręcznie dodawanych członków

Punkty końcowe członkostwa zwracają 409 z "This is a smart list — its members are computed from its rules. Edit the rules instead.", gdy lista docelowa jest inteligentna. Dotyczy to POST /contacts/lists, DELETE /contacts/lists, POST /contacts/lists/batch, contact_ids w POST /lists oraz PUT /lists/{listId}, a także wyboru listy inteligentnej jako celu importu CSV. Zamiast tego zmień reguły.

Wywołanie POST /lists/{listId}/evaluate na liście statycznej również kończy się 409 — nie ma ona żadnych reguł do uruchomienia.


Błędy API kontaktów

Punkty końcowe (endpoints) kontaktów zwracają standardową kopertę błędu:

{
  "success": false,
  "error": "Contact not found"
}

Niektóre punkty końcowe zawierają również error_code, który zazwyczaj odpowiada statusowi HTTP — jedynym wyjątkiem jest przypadek duplikatu kontaktu poniżej, gdzie status HTTP wynosi 200, a tylko error_code zawiera 409. Kody specyficzne dla punktów końcowych kontaktów:

Kod Kiedy występuje w punkcie końcowym kontaktu
400 Nieprawidłowe żądanie — brakujące/nieprawidłowe pole, pusty komunikat, nieprawidłowy kursor lub ponad 500 identyfikatorów w partii.
402 Brak wystarczającej liczby kredytów na wykonanie tagowania AI dla jednego kontaktu (error_code: "insufficient_credits").
404 Kontaktu, listy lub tagu nie znaleziono na Twoim koncie.
409 Kontakt o takim numerze telefonu już istnieje (podczas tworzenia). Zwracane jako error_code w treści z kodem stanu HTTP 200, więc należy tutaj rozgałęzić na error_code. Zwracane również, gdy masowe automatyczne tagowanie jest już w toku (error_code: "auto_tag_run_in_progress") lub gdy połączenie kontaktu z innym kanałem spowodowałoby połączenie dwóch kontaktów już powiązanych z dwiema różnymi osobami.
422 Kontakt nie może obecnie odebrać wiadomości (tryb nie przeszkadzać, profil prywatny lub nieobsługiwany kanał). W punkcie końcowym łączenia kanałów obejmuje również brak numeru telefonu, nieobsługiwaną parę kanałów lub brak podłączonego nadawcy dla kanału docelowego.

403 w punkcie końcowym kontaktu może również oznaczać problem z limitem kontaktów lub uprawnieniami do listy, a nie z dostępem w ramach planu. Wspólne kody, które może zwrócić każdy punkt końcowy — 401, 403 (Twój plan nie obejmuje dostępu do API), 429 (limit szybkości) oraz 500 — zostały wymienione wraz ze wskazówkami dotyczącymi ponawiania prób w sekcji Błędy i stronicowanie.


Następne kroki

  • API wiadomości — wysyłaj wiadomości według identyfikatora kanału i zarządzaj konwersacjami.
  • Dokumentacja API — pełna lista punktów końcowych, w tym tagi i listy.
  • Dostęp do API — uwierzytelnianie, limity szybkości i obsługa błędów.