Przejdź do treści

Przewodniki

Faktury

Agent potrafi odczytać wystawioną fakturę z podłączonego Fakturoid lub ABRA Flexi i wykorzystać ją jako podstawę połączenia przypominającego - nigdy nie wystawia faktury ani nie oznacza jej jako opłaconej.

Co potrafi, a czego nie

  • Wyszukuje wystawione faktury według numeru lub nazwy firmy (list_invoices).
  • Pobiera aktualny stan jednej faktury bezpośrednio od dostawcy (get_invoice).
  • Zakłada Zadanie przypominające (taskType: "invoice"), które odwołuje się do faktury.

Czego nie potrafi

  • Nie wystawia, nie edytuje ani nie usuwa żadnej faktury.
  • Nie oznacza faktury jako opłaconej - to potrafi tylko sam Fakturoid lub ABRA.
  • Nie podłącza Fakturoid za pomocą danych logowania - wyłącznie przez OAuth w przeglądarce.

Podłączenie konta

Obie usługi fakturowania zarządzają Państwo w tym samym miejscu co kalendarze, w portalu w sekcji Dane i integracje (/propojeni). list_integrations i GET /v1/integrations służą tylko do odczytu: zwracają stan połączenia i ewentualny connectUrl, same niczego nie podłączają. Szczegółowy przebieg dla agenta (list_integrations -> connectUrl -> krok w przeglądarce) opisuje strona Połączenia.

Fakturoid

Podłącza się wyłącznie logowaniem OAuth w przeglądarce - POST /v1/integrations z provider: "fakturoid" REST odrzuca błędem integration_unsupported, danych logowania nie można w ten sposób przesłać. Jeśli konto ma więcej niż jedną firmę z włączonym fakturowaniem, po zalogowaniu przeglądarka wraca na stronę Dane i integracje w volai (/propojeni) i dopiero tam pojawia się wybór firmy - wpis w integrations powstaje dopiero po tym wyborze. Pole ready przy fakturoid w GET /v1/integrations informuje wyłącznie, że volai ma skonfigurowane dane OAuth do Fakturoid (FAKTUROID_CLIENT_ID i pozostałe) - NIE że konkretne konto jest już podłączone. O tym, że połączenie jest gotowe, agent przekonuje się po tym, że pojawia się ono w tablicy integrations.

ABRA Flexi

Podłącza się za pomocą danych logowania, tak jak Apple Calendar: POST /v1/integrations z {provider: "abra-flexi", baseUrl, company, username, password}. Adres serwera (baseUrl) musi dokładnie odpowiadać adresowi wcześniej dopuszczonemu przez operatora (ABRA_FLEXI_ALLOWED_HOSTS) - inny adres zwróci błąd.

Hasło należy przekazywać wyłącznie wtedy, gdy użytkownik ma je już bezpiecznie przechowywane (zmienna środowiskowa, plik wskazany przez niego) - nigdy nie należy prosić o nie w rozmowie ani go powtarzać.

Odczyt faktur

Procedura dwuetapowa: najpierw wyszukiwanie, potem aktualny szczegół tej jednej faktury, która Państwa interesuje.

  • list_invoices({integrationId, search?}) - search (do 100 znaków) wyszukuje u dostawcy według numeru dokumentu lub nazwy firmy; zwraca pierwsze 40 wierszy w Fakturoid lub 50 w ABRA, bez stronicowania. Gdy wyników jest zbyt wiele, proszę doprecyzować search.
  • get_invoice({integrationId, invoiceId}) - invoiceId to powtórzony externalId z list_invoices. Zwraca najświeższy stan bezpośrednio od dostawcy, a nie to, co pamięta volai.

Odpowiedniki REST: GET /v1/integrations/{id}/invoices?search=... oraz GET /v1/integrations/{id}/invoices/{invoiceId}.

status to paid, unpaid, overdue lub unknown; amountDueMinor to liczba całkowita w najmniejszych jednostkach WALUTY DOKUMENTU (niekoniecznie CZK), a null oznacza nieustalone saldo. Szczegół zawiera dodatkowo provider, fetchedAt i evidence: "provider_response".

status: "unknown" ani brak kwoty NIGDY nie oznaczają, że faktura jest opłacona - a samo twierdzenie dzwoniącego nie jest dowodem płatności. Za dowód agent uznaje wyłącznie aktualną odpowiedź get_invoice.

Przypomnienie przez Zadania

Masowe połączenia przypominające o nieopłaconych fakturach realizuje się przez Zadania.

Zadanie typu taskType: "invoice" zakłada się z source: "integration", a każdy odbiorca (lub całe zadanie, gdy faktura jest dla wszystkich taka sama) zawiera externalRefs.invoice = {connectionId, externalId, provider?} - connectionId to identyfikator połączenia z list_integrations, externalId to identyfikator faktury z list_invoices. Bez tego odwołania create_task/POST /v1/tasks kończy się błędem validation z komunikatem recipients.externalRefs i żadne zadanie nie zostaje zapisane. Jeśli obowiązkowego odwołania brakuje w już istniejącym rekordzie, get_task/GET /v1/tasks/{id} wskaże to w issues, a start_task odmówi uruchomienia zadania z tym samym błędem walidacji.

Każdy odbiorca zawiera dodatkowo pole paymentStatus (not_applicable, unknown, unpaid, paid, disputed) - tylko do odczytu, system wyprowadza je z ostatniego odczytu faktury u dostawcy tuż przed wybraniem numeru. Bez odwołania do faktury jest to not_applicable, po założeniu lub gdy nie można zweryfikować stanu albo kwoty - unknown, w pozostałych przypadkach zgodnie z odpowiedzią Fakturoid/ABRA - przy opłaconej fakturze zadanie pomija pozycję (skipped) i ustawia paid. Wartości disputed system obecnie sam nie ustawia, potrafi ją tylko wyświetlić portal - należy ona do publicznego zestawu wartości (TaskItem w /openapi.json) na potrzeby przyszłego ręcznego oznaczania spornej faktury.

Błędy

  • integration_not_found - Połączenie o tym integrationId nie istnieje lub nie należy do tego konta.
  • integration_unsupported - Połączenie nie dotyczy fakturowania (na przykład kalendarz) albo jest to próba podłączenia Fakturoid danymi logowania zamiast przez OAuth.
  • integration_unauthorized - Fakturoid lub ABRA cofnęły dostęp - połączenie trzeba wykonać w portalu od nowa.
  • integration_provider_error - Dostawca chwilowo nie odpowiada lub zwrócił błąd - proszę spróbować później, a stan faktury do tego czasu traktować jako nieznany.
  • integration_invalid_query - ABRA odrzuciła search z odwrotnymi ukośnikami lub mieszanymi cudzysłowami - proszę uprościć zapytanie.

Pełną tabelę ze wszystkimi kodami znajdą Państwo w sekcji faktury w dokumentacji REST API oraz w błędach MCP.

Bezpieczeństwo

Tokeny dostępu ani hasła do Fakturoid czy ABRA Flexi nigdy nie są zwracane przez REST API ani MCP, a przechowujemy je w postaci zaszyfrowanej. Odłączenie integracji jest możliwe tylko w portalu lub przez REST (DELETE /v1/integrations/{id}) - MCP celowo nie ma do tego narzędzia, ponieważ operacja jest nieodwracalna.