Conviro API · v1 · stable

Yapay zekâ destek ajanını 5 dakikada

Kendi bilgi tabanınızdan beslenen, ticket çözen, müşteri adayı yakalayan ve insana devreden bir REST API ve webhook seti — orchestration'ı siz kurmadan.

Base URL
api.conviro.io/v1
Auth
Bearer token
Yanıt
JSON · p50 ~450ms
zsh — conviro
$ curl -s api.conviro.io/v1/api/sessions/sess_3f2a/messages \
  -H "Authorization: Bearer cvr_live_***" \
  -d '{"content":"How do I return an order?"}'

# 201 Created — the AI reply follows via the message.new webhook
{
  "messageId": "6d1f0c6e-3b7a-...",
  "role": "system",
  "content": "Message received. Preparing a response...",
  "status": "queued"
}

Hızlı başlangıç

İlk başarılı isteğiniz

Üç adım. Kopyala-yapıştır. Altmış saniye içinde gerçek bir AI yanıtı görürsünüz — veya kayıt olmadan terminalinizden hemen deneyin.

API anahtarı olmadan dene — hemen şimdi

IP başına 5 req/dk
curl -X POST https://conviro.io/api/developers/demo \
  -H "Content-Type: application/json" \
  -d '{"content": "I want to return my last order"}'
  1. 1

    API anahtarı oluştur

    Şuraya gidin: Ayarlar → API Anahtarları ve şu scope ile bir anahtar oluşturun: chat:write . Yalnızca bir kez gösterilir — secret manager'da saklayın.

    API anahtarı al
  2. 2

    Mesaj gönder

    Bearer token ile /sessions/:id/messages'a POST. Mevcut session id'nizi kullanın veya önce POST /sessions ile yeni oluşturun.

  3. 3

    Yanıtı işle

    Şunları alırsınız: messageId ve "queued" durumu. Yapay zekâ yanıtı asenkron üretilir — message.new webhook'una abone olun ya da oturumu GET /sessions/:id ile okuyun.

curl -X POST https://api.conviro.io/v1/api/sessions/SESSION_ID/messages \
  -H "Authorization: Bearer cvr_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"content": "Can I return an item I bought yesterday?"}'

Yanıt

201 Created · application/json
{
  "messageId": "6d1f0c6e-3b7a-4f0e-9a52-8c1e2d4b7a90",
  "role": "system",
  "content": "Message received. Preparing a response...",
  "createdAt": "2026-04-14T10:22:03.412Z",
  "status": "queued"
}

Playground

Try it right now — no signup

Real HTTP requests to a rate-limited demo endpoint that returns scripted replies — no AI model is called, and the delay is artificial. The authenticated API answers asynchronously (see the quick start below).

Scripted demo

Demo ajan

POST /api/developers/demo

Simüle demo — hazır yanıtlar ve yapay gecikme; hiçbir yapay zekâ modeli çağrılmaz. Gerçek API yanıtı asenkron verir.

Merhaba 👋 Ben canlı bir demoyum. Bir hazır soruyu deneyin, yukarıdaki use-case'lere tıklayın veya kendi sorunuzu yazın.

greetingconf 1.00

API ne döndü

{
  "intent": "greeting",
  "confidence": 1,
  "model": "scripted-demo",
  "message": {
    "role": "assistant",
    "content": "Merhaba 👋 Ben canlı bir demoyum. Bir hazır soruyu deneyin, yukarıdaki use-case'lere tıklayın veya kendi sorunuzu yazın."
  }
}

Demo uç noktası şu hızla sınırlı: 5 req/min per IP. Gerçek bir API anahtarı varsayılan olarak 60 rpm alır (yapılandırılabilir).

Kullanım alanları

Ekiplerin gerçekten kurduğu şeyler

Bir karta tıklayarak playground'da canlı çalıştırın — gerçek API yanıtını bir saniye içinde görürsünüz.

Referans

API yüzeyi

En çok kullanacağınız uç noktalar. Base URL: https://api.conviro.io/v1/api

Tam referans
MethodPathGerekli scope
POST/sessionschat:write
GET/sessionschat:read
GET/sessions/:id/messageschat:read
GET/sessions/:idchat:read
POST/sessions/:id/messageschat:write
POST/sessions/:id/identifychat:write
POST/knowledgekb:write
DELETE/knowledge/:idkb:write
GET/analytics/summaryanalytics:read
GET/contactscontacts:read
GET/contacts/:idcontacts:read
POST/contactscontacts:write
PATCH/contacts/:idcontacts:write
GET/lead-formschat:read or magento:module
GET/appointments/slotsappointments:read
POST/appointmentsappointments:write
GET/appointmentsappointments:read
DELETE/appointments/:idappointments:write
GET/webhookswebhooks:write
POST/webhookswebhooks:write
DELETE/webhooks/:idwebhooks:write
POST/consent/whatsappconsent:write
chat:readRead sessions and their messages, and list lead forms.
chat:writeCreate sessions, send messages, identify visitors.
kb:readRead knowledge base items. Minted, but required by no public operation today.
kb:writeCreate and delete knowledge base items, and drive the e-commerce sync endpoints.
analytics:readRead the workspace analytics summary.
webhooks:writeManage webhook subscriptions. Note this is required to LIST them as well as to change them — there is no webhooks:read scope, so a read-only integration still needs the write scope here.
contacts:readRead CRM contacts. Returns PII.
contacts:writeCreate and update CRM contacts — the records human agents work from.
leads:writeCreate a lead: drop a new inbound record at the top of the funnel. Deliberately narrower than contacts:write, so an automation posting form fills does not also get the power to rewrite existing people. Minted, but required by no public operation today.
appointments:readRead open slots and booked appointments.
appointments:writeBook and cancel appointments.
consent:writeRecord a WhatsApp marketing opt-in. Its own scope rather than riding on leads or contacts: a key that can post form fills should not also be able to assert that a person agreed to campaigns.
magento:moduleWhat the Conviro Magento module (1.4.0+) needs and nothing more: it registers its store, delivers the store event outbox, reads the admin stats cards and lists lead forms. It reads no conversation and writes no knowledge-base item through the public API. The module's browser-mediated connect mints a key with only this scope, limited to the chosen assistant.

SDK'lar

Kütüphaneler ve istemciler

Resmi SDK'ları aşamalı olarak gönderiyoruz. REST API küçük, kararlı ve sarmak kolay — beklemek zorunda değilsiniz.

Node.js / TypeScript

Resmi · yakında
// @conviro/sdk — in private beta. The REST API
// already works great with fetch/axios today.

PHP

Resmi · yakında
// composer require conviro/sdk — in private beta.
// Use the cURL example below in the meantime.

Python

Topluluk
# No official SDK yet — the REST API is small enough
# that plain `requests` or `httpx` works well.

Go, Ruby, C#

REST API'yi doğrudan kullan
// No SDK — any HTTP client works. The auth header
// is the only thing you need.
Browse the cookbookWooCommerce pluginWorking snippets for embeds, webhooks, CRM bridges, and platform plugins.

Hatalar

Öngörülebilir hata şekilleri

Her 2xx olmayan yanıt aynı JSON zarfını kullanır. Destekle iletişime geçtiğinizde requestId değerini iletin.

DurumAdNe zaman olur
400Bad RequestThe request was rejected by the handler. `message` is a single string. A 4xx may additionally carry `error`, `code`, `reason` or `state`: a machine-readable name, always one identifier (lower_snake or UPPER_SNAKE). Branch on that name when it is present, never on `message`; most errors carry none.
400Bad Request (validation)Body validation failed. Same status and same keys as bad_request, but `message` is an ARRAY of strings, one per failed constraint. Parse it as `string | string[]` or the most common 400 in the API will crash your error handler. Unknown fields also land here: the global pipe runs with forbidNonWhitelisted, so an undeclared field is a 400 rather than being ignored — except on the two contacts endpoints that bind no DTO class, where unknown fields pass through silently.
401UnauthorizedMissing or malformed Authorization header, or an invalid, revoked or expired key. Never retry: the credential will not become valid.
403ForbiddenThe key is valid but lacks the scope, or is restricted to assistants that do not include the one referenced. Scopes are evaluated with OR: holding ANY of the listed scopes is enough. Fix the key, do not retry.
404Not FoundNo such resource in your workspace. A resource that exists in another tenant is a 404 here, not a 403 — the tenant filter is applied before the lookup, so cross-tenant ids are indistinguishable from absent ones. That is deliberate.
429Too Many RequestsPer-key rate limit exceeded. THIS BODY IS DIFFERENT: it carries `retryAfter` and NO `timestamp`, because the guard writes it directly to the response and never reaches the global filter. A `Retry-After: 60` header is set. The separate plan-level limiter produces a 429 with a different message and no `retryAfter`. Retry after the header says, with backoff.
500Server ErrorSomething failed on our side. The message is always this fixed string — internal detail is logged, never returned. Retry with exponential backoff.

Yanıt gövdesi

application/json
{
  "statusCode": 401,
  "error": "Unauthorized",
  "message": "API key is missing or invalid.",
  "requestId": "req_1H8z...",
  "docsUrl": "https://conviro.io/developers#errors"
}

429'da Retry-After header'ına uyun. 5xx'te üstel geri çekilme ile en fazla üç kez tekrarlayın.

Webhooks

Gerçek zamanlı olaylar, doğrulanmış

Her teslimi HMAC-SHA256 ile imzalarız. Başarısız teslimler üstel geri çekilme ile üç kez tekrarlanır. Devre kesici sürekli başarısız uç noktaları 60s karantinaya alır.

Olaylar

  • message.newA message was added to a session, by the visitor or by the assistant.
  • session.startedA new conversation session was created.
  • session.closedA session was closed.
  • session.escalatedA session was escalated to a human.
  • handoff.requestedA visitor asked for a human agent.
  • lead.capturedA lead was captured from a conversation.
  • lead.createdA lead record was created outside a chat — from an ad integration, a lead form, or an e-commerce order.
  • lead_form.submittedA lead form was submitted.
  • csat.submittedA CSAT rating was submitted.
  • csat.receivedThe same rating as csat.
  • ai.failedThe assistant could not produce an answer.
  • ticket.createdA support ticket was opened.
  • ticket.resolvedA support ticket was resolved.
  • contact.createdA CRM contact was created.
  • contact.updatedA CRM contact was updated.
  • contact.mergedTwo CRM contacts were merged.
  • contact.deletedA CRM contact was deleted.
  • appointment.bookedAn appointment was booked. Not listed in the dashboard event picker — subscribe with "*" or by name.
  • appointment.cancelledAn appointment was cancelled. Not listed in the dashboard event picker — subscribe with "*" or by name.
  • lead.hotA lead crossed the hot-lead threshold. Not listed in the dashboard event picker — subscribe with "*" or by name.
  • lead.updatedA lead record was corrected after capture. Not listed in the dashboard event picker — subscribe with "*" or by name.

Payload

POST your-endpoint · application/json
{
  "event": "session.closed",
  "timestamp": "2026-04-14T10:22:03.412Z",
  "data": {
    "sessionId": "sess_3f2a...",
    "chatbotId": "bot_123"
  }
}

İmzayı doğrula

node.js
// Node.js (Express) — verify a Conviro webhook
import crypto from 'crypto';

// The RAW body is required. express.json() parses and discards it, and
// JSON.stringify(req.body) does NOT reproduce the signed bytes — key
// order and whitespace both change the digest.
app.post('/conviro/webhook',
  express.raw({ type: 'application/json', limit: '1mb' }),
  (req, res) => {
    if (!verify(req.body, req.header('X-Webhook-Signature'))) {
      return res.status(401).end();
    }
    res.status(200).end();            // acknowledge within 10s
    void handle(JSON.parse(req.body.toString('utf8')));
  });

const TOLERANCE_SECONDS = 300;

function verify(rawBody, header) {
  if (!header) return false;

  // Header format: t=<unix_seconds>,v1=<hex_digest>
  const parts = new Map(header.split(',').map((p) => {
    const i = p.indexOf('=');
    return [p.slice(0, i).trim(), p.slice(i + 1).trim()];
  }));
  const timestamp = parts.get('t');
  const signature = parts.get('v1');
  if (!timestamp || !signature) return false;

  // Replay window: without it, a captured payload is valid forever.
  const age = Math.abs(Math.floor(Date.now() / 1000) - Number(timestamp));
  if (!Number.isFinite(age) || age > TOLERANCE_SECONDS) return false;

  // The digest covers "<timestamp>.<rawBody>" — NOT the body on its own.
  const expected = crypto
    .createHmac('sha256', process.env.CONVIRO_WEBHOOK_SECRET)
    .update(timestamp + '.')
    .update(rawBody)
    .digest('hex');

  const a = Buffer.from(signature, 'utf8');
  const b = Buffer.from(expected, 'utf8');
  // timingSafeEqual throws on a length mismatch, so check length first.
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

Nasıl çalışır

Tek API çağrısı, eksiksiz pipeline

Mesajı gönderirsiniz — sınıflandırma, getirme, üretim ve yönlendirmeyi biz halleder. Sonraki adımı belirlemeniz için ihtiyacınız olan her şeyi tek bir yanıtta alırsınız.

  1. Ziyaretçi

    Mesaj gönderir

  2. Sınıflandır

    Niyet + güven

  3. Bilgi

    Bilgi tabanından getir

  4. Yanıt Üret

    Yanıt + önerilen eylemler

  5. Devret (gerekirse)

    Düşük güven → insan

Tipik gecikme
~450ms p50
Hız limiti
Anahtar başına 60 rpm · ayarlanabilir
Tekrar güvenli
Idempotent tekrarlar · webhook geri çekilme

Hazır olduğunuzda

İlk API çağrınız 60 saniye uzakta

API anahtarı oluşturun, quick-start snippet'i kopyalayın, gerçek yanıtı görün. Ücretsiz katman geliştirip test etmenize yetecek çağrıyı içerir.