205 lines
8.7 KiB
Markdown
205 lines
8.7 KiB
Markdown
# 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/<app-id>/...`
|
||
|
||
### 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/<app-id>/health
|
||
GET https://services.csbot.cz/apps/<app-id>/docs
|
||
```
|
||
|
||
Ve Swagger UI ověř, že `Try it out` volá endpointy přes `/apps/<app-id>` a že
|
||
jsou vyžadované hlavičky `X-Api-Key`, `X-Raynet-Email`, `X-Instance-Name`.
|
||
```
|