Nodea — logo

Profil konta — API v1 i MCP | Dokumentacja Nodea

Moduł Profil konta obejmuje odczyt i częściową aktualizację profilu użytkownika tokenu: dane identyfikacyjne, firmę i adres rozliczeniowy, profil VAT (kraj, status firmy, numer VAT z walidacją VIES), numer podatkowy oraz strefę czasową. Dokument opisuje warstwę REST API v1 (/api/v1/profile) oraz narzędzia MCP profile-get i profile-update.

Uwierzytelnianie i zakresy (scopes)

API v1 uwierzytelnia się osobistym tokenem Passport przez nagłówek Authorization: Bearer <token>. Profil operuje wyłącznie na użytkowniku tokenu — nie przyjmuje żadnych identyfikatorów, więc nie istnieje powierzchnia cross-tenant.

  • account:read — odczyt profilu (GET /profile).
  • account:write — częściowa aktualizacja (PATCH /profile).

Profil jest niebramkowany żadną flagą Pennant — dostęp do konta nigdy nie jest feature-flagowany (tak samo jak w web UI). Limit zapytań: throttle:api-v1 = 240/min na użytkownika tokenu.

Co jest świadomie pominięte (web-only)

Wrażliwe, wymagające potwierdzenia operacje pozostają wyłącznie w web UI i nie są eksponowane przez API v1:

  • zmiana adresu e-mail,
  • zmiana hasła,
  • zarządzanie 2FA (dwuskładnikowe uwierzytelnianie),
  • odłączenie dostawcy OAuth,
  • upload awatara,
  • zmiana waluty rozliczeniowej (w web zablokowana blokadą zerowego salda portfeli).

Pole email jest zwracane w odczycie, ale PATCH /profile nie posiada dla niego reguły — jego przesłanie jest ignorowane (pole nie jest częścią validated()). W odróżnieniu od tego narzędzie MCP profile-update jawnie odrzuca email i password błędem walidacji (patrz sekcja MCP) oraz — inaczej niż API — potrafi zmienić walutę.

API v1 — endpointy

MetodaŚcieżkaScopeOpis
GET/api/v1/profileaccount:readProfil użytkownika tokenu (dane, firma, adres, VAT, strefa czasowa, waluta).
PATCH/api/v1/profileaccount:writeCzęściowa aktualizacja dowolnego podzbioru pól ogólnych i VAT. Zwraca zaktualizowany profil.

GET /profile — odpowiedź

Zwraca ProfileResource — pola: id, name, email, company_name, address, country, is_company (bool), vat_number, vat_validated (bool), vat_validated_at (ISO 8601 lub null), tax_number, timezone, currency (PLN|EUR), created_at. Nigdy nie zwraca sekretów, stanu 2FA, hashy hasła/remember, wierszy dostawców OAuth ani flag administracyjnych.

PATCH /profile — parametry ciała

Każda reguła nosi sometimes — klient może wysłać dowolny podzbiór pól; pominięte pola pozostają nietknięte (partial update).

  • name (string, sometimes|required, max 255) — przesłana nazwa nie może być pusta.
  • company_name (string|null, max 255).
  • address (string|null, max 1000).
  • tax_number (string|null, max 64).
  • timezone (string|null, reguła timezone — identyfikator IANA).
  • country (string|null, size:2 — ISO 3166-1 alpha-2).
  • is_company (boolean).
  • vat_number (string|null, max 32).

Waluta nie jest przyjmowana przez API — zmiana currency jest web-only (i dostępna w MCP). Pola ogólne (name, company_name, address, tax_number, timezone) są zapisywane tylko, gdy obecne w ładunku.

Profil VAT i re-walidacja VIES

Przesłanie któregokolwiek z pól country / is_company / vat_number unieważnia poprzednią walidację VIES: vat_validated jest ustawiane na false, a vat_validated_at na null. Następnie, gdy efektywny profil (przesłane wartości nałożone na zapisane) jest firmą (is_company = true) z jednocześnie ustawionym krajem i numerem VAT, wykonywany jest round-trip do VIES (ViesValidator). Kraj i numer VAT są normalizowane (upper-case, trim). Jak w web: nieudany lookup VIES i tak zapisuje przesłane wartości — pole vat_validated pozostaje po prostu false (brak gałęzi odwrotnego obciążenia). VIES używa SOAP (nie fasady Http) i poza produkcją domyślnie działa w trybie sandbox (billing.vies.sandbox).

Kody błędów

  • 401 — brak/niepoprawny token.
  • 403 — brak wymaganego scope (account:read przy GET, account:write przy PATCH).
  • 422 — walidacja (np. pusty name, country spoza size:2, nieprawidłowa strefa czasowa).

Przykłady — API

Odczyt profilu

curl -s https://app.nodea.io/api/v1/profile \
  -H "Authorization: Bearer $NODEA_TOKEN" \
  -H "Accept: application/json"

Aktualizacja danych ogólnych i strefy czasowej

curl -s -X PATCH https://app.nodea.io/api/v1/profile \
  -H "Authorization: Bearer $NODEA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Jan Kowalski",
    "company_name": "Kowalski sp. z o.o.",
    "address": "ul. Przykładowa 1, 00-001 Warszawa",
    "timezone": "Europe/Warsaw"
  }'

Ustawienie profilu VAT (wyzwala re-walidację VIES)

curl -s -X PATCH https://app.nodea.io/api/v1/profile \
  -H "Authorization: Bearer $NODEA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "is_company": true,
    "country": "PL",
    "vat_number": "PL1234567890"
  }'

MCP — narzędzia

Narzędzia MCP dzielą model uwierzytelniania i zakresów z API v1 (Bearer + scope sprawdzany w ensureScope). Profil jest niebramkowany flagą, więc oba narzędzia są zawsze widoczne w tools/list. Operują wyłącznie na użytkowniku tokenu.

NarzędzieScopeTrybOpis
profile-getaccount:readread-onlyZwraca profil: name, email, company_name, adres, country, status firmy/VAT, tax_number, strefę czasową i walutę. Bez poświadczeń i stanu 2FA.
profile-updateaccount:writeidempotentneCzęściowa aktualizacja; tylko przesłane pola się zmieniają. Dodatkowo obsługuje currency. Odrzuca email/password.

profile-get

Bez parametrów. Odpowiedź jest nadzbiorem ProfileResource — te same pola plus effective_timezone (rozwiązana strefa czasowa użytkownika, gdy timezone jest null).

profile-update — parametry

Wszystkie opcjonalne; zmieniają się tylko przesłane. Puste stringi / null czyszczą pole (blank → null), kraj i numer VAT są upper-case.

  • name (string, max 255).
  • company_name (string, max 255; null/pusty czyści).
  • address (string, max 1000; null/pusty czyści).
  • tax_number (string, max 64; null/pusty czyści).
  • timezone (string — identyfikator IANA; null czyści).
  • country (string — ISO 3166-1 alpha-2; null czyści).
  • is_company (boolean).
  • vat_number (string, max 32; null/pusty czyści).
  • currency (enum PLN|EUR) — zablokowana, gdy którykolwiek portfel ma niezerowe saldo (zwraca błąd narzędzia); zmiana jest logowana do dziennika aktywności.

Różnice względem API: zmiana pól VAT (country/is_company/vat_number) na wartość różną od zapisanej resetuje vat_validated (i vat_validated_at), ale to narzędzie nie wykonuje round-tripu do VIES — ponowną walidację przeprowadza web UI. Przesłanie email lub password kończy się błędem walidacji (reguła prohibited: „The email address / password can only be changed in the web UI.”), a nie cichym zignorowaniem jak w API.

Przykład — MCP (JSON-RPC)

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "profile-get",
    "arguments": {}
  }
}
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "profile-update",
    "arguments": {
      "is_company": true,
      "country": "PL",
      "vat_number": "PL1234567890",
      "timezone": "Europe/Warsaw"
    }
  }
}