# RAYNET konektor Stateless proxy nad [RAYNET CRM API v2](https://app.raynetcrm.com/api/doc/index-en.html). Pokrývá celé RAYNET API díky jednotným REST konvencím. ## Přihlášení (společné pro celé připojení) RAYNET API používá HTTP Basic Auth (email + API klíč) a hlavičku s názvem instance. V této službě se předává **třemi hlavičkami u každého requestu**: | Hlavička | Co to je | Kde to vzít | |-----------------------|-------------------|-------------| | `X-Api-Key` | API klíč (secret) | RAYNET CRM: **Nastavení → Klíč k API** | | `X-Raynet-Email` | Email uživatele | Přihlašovací email do RAYNET | | `X-Instance-Name` | Název instance | Identifikátor instance (subdoména účtu) | > `X-Api-Key` je secret – nikdy se neloguje, necommituje ani nevrací z endpointů > (viz AGENTS.md). Tyto údaje jsou zobrazené i nahoře ve Swaggeru (`/docs`). Base URL RAYNET: `https://app.raynet.cz/api/v2`. ## REST konvence RAYNET (platí pro celé API) | Operace | RAYNET metoda + cesta | |---------|------------------------------| | List | `GET /{resource}/` | | Detail | `GET /{resource}/{id}/` | | Create | `PUT /{resource}/` | | Update | `POST /{resource}/{id}/` | | Delete | `DELETE /{resource}/{id}/` | Příklady entit: `company`, `person`, `lead`, `businessCase`, `activity`, `product`, `offer`, `order`, `project`, … ## Endpointy služby Veřejně přes AppFactory reverse proxy: `https://services.csbot.cz/apps//...` ### Typované entity Pro každou z těchto entit existuje plné CRUD se **strukturou objektu i odpovědí viditelnou ve Swaggeru** (request modely, povinná pole, validace): | Cesta | Entita | Povinná pole | |---------------------------|--------------------|--------------| | `/company` | Firma / klient | `name`, `rating`, `state`, `role` | | `/person` | Kontaktní osoba | `lastName` | | `/lead` | Lead / poptávka | `topic`, `priority` | | `/businessCase` | Obchodní případ | `name`, `company` | | `/offer` | Nabídka | `name`, `company`, `businessCase` | | `/salesOrder` | Objednávka | `name`, `company`, `businessCase` | | `/invoice` | Faktura | `company`, `currency`, `dueDate`, `issueDate`, `invoiceType`, `paymentType`, `taxableSupplyDate` | | `/product` | Produkt | `code`, `name` | | `/priceList` | Ceník | `name`, `code`, `currency`, `validFrom` | | `/project` | Projekt | `name`, `company` | | `/task` | Úkol | `title`, `priority`, `owner`, `resolver`, `deadline` | | `/email` | E-mail (aktivita) | `title`, `priority`, `owner` | | `/event` | Událost | `title`, `priority`, `owner` | | `/meeting` | Schůzka | `title`, `priority`, `owner` | | `/phoneCall` | Telefonát | `title`, `priority`, `owner` | | `/letter` | Dopis | `title`, `priority`, `owner` | | `/webhook` | Webhook | `url`, `events` | Operace u každé entity: | Metoda | Cesta | Popis | |--------|--------------------|--------------------------------------| | POST | `/{entita}` | Vytvoří záznam (validovaný objekt) | | GET | `/{entita}` | Seznam (`offset`, `limit`, `fulltext` + libovolné RAYNET filtry) | | GET | `/{entita}/{id}` | Detail | | PUT | `/{entita}/{id}` | Částečná úprava (všechna pole volitelná) | | DELETE | `/{entita}/{id}` | Smazání | Enumy firmy: `rating` = `A`/`B`/`C`; `state` = `A_POTENTIAL`/`B_ACTUAL`/`C_DEFERRED`/`D_UNATTRACTIVE`; `role` = `A_SUBSCRIBER`/`B_PARTNER`/`C_SUPPLIER`/`D_RIVAL`; `taxPayer` = `YES`/`NO`. > Pole jsou v `camelCase` (tak je očekává RAYNET). Nevyjmenovaná pole jsou > povolená (`extra="allow"`), takže lze poslat i pole, která model neuvádí. ### Generický průchod na zbytek API Pro entity bez typovaného modelu – zejména **uživatelé** (`userAccount`), soubory (`file`), DMS dokumenty/složky, GDPR, hromadné e-maly a všechny **číselníky** (`currency`, `legalForm`, `paymentTerm`, `taxRate`, `territory`, `contactSource`, `companyCategory`, `productCategory`, `leadPhase`, `businessCasePhase`, `offerStatus`, `salesOrderStatus`, `projectStatus`, `maritalStatus`, `employeesNumber`, `economyActivity`, klasifikace 1/2/3, …): | Metoda | Cesta | Mapuje se na RAYNET | |--------|-----------------------------|-------------------------------| | GET | `/api/{resource}` | `GET /{resource}/` (query params se předávají) | | GET | `/api/{resource}/{id}` | `GET /{resource}/{id}/` | | POST | `/api/{resource}` | `PUT /{resource}/` (create) | | PUT | `/api/{resource}/{id}` | `POST /{resource}/{id}/` (update) | | DELETE | `/api/{resource}/{id}` | `DELETE /{resource}/{id}/` | ### Vnořené zdroje a speciální akce Pro kolekce a akce nad záznamem (`sub` = zbytek cesty, přesně dle RAYNET vč. koncového lomítka u kolekcí): | Metoda | Cesta | Příklad cíle | |--------|----------------------------------------|--------------| | GET | `/api/{resource}/{id}/{sub}` | `/invoice/{id}/pdfExport`, `/company/{id}/relationship/` | | POST | `/api/{resource}/{id}/{sub}` | `/invoice/{id}/cancel`, `/company/{id}/lock`, `/company/{id}/merge/{srcId}/` | | PUT | `/api/{resource}/{id}/{sub}` | `/company/{id}/address/`, `/invoice/{id}/payment/`, `/offer/{id}/item/` | | DELETE | `/api/{resource}/{id}/{sub}` | `/company/{id}/address/5/` | ### Raw – 100 % pokrytí Pro jakoukoli cestu / metodu (i netypické, např. `PUT /invoice/creditNote`): ```text POST /raw { "method": "PUT", "path": "/invoice/creditNote", "params": {...}, "data": {...} } ``` ### Tvar odpovědí - Create → `{ "success": true, "id": 123, "data": {...} }` - Detail → `{ "success": true, "data": { ...objekt vč. id, rowInfo } }` - Seznam → `{ "success": true, "totalCount": N, "data": [ ... ] }` - Update / Delete → `{ "success": true }` ### Příklad těla `POST /company` ```json { "name": "ACME s.r.o.", "rating": "A", "state": "A_POTENTIAL", "role": "A_SUBSCRIBER", "regNumber": "12345678", "taxNumber": "CZ12345678", "taxPayer": "YES", "addresses": [ { "address": { "name": "Sídlo klienta", "street": "Francouzská 6167/5", "city": "Ostrava", "province": "Morava", "zipCode": "708 00", "country": "CZ" }, "contactInfo": { "email": "info@acme.cz", "tel1": "+420 553 401 520", "tel1Type": "recepce", "www": "www.acme.cz" } } ], "tags": ["import", "konektor"] } ``` ## Chybové stavy | HTTP | Kdy | |------|-----------------------------------------------------------| | 400 | RAYNET odmítl data (nevalidní vstup) | | 401 | chybný API klíč / email / instance (autentizace selhala) | | 422 | nevalidní vstup (FastAPI validace nebo chybí povinné pole)| | 502 | RAYNET nedostupný / chyba serveru / timeout | ## Použití konektoru přímo v Pythonu ```python from app.raynet_client import RaynetClient, RaynetError client = RaynetClient(api_key="...", email="user@firma.cz", instance_name="moje-instance") try: # pojmenovaná zkratka company = client.create_company({ "name": "ACME s.r.o.", "rating": "A", "state": "A_POTENTIAL", "role": "A_SUBSCRIBER", }) # generické CRUD nad libovolnou entitou leads = client.list_records("lead", {"limit": 50}) deal = client.get_record("businessCase", 123) client.update_record("person", 42, {"lastName": "Novák"}) # speciální akce / vnořené zdroje client.call("POST", f"/company/{company['id']}/lock") except RaynetError as exc: print("Chyba:", exc.message, exc.status_code) ``` `RaynetClient` drží `requests.Session` (Basic Auth + `X-Instance-Name`), automaticky opakuje přechodné chyby (síť, 429, 5xx) a vyhazuje typované výjimky `RaynetAuthError` / `RaynetValidationError` / `RaynetError`. ## Ověření po nasazení ```text GET https://services.csbot.cz/apps//health GET https://services.csbot.cz/apps//docs ``` Ve Swagger UI ověř, že `Try it out` volá endpointy přes `/apps/` a že jsou vyžadované hlavičky `X-Api-Key`, `X-Raynet-Email`, `X-Instance-Name`. ```