Documentație tehnică

Documentație

Ghiduri tehnice pentru crawling, indexare, setări de domeniu, API, contorizare și integrarea ZENIA Assistant.

Acces API

ZENIA oferă un REST API pentru integrări server-to-server, disponibil sub /api/v1. Îl poți folosi pentru a citi informații despre spațiul de lucru, a verifica domenii, a consulta utilizarea și a trimite mesaje către chat fără să folosești panoul din browser.

Accesul API este protejat prin chei API create din Cont → Acces API. Fiecare cheie este asociată unui spațiu de lucru, unui set de permisiuni și disponibilității funcției în planul activ.

Explicație pe înțeles

Ce înseamnă asta dacă nu ești tehnic

Acces API înseamnă că sistemele tale pot comunica direct cu ZENIA fără să deschizi manual panoul web. Creezi o cheie privată, îi dai doar permisiunile necesare și permiți website-ului, CRM-ului, aplicației interne sau automatizării tale să ceară informații de la ZENIA.

Un flux obișnuit arată așa: creezi cheia, o salvezi pe server, alegi un domeniu deja indexat în ZENIA, apoi backendul tău apelează API-ul pentru a citi date despre spațiul de lucru, domenii, utilizare sau pentru a trimite întrebări către chat.

Dacă lucrezi cu un dezvoltator, partea ta este de obicei să creezi cheia, să o copiezi o singură dată, să comunici domeniul indexat și să confirmi ce acțiuni trebuie să poată face integrarea.

Disponibilitate

Cine poate folosi Acces API

Accesul API este disponibil pentru planurile care includ această funcționalitate. ZENIA verifică planul, statusul contului și permisiunile cheii la fiecare cerere API.

Dacă spațiul de lucru nu are Acces API activ sau dacă accesul comercial este restricționat, cererile API pot fi respinse chiar dacă cheia există.

Administrarea cheilor

Creează, păstrează și revocă chei în siguranță

Creezi chei din Cont → Acces API. Pentru fiecare cheie alegi un nume și permisiunile necesare integrării.

Secretul brut este afișat o singură dată. ZENIA stochează doar o formă securizată a cheii, deci nu poți vedea din nou secretul mai târziu. Dacă îl pierzi, revocă cheia și creează una nouă.

Folosește chei separate pentru integrări, medii sau aplicații diferite. Secțiunea Utilizare API te ajută să vezi dacă o cheie este folosită și dacă produce erori sau cereri limitate.

Utilizare API

Monitorizarea utilizării API

Poți monitoriza activitatea API a spațiului de lucru din Cont → Acces API → Utilizare API.

Această secțiune te ajută să verifici dacă integrările sunt active și funcționează corect. Afișează valori agregate, precum cereri totale, cereri reușite, cereri cu erori, cereri limitate, cereri de chat, utilizare pe endpointuri, coduri de eroare frecvente și utilizare pe fiecare cheie.

Secțiunea este doar pentru citire și este limitată la spațiul tău de lucru. Nu afișează chei API brute, headere Authorization, corpuri de cerere, mesaje chat, răspunsuri ale asistentului, adrese IP sau date din alte spații de lucru.

Folosește această secțiune ca să verifici:

  • dacă o integrare mai trimite cereri
  • ce cheie API este folosită
  • dacă cererile eșuează
  • dacă cererile sunt limitate
  • dacă utilizarea Chat API crește
Permisiuni

Permisiuni disponibile

Permisiunile limitează ce poate face fiecare cheie API. Folosește întotdeauna setul minim de permisiuni necesar integrării.

Permisiunile sunt aplicate la nivelul cheii API, iar planul activ decide în continuare dacă Acces API și analytics sunt disponibile.

PermisiuneCe permiteNecesar pentru
chat:writeTrimiterea mesajelor către Chat APIPOST /api/v1/chat/messages
workspace:readCitirea informațiilor despre spațiul de lucruGET /api/v1/workspace
domains:readCitirea domeniilor din spațiul de lucruGET /api/v1/domains, GET /api/v1/domains/:hostname
usage:readCitirea utilizării curenteGET /api/v1/usage/current, GET /api/v1/domains/:hostname/usage/current
analytics:readCitirea istoricului de utilizare, atunci când analytics este disponibil în planul activGET /api/v1/usage/history, GET /api/v1/domains/:hostname/usage/history
Înainte de test

Pregătește cele trei valori necesare

Înainte să trimiți cereri, pregătește aceste valori:

  • ApiBaseUrl: URL-ul complet de bază al API-ului, de exemplu https://buildbot.ro/api/v1. Pentru dezvoltare locală, poți folosi URL-ul mediului tău local.
  • ZENIA_API_KEY: cheia API brută afișată o singură dată la creare.
  • your-indexed-domain.com: un hostname care există deja în același spațiu de lucru ca cheia.

Exemplele de mai jos pornesc de la ideea că ApiBaseUrl include deja /api/v1, deci fiecare cerere mai adaugă doar calea endpointului, cum ar fi /workspace sau /chat/messages.

Endpointurile specifice domeniului cer ca hostname-ul să existe în spațiul tău de lucru. Cererile de chat funcționează cel mai bine după ce domeniul a fost indexat, pentru că răspunsurile depind de baza de cunoștințe disponibilă.

În PowerShell, este mai sigur să construiești JSON-ul dintr-un hashtable și să folosești ConvertTo-Json -Compress decât să escapezi manual stringuri JSON.

Autentificare

Autentificare cu Bearer token

Trimite cheia API brută în headerul Authorization, în formatul Bearer YOUR_KEY. Sesiunile de browser și tokenurile CSRF nu sunt folosite pentru /api/v1.

Folosește cheile API doar din backendul tău sau din alte medii server de încredere. Cererile cu autentificare invalidă pot fi limitate înainte să ajungă la logica endpointului.

Autentificare cu Bearer token
PowerShell
$ApiBaseUrl = "https://buildbot.ro/api/v1"
$ApiKey = "ZENIA_API_KEY"

$Headers = @{
  Authorization = "Bearer $ApiKey"
  "Content-Type" = "application/json"
}

Invoke-RestMethod -Method Get -Uri "$ApiBaseUrl/workspace" -Headers $Headers
Endpointuri

Endpointuri disponibile

Toate endpointurile sunt montate sub /api/v1. Endpointurile de domeniu returnează doar domenii care aparțin spațiului de lucru autentificat.

Endpointurile de citire și chat sunt limitate pentru a proteja calitatea serviciului. Dacă depășești limita, API-ul răspunde cu RATE_LIMITED și poate include un header Retry-After.

EndpointPermisiune necesarăScop
GET /Orice cheie validăStatus API și verificare de capabilități
GET /workspaceworkspace:readPlanul spațiului de lucru și contextul de facturare
GET /domainsdomains:readListarea domeniilor din spațiul de lucru
GET /domains/:hostnamedomains:readCitirea unui domeniu propriu
GET /usage/currentusage:readUtilizarea curentă a spațiului de lucru
GET /usage/historyanalytics:readIstoricul de utilizare al spațiului de lucru
GET /domains/:hostname/usage/currentusage:readUtilizarea curentă pentru un domeniu
GET /domains/:hostname/usage/historyanalytics:readIstoricul de utilizare pentru un domeniu
POST /chat/messageschat:writeTrimiterea unui mesaj către chat și primirea unui răspuns ancorat în surse
Cereri de chat

Trimite mesaje din backendul tău

Endpointul de chat acceptă hostname-ul domeniului și mesajul utilizatorului. ZENIA aplică automat setările server-side ale domeniului pentru căutarea în surse și comportamentul asistentului.

Chatul pe domeniu funcționează cel mai bine după indexare, pentru că răspunsul depinde de baza de cunoștințe disponibilă. Prima cerere poate omite sessionId. ZENIA îl generează automat și îl întoarce în răspuns.

Răspuns reușit

Cum arată un răspuns de chat reușit

O cerere de chat reușită întoarce ok: true și un obiect message. Exemplul de mai jos arată forma generală a răspunsului.

citations poate fi gol, confidence poate fi null, iar fallback poate lipsi atunci când nu se aplică.

JSON
{"ok":true,"message":{"reply":"Answer text...","sessionId":"generated-or-existing-session-id","citations":[],"confidence":"medium","fallback":false}}
Mesaje de continuare

Refolosește sessionId pentru aceeași conversație

Prima cerere de chat poate omite sessionId. API-ul întoarce apoi un identificator de sesiune în răspuns.

Salvează acea valoare și trimite-o din nou la următorul mesaj dacă vrei ca mesajul de continuare să rămână în același fir de conversație.

Exemple de cod

Exemple de cod

Rulează aceste exemple doar din backendul tău sau dintr-un mediu server de încredere. Nu expune cheile API în cod de browser, aplicații mobile, repository-uri publice, screenshoturi, loguri, chaturi de suport sau asistenți AI.

Trimite primul mesaj de chat
PowerShell
$ApiBaseUrl = "https://buildbot.ro/api/v1"
$ApiKey = "ZENIA_API_KEY"
$Domain = "your-indexed-domain.com"

$Headers = @{
  Authorization = "Bearer $ApiKey"
  "Content-Type" = "application/json"
}

$Body = @{
  domain = $Domain
  message = "What services do you offer?"
} | ConvertTo-Json -Compress

Invoke-RestMethod `
  -Method Post `
  -Uri "$ApiBaseUrl/chat/messages" `
  -Headers $Headers `
  -Body $Body
Continuă cu sessionId
PowerShell
$Body = @{
  domain = $Domain
  sessionId = "SESSION_ID_FROM_PREVIOUS_RESPONSE"
  message = "And what are the pricing options?"
} | ConvertTo-Json -Compress

Invoke-RestMethod `
  -Method Post `
  -Uri "$ApiBaseUrl/chat/messages" `
  -Headers $Headers `
  -Body $Body
Citește utilizarea curentă
PowerShell
Invoke-RestMethod `
  -Method Get `
  -Uri "$ApiBaseUrl/usage/current" `
  -Headers $Headers
Testare și lansare

Cum testezi integrarea

Folosește această ordine la lansare:

  1. Testează mai întâi endpointurile root și workspace.
  2. Testează apoi endpointurile de domenii și utilizare.
  3. Testează chatul fără sessionId ca să confirmi că serverul generează unul.
  4. Testează chatul și cu un sessionId explicit dacă aplicația ta trebuie să păstreze același fir de conversație.
  5. Rulează teste negative pentru autentificare lipsă, cheie invalidă, erori de validare, payload prea mare, limitare de rată și domeniu lipsă sau străin.

După ce trimiți câteva cereri, deschide Cont → Acces API → Utilizare API și confirmă că metricile se actualizează.

După ce funcționează cererea scurtă de quick start, poți rula smoke testul complet de mai jos.

Avansat

Avansat: smoke test complet pentru endpointuri

Folosește scriptul de mai jos după ce funcționează cererea din quick start. El verifică principalele endpointuri de citire, cererile de chat și cele mai comune cazuri de eroare.

Avansat: smoke test complet pentru endpointuri
PowerShell
$ApiBaseUrl = "https://buildbot.ro/api/v1"
$ApiKey = "ZENIA_API_KEY"
$Domain = "your-indexed-domain.com"

$Headers = @{
  Authorization = "Bearer $ApiKey"
  "Content-Type" = "application/json"
}

function Test-Route {
  param(
    [string]$Name,
    [string]$Method,
    [string]$Uri,
    [object]$Body = $null,
    [int[]]$ExpectedStatus = @(200),
    [hashtable]$RequestHeaders = $Headers
  )

  Write-Host ""
  Write-Host "=== $Name ===" -ForegroundColor Cyan
  Write-Host "$Method $Uri"

  try {
    $params = @{
      Method = $Method
      Uri = $Uri
    }

    if ($null -ne $RequestHeaders) {
      $params.Headers = $RequestHeaders
    }

    if ($null -ne $Body) {
      if ($Body -is [string]) {
        $params.Body = $Body
      } else {
        $params.Body = ($Body | ConvertTo-Json -Compress)
      }
    }

    $response = Invoke-RestMethod @params
    Write-Host "PASS 200" -ForegroundColor Green
    $response | ConvertTo-Json -Depth 10
  }
  catch {
    $status = $null
    $text = $_.Exception.Message

    if ($_.Exception.Response) {
      $status = [int]$_.Exception.Response.StatusCode
      $reader = New-Object System.IO.StreamReader($_.Exception.Response.GetResponseStream())
      $text = $reader.ReadToEnd()
    }

    if ($ExpectedStatus -contains $status) {
      Write-Host "PASS $status" -ForegroundColor Green
    } else {
      Write-Host "FAIL status=$status expected=$($ExpectedStatus -join ",")" -ForegroundColor Red
    }

    Write-Host $text
  }
}

Test-Route -Name "GET /api/v1" -Method "GET" -Uri "$ApiBaseUrl"
Test-Route -Name "GET /api/v1/workspace" -Method "GET" -Uri "$ApiBaseUrl/workspace"
Test-Route -Name "GET /api/v1/domains" -Method "GET" -Uri "$ApiBaseUrl/domains"
Test-Route -Name "GET /api/v1/domains/:hostname" -Method "GET" -Uri "$ApiBaseUrl/domains/$Domain"
Test-Route -Name "GET /api/v1/usage/current" -Method "GET" -Uri "$ApiBaseUrl/usage/current"
Test-Route -Name "GET /api/v1/usage/history" -Method "GET" -Uri "$ApiBaseUrl/usage/history?months=12"
Test-Route -Name "GET /api/v1/domains/:hostname/usage/current" -Method "GET" -Uri "$ApiBaseUrl/domains/$Domain/usage/current"
Test-Route -Name "GET /api/v1/domains/:hostname/usage/history" -Method "GET" -Uri "$ApiBaseUrl/domains/$Domain/usage/history?months=12"

$chat1 = @{
  domain = $Domain
  message = "What services do you offer?"
}

Test-Route -Name "POST /api/v1/chat/messages without sessionId" -Method "POST" -Uri "$ApiBaseUrl/chat/messages" -Body $chat1

$chat2 = @{
  domain = $Domain
  sessionId = "manual-test-session-001"
  message = "And what are the pricing options?"
}

Test-Route -Name "POST /api/v1/chat/messages with sessionId" -Method "POST" -Uri "$ApiBaseUrl/chat/messages" -Body $chat2

$BadHeaders = @{
  Authorization = "Bearer invalid_key"
  "Content-Type" = "application/json"
}

Test-Route -Name "GET /api/v1/workspace without auth" -Method "GET" -Uri "$ApiBaseUrl/workspace" -RequestHeaders $null -ExpectedStatus @(401)
Test-Route -Name "GET /api/v1/workspace with invalid key" -Method "GET" -Uri "$ApiBaseUrl/workspace" -RequestHeaders $BadHeaders -ExpectedStatus @(401)
Test-Route -Name "POST /api/v1/chat/messages with empty body" -Method "POST" -Uri "$ApiBaseUrl/chat/messages" -Body "{}" -ExpectedStatus @(400)
Test-Route -Name "POST /api/v1/chat/messages with malformed JSON" -Method "POST" -Uri "$ApiBaseUrl/chat/messages" -Body '{' -ExpectedStatus @(400)

$largeBody = @{
  domain = $Domain
  message = ("x" * 40000)
} | ConvertTo-Json -Compress

Test-Route -Name "POST /api/v1/chat/messages with oversized body" -Method "POST" -Uri "$ApiBaseUrl/chat/messages" -Body $largeBody -ExpectedStatus @(413)
Test-Route -Name "POST /api/v1/chat/messages with foreign domain" -Method "POST" -Uri "$ApiBaseUrl/chat/messages" -Body @{ domain = "not-owned-example.test"; message = "Hello" } -ExpectedStatus @(404)
Erori

Răspunsuri de eroare frecvente

Erorile includ un câmp code lizibil de mașină. Folosește acel câmp în integrarea ta. Nu te baza pe formularea exactă a mesajului din câmpul error.

Când API-ul răspunde cu 429 RATE_LIMITED, respectă headerul Retry-After dacă este prezent.

CodSemnificațieCe faci mai departe
API_AUTH_REQUIREDBearer token lipsește sau este invalidTrimite Authorization: Bearer <key>
API_SCOPE_REQUIREDCheia nu are permisiunea cerută de endpointCreează o cheie cu permisiunea necesară
API_ACCESS_NOT_AVAILABLEPlanul activ nu include Acces APITreci la un plan care include Acces API sau verifică statusul planului
DOMAIN_NOT_FOUNDDomeniul lipsește, a fost șters sau nu aparține spațiului de lucruVerifică domeniul în panou
API_KEY_INVALIDCheia este greșită, revocată, expirată sau formatată incorectVerifică cheia sau creează una nouă
ANALYTICS_NOT_AVAILABLEPlanul activ nu include analyticsFolosește endpointurile de utilizare curentă sau schimbă planul
VALIDATION_ERRORLipsesc câmpuri obligatorii sau valorile sunt invalideVerifică valori precum domain și message
INVALID_JSONCorpul cererii nu este JSON validCorectează formatul JSON sau folosește ConvertTo-Json
PAYLOAD_TOO_LARGECorpul cererii este prea mareRedu dimensiunea cererii
RATE_LIMITEDAi trimis prea multe cereri într-un interval scurtAșteaptă și reîncearcă după Retry-After, dacă este prezent
CHAT_RELAY_FAILEDServiciul de chat nu a putut procesa mesajulReîncearcă mai târziu; dacă problema persistă, verifică statusul serviciului
Securitate

Bune practici de securitate

Tratează cheile API ca pe parole. Nu le lipi în asistenți AI, chaturi de suport, screenshoturi, loguri, cod de browser, aplicații mobile sau repository-uri publice. Dacă o cheie a fost expusă, revoc-o imediat și creează una nouă.

Folosește chei separate pentru fiecare integrare sau mediu și acordă fiecăreia doar permisiunile necesare. Panoul poate afișa când o cheie a fost folosită ultima dată, dar nu expune adrese IP.

Utilizarea API nu este un jurnal de cereri. Afișează doar contoare agregate. Nu expune corpuri de cerere, mesaje chat, răspunsuri ale asistentului, headere Authorization, chei API brute sau adrese IP.