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
chat:readCitește arhiva de chat limitată la subiectGET /api/v1/domains/:hostname/chat/sessions, GET /api/v1/domains/:hostname/chat/sessions/:sessionReference
Î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
GET /domains/:hostname/chat/sessionschat:readListează sesiunile de chat ale subiectului anonim
GET /domains/:hostname/chat/sessions/:sessionReferencechat:readCitește transcrierea unei sesiuni a subiectului anonim
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
Arhivă de conversații anonime

Arhiva publică de chat

Arhiva publică de chat permite unui client server autorizat să lege o sesiune de chat reușită de un subiect anonim opac, să listeze doar conversațiile legate de acel subiect, să redeschidă în siguranță o transcriere și să o continue prin endpointul de chat existent.

chat:write trimite sau continuă mesaje. chat:read listează și citește arhiva. Niciun scope nu îl include implicit pe celălalt.

Proprietatea conversației

Header pentru subiectul anonim

Trimite X-ZENIA-Anonymous-Subject din backendul tău de încredere. Valoarea trebuie să fie un singur șir de 32–128 caractere care conține doar A-Z, a-z, 0-9, _ sau -, fără spații la început sau la final.

Backendul tău generează și persistă o valoare opacă cu entropie ridicată. Nu o deriva din email, adresă IP, User-Agent sau alte date de identificare din browser. ZENIA stochează doar digestul SHA-256, nu subiectul brut.

Paginare

Paginarea arhivei

Listarea folosește implicit limit=20 și acceptă 1..50. Rezultatele sunt ordonate după cea mai recentă activitate din arhivă. Tratează cursor și nextCursor ca valori opace; nextCursor: null înseamnă că nu mai există o pagină următoare.

Proiecție sigură

Răspunsul listei de arhivă

Fiecare sumar expune sessionId extern, un preview determinist, numărul de mesaje și timestampurile. Sesiunile de bază lipsă sau stale sunt omise. Preview-ul nu este un titlu generat de AI.

JSON
{"ok":true,"sessions":[{"sessionId":"external-session-reference","preview":"First user message preview","messageCount":4,"createdAt":"2026-08-30T12:00:00.000Z","updatedAt":"2026-08-30T12:05:00.000Z"}],"nextCursor":null}
Proiecție sigură

Răspunsul pentru detaliul arhivei

Detaliul întoarce rol/conținut/timp plus doar metadatele de răspuns persistate și permise explicit, precum citații, confidence, guardrail, canonical resolution și follow-up actions. Fallback-ul istoric este omis când nu a fost persistat.

JSON
{"ok":true,"session":{"sessionId":"external-session-reference","createdAt":"2026-08-30T12:00:00.000Z","updatedAt":"2026-08-30T12:05:00.000Z","messages":[{"role":"user","content":"Example question","createdAt":"2026-08-30T12:00:00.000Z"},{"role":"assistant","content":"Example grounded answer","createdAt":"2026-08-30T12:00:01.000Z","citations":[],"confidence":"medium"}]}}
Doar server-to-server

Limita de confidențialitate a arhivei

Păstrează cheia API și subiectul anonim într-un backend/BFF de încredere. Nu include o cheie API ZENIA secretă în cod de browser sau aplicație mobilă.

DTO-urile arhivei nu întorc IP/User-Agent, subiectul brut sau digestul lui, ID-uri interne de workspace, ChatSession._id intern, retrieval frames, candidați/scoruri brute, chei/conflict internals, adnotări de operator sau metadate necunoscute. Conținutul transcrierii rămâne canonic în stocarea chatului; arhiva păstrează doar asocierea subiect/sesiune.

Erori arhivă

Erori ale arhivei publice de chat

Folosește câmpul code citibil de mașină. Erorile de sesiune normalizate pentru securitate nu dezvăluie dacă o sesiune străină există.

CodHTTPSemnificație
ANONYMOUS_SUBJECT_REQUIRED400Citirea arhivei necesită headerul de subiect
ANONYMOUS_SUBJECT_INVALID400Headerul subiectului anonim este invalid
VALIDATION_ERROR400Body, paginare sau cursor invalid
API_SCOPE_REQUIRED403Cheia API nu are scope-ul chat:read sau chat:write necesar
DOMAIN_NOT_FOUND404Domeniul nu este disponibil sau nu aparține workspace-ului cheii API
CHAT_SESSION_NOT_AVAILABLE404Sesiunea nu este disponibilă, legată, actuală sau aparține altui subiect; existența nu este dezvăluită
CHAT_ARCHIVE_BIND_FAILED500Chatul a reușit, dar asocierea cu arhiva nu a putut fi finalizată
CHAT_ARCHIVE_READ_FAILED500Eroare neașteptată la citirea arhivei
Creează o sesiune legată de subiect
PowerShell
$Subject = $env:ZENIA_ANONYMOUS_SUBJECT
$ArchiveHeaders = @{
  Authorization = "Bearer $ApiKey"
  "Content-Type" = "application/json"
  "X-ZENIA-Anonymous-Subject" = $Subject
}
$Body = @{ domain = $Domain; message = "What services do you offer?" } | ConvertTo-Json -Compress
Invoke-RestMethod -Method Post -Uri "$ApiBaseUrl/chat/messages" -Headers $ArchiveHeaders -Body $Body
Continuă o sesiune legată de subiect
PowerShell
$Body = @{
  domain = $Domain
  sessionId = "SESSION_ID_FROM_PREVIOUS_RESPONSE"
  message = "Continue the same conversation"
} | ConvertTo-Json -Compress
Invoke-RestMethod -Method Post -Uri "$ApiBaseUrl/chat/messages" -Headers $ArchiveHeaders -Body $Body
Listează sesiunile arhivei subiectului
PowerShell
Invoke-RestMethod `
  -Method Get `
  -Uri "$ApiBaseUrl/domains/$Domain/chat/sessions?limit=20" `
  -Headers $ArchiveHeaders
Citește o sesiune din arhivă
PowerShell
$SessionReference = "SESSION_ID_FROM_ARCHIVE"
Invoke-RestMethod `
  -Method Get `
  -Uri "$ApiBaseUrl/domains/$Domain/chat/sessions/$SessionReference" `
  -Headers $ArchiveHeaders
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.