Profesjonalne REST API dla systemu InsERT Nexo Subiekt · Rachmistrz · Rewizor · Gratyfikant · Gestor
Rozwijane przez DMservice | 📧 mateusz.serwinowski@dmservice.pl
🚀 Swagger UI (pełny katalog endpointów): http://localhost:5000/swagger 🔑 Autoryzacja kluczem API — patrz Autentykacja 📦 Wersja SDK: nexo 61.0.0.9362 (
docs/nexoSDK_61.0.0.9362/)
- Wymagania
- Konfiguracja
- Uruchomienie
- Autentykacja
- Multi-tenant (wiele firm)
- Konwencje API
- Moduły API
- Integracja z Laravel
- Przykłady użycia
- Architektura i uwagi techniczne
- Windows 10/11 lub Windows Server
- .NET 8.0 SDK
- Zainstalowany InsERT Nexo z licencją na Sferę
- SQL Server z bazą danych Nexo
Skopiuj src/appsettings.template.json do src/appsettings.json i uzupełnij:
{
"Sfera": {
"Server": "(local)\\INSERTNEXO",
"Database": "NazwaTwojejBazy",
"UseWindowsAuth": true,
"SqlLogin": null,
"SqlPassword": null,
"NexoLogin": "Szef",
"NexoPassword": "",
"Product": "Subiekt"
}
}| Parametr | Opis |
|---|---|
Server |
Nazwa instancji SQL Server |
Database |
Nazwa bazy danych Nexo |
UseWindowsAuth |
true dla autentykacji Windows, false dla SQL |
SqlLogin / SqlPassword |
Dane logowania SQL (gdy UseWindowsAuth = false) |
NexoLogin / NexoPassword |
Operator Nexo (domyślny) |
Product |
Subiekt, Rachmistrz, Rewizor, Gratyfikant |
AutoSyncSdk |
Automatyczna synchronizacja DLL-i SDK przy starcie (domyślnie true) |
NexoInstallPath |
Ścieżka instalacji nexo (domyślnie wykrywana) |
PreferDeploymentBinaries |
Binarki z deploymentu nexo klienta (%LocalAppData%\InsERT\Deployments\Nexo\*\Binaries) nadpisują DLL-e z builda przy różnicy wersji — spójność z wersją bazy (domyślnie true) |
SdkFallbackUrl / SdkFallbackToken |
Zip z DLL-ami SDK pobierany przy starcie, gdy na maszynie nie ma nexo, a build nie zawierał DLL-i |
Kolejność źródeł DLL-i SDK przy starcie: deployment nexo na maszynie klienta (zawsze zgodny z wersją bazy) → instalacja w Program Files → zip z SdkFallbackUrl.
Wszystkie parametry można nadpisać zmiennymi środowiskowymi SFERA_* (np. SFERA_SERVER, SFERA_NEXO_LOGIN); klucz API — API_KEY, port — API_PORT.
⚠️ Nie commitujappsettings.jsonz realnymi danymi. Używaj zmiennych środowiskowych w produkcji.
Build wymaga Windows (target
net8.0-windows, WinForms, DLL-e SDK InsERT).
# 1. Wypełnij src\lib\nexo-sdk DLL-ami SDK (nie są śledzone w git)
# Domyślnie: docs\nexoSDK_*\Bin, fallback: zainstalowane nexo
.\scripts\setup-sdk.ps1
# własne źródło: .\scripts\setup-sdk.ps1 -SdkSourcePath "C:\Program Files (x86)\InsERT\nexo"
# 2. Konfiguracja
copy src\appsettings.template.json src\appsettings.json # i uzupełnij danedotnet build src\NexoSferaApi.csproj # sam build
dotnet run --project src\NexoSferaApi.csproj # build + start- API:
http://localhost:5000(port: envAPI_PORTalboKestrel:Endpoints:Http:Url) - Swagger UI:
http://localhost:5000/swagger - Specyfikacja OpenAPI:
http://localhost:5000/swagger/v1/swagger.json
dotnet publish src\NexoSferaApi.csproj -c Release -o publish
.\publish\NexoSferaApi.exe
# albo pełny pakiet release:
.\scripts\build-release.ps1# DLL-e SDK z innej ścieżki (bez setup-sdk.ps1)
dotnet build src\NexoSferaApi.csproj -p:NexoSdkPath="C:\Program Files (x86)\InsERT\nexo"
# Tryb Development - aktywne endpointy debug/* i diagnostics
$env:ASPNETCORE_ENVIRONMENT="Development"; dotnet run --project src\NexoSferaApi.csprojappsettings.json nie jest potrzebny do builda — konfiguracja jest wyłącznie runtime'owa (env vars SFERA_*, API_KEY, ApiKeys__Keys__0__Key… albo appsettings.Production.json obok exe). Gotowe workflow: .github/workflows/build.yml (windows-latest, SDK z prywatnego zipa przez secret NEXO_SDK_URL) oraz build-selfhosted.yml (runner z zainstalowanym nexo). Szczegóły: docs/CI-CD-SETUP.md.
Każde żądanie (poza GET /api/health i GET /api/settings/info) wymaga klucza API. Obsługiwane formy (w kolejności preferencji):
Authorization: Bearer {klucz-api} # preferowana
X-API-Key: {klucz-api} # legacy
?api_key={klucz-api} # tylko do testów — klucz ląduje w logach!
Endpoint MCP (/mcp, integracja z agentami AI) podlega tej samej autoryzacji.
Różne klucze API mogą pracować jako różni operatorzy Nexo — to umożliwia obsługę wielu firm/działów jedną instancją API:
{
"ApiKeys": {
"Keys": [
{
"Key": "klucz-api-firma-a",
"Name": "Firma A - Główna",
"IsActive": true,
"NexoLogin": "operator1",
"NexoPassword": "haslo1",
"DefaultWarehouse": "MG1",
"DefaultBranch": "WAW",
"CompanyDescription": "Firma A - Oddział Warszawa"
},
{
"Key": "klucz-api-default",
"Name": "Klucz domyślny",
"IsActive": true,
"CompanyDescription": "Używa domyślnego operatora z sekcji Sfera"
}
]
}
}| Parametr | Wymagany | Opis |
|---|---|---|
Key |
Tak | Unikalny klucz API |
Name |
Tak | Nazwa opisowa klucza |
IsActive |
Tak | Czy klucz jest aktywny |
NexoLogin / NexoPassword |
Nie | Operator Nexo dla tego klucza; brak = operator domyślny z sekcji Sfera |
Database |
Nie | Osobna baza Nexo (= osobna firma) dla tego klucza; brak = baza domyślna |
DefaultWarehouse / DefaultBranch |
Nie | Magazyn/oddział ustawiany w kontekście każdego żądania tym kluczem |
CompanyDescription |
Nie | Opis do celów logowania |
- Połączenie per baza —
SferaConnectionPoolutrzymuje osobne połączenie SDK (z własnym wątkiem STA) dla każdej bazy z konfiguracji kluczy; połączenia powstają leniwie przy pierwszym żądaniu danym kluczem. - Routing per żądanie —
SferaServiceRouterczyta claims klucza i kieruje każdą operację (wszystkie 61 kontrolerów, bez wyjątków) do właściwego połączenia. - Operator i kontekst — przed każdą operacją router wymusza operatora i magazyn/oddział klucza; klucz bez własnego operatora zawsze wraca do operatora domyślnego, więc kontekst jednej firmy nie przecieka do drugiej.
- Izolacja danych — każdy operator widzi w Nexo tylko to, na co pozwalają jego uprawnienia; osobne bazy są odizolowane całkowicie.
Uwaga wydajnościowa: operacje w ramach jednej bazy wykonują się sekwencyjnie (jeden wątek STA na bazę), ale różne firmy/bazy pracują na osobnych wątkach — równolegle. Pierwsze żądanie do nowej bazy płaci koszt nawiązania połączenia (kilka sekund).
- Przechowuj klucze API w zmiennych środowiskowych / sejfie, rotuj regularnie
- Używaj HTTPS w produkcji
- Nadawaj operatorom Nexo minimalne wymagane uprawnienia
Odpowiedzi pojedyncze (ApiResponse<T>):
{ "success": true, "data": { ... }, "message": null, "errors": null }Odpowiedzi listowe (PagedResponse<T>):
{
"success": true,
"data": [ ... ],
"page": 1,
"pageSize": 50,
"totalCount": 1234,
"totalPages": 25,
"hasNextPage": true,
"hasPreviousPage": false
}Błędy: success: false + message/errors, status HTTP 400/404/500. (Część starszych endpointów zwraca jeszcze surowe obiekty — trwa ujednolicanie.)
Endpointy listowe przyjmują ?page=1&pageSize=50 oraz filtry specyficzne dla zasobu (np. search, activeOnly, zakresy dat) — szczegóły w Swaggerze.
SDK Sfery działa na jednym dedykowanym wątku STA — wszystkie operacje SDK wykonują się sekwencyjnie. Konsekwencje:
- Równoległe żądania są kolejkowane, nie wykonują się jednocześnie
- Długa operacja (np. generowanie JPK) opóźnia kolejne żądania
- Po stronie klienta ustaw rozsądne timeouty i unikaj agresywnego fan-outu
GET /api/health— status API (anonimowy)GET /api/health/sfera— status połączenia ze SferąPOST /api/health/reconnect— pełna rekonekcja (dispose + connect na wątku STA)
Pełny, zawsze aktualny katalog 354 endpointów znajdziesz w Swagger UI (/swagger). Przegląd modułów:
| Domena | Moduły (route prefix) |
|---|---|
| Sprzedaż i zakupy | documents (FS/FZ/PA/korekty/zaliczki/marża), customer-orders (ZK), orders (ZD), offers (oferty Gestor), promotions, discounts |
| Magazyn | warehouse-documents (WZ/PZ/RW/PW/MM), warehouses, inventory (stany, ruchy, wycena), assembly (kompletacja ZM), remainders (remanenty) |
| Kartoteki | customers + contractor-groups, products + product-groups/-attributes/-templates/-symbols, photo-gallery, custom-fields |
| Finanse | payments (KP/KW/BP/BW, rozrachunki), finance-reports (kasy, rachunki, wyciągi, wiekowanie), vat-registry, accruals (RMK) |
| Księgowość | booking-documents (dekretacja), accounting-import, internal-documents (DW), financial-statements, archives |
| Podatki i deklaracje | jpk, ksef (e-faktury), declarations (VAT/ZUS), intrastat |
| Kadry i płace | employees, contracts, payroll (listy płac), absences, ppk |
| Majątek | fixed-assets (środki trwałe), fleet (pojazdy) |
| CRM i serwis | activities (działania CRM), service-orders (zlecenia serwisowe), comments, calendars, attachments |
| E-commerce i logistyka | ecommerce (integracje, oferty internetowe, paczki), couriers |
| Słowniki i konfiguracja | dictionary (VAT, jm, waluty, kursy, formy płatności, kraje), configurations, system-parameters, settings, organization, permissions, devices, print |
| System | health, system (firma, operator, licencja), audit-trail, reports, office-clients, diagnostics (tylko do debugowania) |
// config/services.php
'nexo' => [
'base_url' => env('NEXO_API_URL', 'http://nexo-host:5000'),
'api_key' => env('NEXO_API_KEY'),
],use Illuminate\Support\Facades\Http;
$nexo = Http::baseUrl(config('services.nexo.base_url'))
->withToken(config('services.nexo.api_key')) // Authorization: Bearer
->timeout(120) // operacje SDK są sekwencyjne!
->acceptJson();
// Lista produktów
$products = $nexo->get('/api/products', ['search' => 'laptop', 'page' => 1, 'pageSize' => 20])
->json('data');
// Faktura sprzedaży
$invoice = $nexo->post('/api/documents/sales-invoice', [
'customerNIP' => '1234567890',
'warehouseSymbol' => 'MAG',
'items' => [
['productSymbol' => 'TOWAR001', 'quantity' => 5, 'priceNet' => 100.00],
],
])->json();
if (! $invoice['success']) {
Log::error('Nexo API error', $invoice['errors'] ?? []);
}curl -X POST http://localhost:5000/api/customers \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your-api-key" \
-d '{
"symbol": "KLIENT001",
"shortName": "Firma ABC",
"fullName": "Firma ABC Sp. z o.o.",
"nip": "1234567890",
"email": "kontakt@firmaabc.pl",
"phone": "123456789",
"type": 0,
"address": {
"street": "ul. Przykladowa",
"buildingNumber": "10",
"city": "Warszawa",
"postalCode": "00-001"
}
}'curl -X POST http://localhost:5000/api/documents/sales-invoice \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your-api-key" \
-d '{
"type": 1,
"customerNIP": "1234567890",
"warehouseSymbol": "MAG",
"items": [
{ "productSymbol": "TOWAR001", "quantity": 5, "priceNet": 100.00 }
]
}'curl -X POST http://localhost:5000/api/documents/receipt \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your-api-key" \
-d '{
"warehouseSymbol": "MAG",
"items": [
{ "productSymbol": "TOWAR001", "quantity": 2, "priceGross": 123.00 }
]
}'curl -X POST http://localhost:5000/api/warehouse-documents/pw \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your-api-key" \
-d '{
"warehouseSymbol": "MG",
"issueDate": "2026-05-06T00:00:00",
"notes": "Import z systemu zewnetrznego",
"items": [
{ "productSymbol": "TOWAR001", "quantity": 4.0, "unit": "szt.", "priceNet": 16.05 },
{ "productEan": "5901234123457", "quantity": 10.0, "priceNet": 25.00 }
]
}'Dla MM dodaj targetWarehouseSymbol. Dla RW ceny mogą być ignorowane — system wycenia rozchód wg metody FIFO/LIFO/średniej ważonej skonfigurowanej w Nexo.
curl -X POST http://localhost:5000/api/warehouse-documents/109622/associate \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your-api-key" \
-d '{ "targetDocumentId": 109623, "relationType": "related" }'curl -X POST http://localhost:5000/api/payments/cash/kp \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your-api-key" \
-d '{
"amount": 1000.00,
"description": "Wplata gotowki",
"customerNIP": "1234567890",
"cashRegisterSymbol": "KASA1"
}'nexo-sfera-api/
├── src/
│ ├── Controllers/ # 61 kontrolerów REST
│ ├── Services/ # SferaService (wątek STA), synchronizator SDK
│ ├── Models/ # Dto / Requests / Responses
│ ├── Helpers/ # DynamicPropertyHelper, walidacja stanów
│ ├── Authentication/ # API Key auth (Bearer / X-API-Key)
│ ├── Configuration/ # SferaSettings, ApiKeySettings
│ ├── Middleware/ # Obsługa błędów
│ ├── Mcp/ # Narzędzia MCP dla agentów AI (patrz MCP.md)
│ └── Program.cs
├── lib/nexo-sdk/ # DLL-e SDK Nexo
├── docs/
│ ├── nexoSDK_61.0.0.9362/ # Oficjalna dokumentacja SDK (nieśledzona w git)
│ └── AUDIT-2026-06-12.md # Audyt jakości i mapa pokrycia SDK
└── scripts/ # Skrypty deploy/diagnostyka
SDK Nexo Sfera używa EF6 i był projektowany pod aplikacje desktopowe:
- Dedykowany wątek STA — wszystkie operacje SDK wykonuje jeden wątek z
WindowsFormsSynchronizationContext(wymóg EF6) ExecuteWithLockAsync— każdy dostęp do SDK z kontrolera musi przejść przez ten wrapper (serializacja pracy na wątku STA); obiektydynamicSDK nie mogą opuścić lambdy- Rekonekcja —
POST /api/health/reconnectbezpiecznie ubija i odtwarza połączenie na wątku STA
// 1. Ustaw magazyn na Dokument (nie na Dane!)
faktura.Dokument.Magazyn = magazyn;
// 2. Zarezerwuj numer PRZED dodaniem pozycji
faktura.ZarezerwujNumer();
// 3. Dodaj pozycje przez ID produktu
var pozycja = faktura.Pozycje.Dodaj(towarId);
pozycja.Ilosc = quantity;
// 4. Zapisz dokument
faktura.Zapisz();API pomija walidację stanów dla produktów typu usługa (Rodzaj_Id = 1) — usługi można dodawać do dokumentów sprzedaży bez sprawdzania stanów. Walidacja działa normalnie dla towarów (0), kompletów (2) i materiałów (3).
{ "id": 12345, "number": "FS/2026/01/123", "statusId": 3, "status": "Zrealizowano", "statusSymbol": "ZREAL" }Pole notes jest ignorowane (i logowane) przy tworzeniu FS, FZ, PA, korekt, faktur zaliczkowych i VAT marża; działa normalnie dla dokumentów magazynowych i zamówień.
Projekt wymaga ważnej licencji InsERT Nexo z modułem Sfera. Licencja komercyjna DMservice.
⭐ Jeśli projekt jest przydatny, zostaw gwiazdkę!