Help Center Usage

Usage

#ოპერატორები

მართეთ ჩატის ოპერატორები თქვენს ChatHub ორგანიზაციებში. ოპერატორები არიან აგენტები, რომლებიც მართავენ მომხმარებელთა საუბრებს.

მიმოხილვა

ოპერატორები ChatHub-ში:

  • გაუმკლავდეთ მომხმარებელთა ჩეთის საუბრებს
  • ეკუთვნით კონკრეტულ ორგანიზაციებს
  • გქონდეთ აქტიური, არააქტიური ან წაშლილი სტატუსი
  • შეიძლება ჰქონდეს ინდივიდუალური ავთენტიფიკაციის ნიშნები
  • მიიღეთ და უპასუხეთ შეტყობინებებს

ოპერატორების სია

მიიღეთ ყველა ოპერატორი კონკრეტული ორგანიზაციისთვის.

საბოლოო წერტილი

GET /api/operator?organizationId={id}

მოთხოვნა

curl -X GET "https://chatapi.smsbat.com/api/operator?organizationId=24" \
  -H "Authorization: Bearer {company-token}" \
  -H "Accept: text/plain"

პარამეტრები

პარამეტრიტიპიმდებარეობასაჭიროაღწერა
ორგანიზაციის IDმთელი რიცხვიშეკითხვადიახორგანიზაციის ID

სათაურები

სათაურიღირებულებასაჭირო
ავტორიზაციამატარებელი {token}დიახ
მიღებატექსტი/უბრალოდიახ

პასუხი

[
  {
    "id": 101,
    "name": "John Smith",
    "status": 0,
    "organization": {
      "id": 24,
      "name": "Customer Support"
    }
  },
  {
    "id": 102,
    "name": "Sarah Johnson",
    "status": 0,
    "organization": {
      "id": 24,
      "name": "Customer Support"
    }
  },
  {
    "id": 103,
    "name": "Mike Wilson",
    "status": 1,
    "organization": {
      "id": 24,
      "name": "Customer Support"
    }
  }
]

რეაგირების ველები

ველიტიპიაღწერა
idმთელი რიცხვიოპერატორის უნიკალური იდენტიფიკატორი
სახელისიმებიანიოპერატორის საჩვენებელი სახელი
სტატუსსმთელი რიცხვიოპერატორის სტატუსი (0=აქტიური, 1=არააქტიური, 2=წაშლილი)
ორგანიზაციაობიექტიმშობელი ორგანიზაციის დეტალები
organization.idმთელი რიცხვიორგანიზაციის ID
ორგანიზაცია.სახელისიმებიანიორგანიზაციის სახელი

ოპერატორის სტატუსი

სტატუსიღირებულებააღწერა
აქტიური0ოპერატორი ამჟამად მუშაობს და შეუძლია ჩეთების მიღება
არააქტიური1ოპერატორი დროებით გამორთულია
წაშლილია2ოპერატორი ამოღებულია სისტემიდან

დაამატეთ ოპერატორები

დაამატეთ ახალი ოპერატორები ორგანიზაციებს სინქრონიზაციის ბოლო წერტილის გამოყენებით.

საბოლოო წერტილი

POST /api/operator/synchronize

მოთხოვნა

curl -X POST https://chatapi.smsbat.com/api/operator/synchronize \
  -H "Authorization: Bearer {company-token}" \
  -H "Content-Type: application/json" \
  -d '[
    {
      "organizationId": 24,
      "name": "Alex Brown"
    },
    {
      "organizationId": 24,
      "name": "Emma Davis"
    }
  ]'

მოთხოვნის ორგანო

ოპერატორის ობიექტების მასივი:

[
  {
    "organizationId": 24,
    "name": "Alex Brown"
  },
  {
    "organizationId": 24,
    "name": "Emma Davis"
  }
]

მოთხოვნის ველები

ველიტიპისაჭიროაღწერა
ორგანიზაციის IDმთელი რიცხვიდიახსამიზნე ორგანიზაციის ID
სახელისიმებიანიდიახოპერატორის საჩვენებელი სახელი

პასუხი

[
  {
    "id": 104,
    "name": "Alex Brown",
    "status": 0
  },
  {
    "id": 105,
    "name": "Emma Davis",
    "status": 0
  }
]

შეცვალეთ ოპერატორის სტატუსი

ოპერატორის სტატუსის განახლება (აქტიური/არააქტიური/წაშლილი).

საბოლოო წერტილი

POST /api/operator/status

მოთხოვნა

curl -X POST https://chatapi.smsbat.com/api/operator/status \
  -H "Authorization: Bearer {company-token}" \
  -H "Content-Type: application/json" \
  -d '{
    "id": 104,
    "status": 1
  }'

მოთხოვნის ორგანო

{
  "id": 0,
  "status": 0
}

მოთხოვნის ველები

ველიტიპისაჭიროაღწერა
idმთელი რიცხვიდიახოპერატორის ID
სტატუსსმთელი რიცხვიდიახახალი სტატუსი (0=აქტიური, 1=არააქტიური, 2=წაშლილი)

პასუხი

200 OK

წარმატება აბრუნებს HTTP 200-ს პასუხის გარეშე.

სტატუსის მნიშვნელობები

სტატუსიღირებულებააღწერა
აქტიური0ოპერატორს შეუძლია ჩეთების მართვა
არააქტიური1ოპერატორი დროებით გამორთულია
წაშლილია2ოპერატორი ამოღებულია სისტემიდან

მაგალითი: გამორთეთ ოპერატორი

curl -X POST https://chatapi.smsbat.com/api/operator/status \
  -H "Authorization: Bearer {company-token}" \
  -H "Content-Type: application/json" \
  -d '{
    "id": 104,
    "status": 1
  }'

მაგალითი: ხელახლა გააქტიურეთ ოპერატორი

curl -X POST https://chatapi.smsbat.com/api/operator/status \
  -H "Authorization: Bearer {company-token}" \
  -H "Content-Type: application/json" \
  -d '{
    "id": 104,
    "status": 0
  }'

მაგალითი: წაშალე ოპერატორი

curl -X POST https://chatapi.smsbat.com/api/operator/status \
  -H "Authorization: Bearer {company-token}" \
  -H "Content-Type: application/json" \
  -d '{
    "id": 104,
    "status": 2
  }'

განხორციელების მაგალითები

პითონი

import requests

class OperatorManager:
    def __init__(self, company_token, base_url='https://chatapi.smsbat.com'):
        self.company_token = company_token
        self.base_url = base_url
        self.headers = {
            'Authorization': f'Bearer {company_token}',
            'Accept': 'text/plain'
        }

    def list_operators(self, organization_id):
        """Get all operators for an organization"""
        response = requests.get(
            f'{self.base_url}/api/operator',
            headers=self.headers,
            params={'organizationId': organization_id}
        )
        response.raise_for_status()
        return response.json()

    def add_operators(self, operators):
        """Add new operators
        Args:
            operators: List of dicts with organizationId and name
        """
        response = requests.post(
            f'{self.base_url}/api/operator/synchronize',
            headers={**self.headers, 'Content-Type': 'application/json'},
            json=operators
        )
        response.raise_for_status()
        return response.json()

    def get_active_operators(self, organization_id):
        """Get only active operators"""
        operators = self.list_operators(organization_id)
        return [op for op in operators if op['status'] == 0]

    def find_operator_by_name(self, organization_id, name):
        """Find operator by name"""
        operators = self.list_operators(organization_id)
        for operator in operators:
            if operator['name'].lower() == name.lower():
                return operator
        return None

    def change_operator_status(self, operator_id, status):
        """Change operator status
        Args:
            operator_id: Operator ID
            status: 0 (Active), 1 (Inactive), 2 (Deleted)
        """
        response = requests.post(
            f'{self.base_url}/api/operator/status',
            headers={**self.headers, 'Content-Type': 'application/json'},
            json={'id': operator_id, 'status': status}
        )
        response.raise_for_status()
        return response.status_code == 200

manager = OperatorManager('your-company-token')

# List operators
operators = manager.list_operators(organization_id=24)
print(f"Found {len(operators)} operators")

# Get only active operators
active = manager.get_active_operators(24)
print(f"{len(active)} active operators")

# Add new operators
new_operators = manager.add_operators([
    {'organizationId': 24, 'name': 'John Doe'},
    {'organizationId': 24, 'name': 'Jane Smith'}
])
print(f"Added {len(new_operators)} operators")

# Find operator by name
operator = manager.find_operator_by_name(24, 'John Doe')
if operator:
    print(f"Found operator: {operator['name']} (ID: {operator['id']})")

# Change operator status
manager.change_operator_status(104, 1)  # Deactivate
print("Operator deactivated")

manager.change_operator_status(104, 0)  # Reactivate
print("Operator reactivated")

JavaScript (Node.js)

const axios = require('axios');

class OperatorManager {
  constructor(companyToken, baseUrl = 'https://chatapi.smsbat.com') {
    this.companyToken = companyToken;
    this.baseUrl = baseUrl;
    this.headers = {
      'Authorization': `Bearer ${companyToken}`,
      'Accept': 'text/plain'
    };
  }

  async listOperators(organizationId) {
    const response = await axios.get(
      `${this.baseUrl}/api/operator`,
      {
        headers: this.headers,
        params: { organizationId }
      }
    );

    return response.data;
  }

  async addOperators(operators) {
    const response = await axios.post(
      `${this.baseUrl}/api/operator/synchronize`,
      operators,
      {
        headers: {
          ...this.headers,
          'Content-Type': 'application/json'
        }
      }
    );

    return response.data;
  }

  async getActiveOperators(organizationId) {
    const operators = await this.listOperators(organizationId);
    return operators.filter(op => op.status === 0);
  }

  async findOperatorByName(organizationId, name) {
    const operators = await this.listOperators(organizationId);
    return operators.find(op =>
      op.name.toLowerCase() === name.toLowerCase()
    );
  }

  async getOperatorById(organizationId, operatorId) {
    const operators = await this.listOperators(organizationId);
    return operators.find(op => op.id === operatorId);
  }

  async changeOperatorStatus(operatorId, status) {
    const response = await axios.post(
      `${this.baseUrl}/api/operator/status`,
      { id: operatorId, status },
      {
        headers: {
          ...this.headers,
          'Content-Type': 'application/json'
        }
      }
    );

    return response.status === 200;
  }
}

// Usage
const manager = new OperatorManager('your-company-token');

async function manageOperators() {
  // List operators
  const operators = await manager.listOperators(24);
  console.log(`Found ${operators.length} operators`);

  // Get active operators
  const active = await manager.getActiveOperators(24);
  console.log(`${active.length} active operators`);

  // Add new operators
  const newOperators = await manager.addOperators([
    { organizationId: 24, name: 'John Doe' },
    { organizationId: 24, name: 'Jane Smith' }
  ]);
  console.log(`Added ${newOperators.length} operators`);

  // Find operator by name
  const operator = await manager.findOperatorByName(24, 'John Doe');
  if (operator) {
    console.log(`Found: ${operator.name} (ID: ${operator.id})`);
  }

  // Change operator status
  await manager.changeOperatorStatus(104, 1); // Deactivate
  console.log('Operator deactivated');

  await manager.changeOperatorStatus(104, 0); // Reactivate
  console.log('Operator reactivated');
}

manageOperators();

PHP

<?php

class OperatorManager {
    private $companyToken;
    private $baseUrl;

    public function __construct($companyToken, $baseUrl = 'https://chatapi.smsbat.com') {
        $this->companyToken = $companyToken;
        $this->baseUrl = $baseUrl;
    }

    public function listOperators($organizationId) {
        $url = $this->baseUrl . '/api/operator?organizationId=' . $organizationId;

        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Authorization: Bearer ' . $this->companyToken,
            'Accept: text/plain'
        ]);

        $response = curl_exec($ch);
        curl_close($ch);

        return json_decode($response, true);
    }

    public function addOperators($operators) {
        $ch = curl_init($this->baseUrl . '/api/operator/synchronize');

        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Authorization: Bearer ' . $this->companyToken,
            'Content-Type: application/json',
            'Accept: text/plain'
        ]);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($operators));

        $response = curl_exec($ch);
        curl_close($ch);

        return json_decode($response, true);
    }

    public function getActiveOperators($organizationId) {
        $operators = $this->listOperators($organizationId);
        return array_filter($operators, function($op) {
            return $op['status'] === 0;
        });
    }

    public function findOperatorByName($organizationId, $name) {
        $operators = $this->listOperators($organizationId);

        foreach ($operators as $operator) {
            if (strcasecmp($operator['name'], $name) === 0) {
                return $operator;
            }
        }

        return null;
    }

    public function changeOperatorStatus($operatorId, $status) {
        $ch = curl_init($this->baseUrl . '/api/operator/status');

        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Authorization: Bearer ' . $this->companyToken,
            'Content-Type: application/json'
        ]);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
            'id' => $operatorId,
            'status' => $status
        ]));

        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        return $httpCode === 200;
    }
}

// Usage
$manager = new OperatorManager('your-company-token');

// List operators
$operators = $manager->listOperators(24);
echo "Found " . count($operators) . " operators\n";

// Get active operators
$active = $manager->getActiveOperators(24);
echo count($active) . " active operators\n";

// Add new operators
$newOperators = $manager->addOperators([
    ['organizationId' => 24, 'name' => 'John Doe'],
    ['organizationId' => 24, 'name' => 'Jane Smith']
]);
echo "Added " . count($newOperators) . " operators\n";

// Find operator
$operator = $manager->findOperatorByName(24, 'John Doe');
if ($operator) {
    echo "Found: " . $operator['name'] . " (ID: " . $operator['id'] . ")\n";
}

// Change operator status
$manager->changeOperatorStatus(104, 1); // Deactivate
echo "Operator deactivated\n";

$manager->changeOperatorStatus(104, 0); // Reactivate
echo "Operator reactivated\n";

საერთო გამოყენების შემთხვევები

ბორტზე ახალი გუნდის წევრები

async function onboardOperators(teamMembers, organizationId) {
  const operators = teamMembers.map(member => ({
    organizationId,
    name: member.fullName
  }));

  const created = await addOperators(operators);

  // Generate tokens for each operator
  for (const operator of created) {
    const token = await getOperatorToken(operator.id);
    await sendWelcomeEmail(operator, token);
  }

  return created;
}

მონიტორის ოპერატორის სტატუსი

async function getOperatorStatistics(organizationId) {
  const operators = await listOperators(organizationId);

  return {
    total: operators.length,
    active: operators.filter(op => op.status === 0).length,
    inactive: operators.filter(op => op.status === 1).length,
    deleted: operators.filter(op => op.status === 2).length
  };
}

დატვირთვის დაბალანსება

async function assignChatToOperator(organizationId, chatId) {
  const activeOperators = await getActiveOperators(organizationId);

  if (activeOperators.length === 0) {
    throw new Error('No active operators available');
  }

  // Simple round-robin assignment
  const operatorIndex = chatId % activeOperators.length;
  return activeOperators[operatorIndex];
}

ნაყარი იმპორტი

async function importOperatorsFromCSV(csvData, organizationId) {
  const lines = csvData.split('\n').slice(1); // Skip header

  const operators = lines
    .filter(line => line.trim())
    .map(line => {
      const [name] = line.split(',');
      return { organizationId, name: name.trim() };
    });

  // Batch import in chunks of 100
  const chunkSize = 100;
  const results = [];

  for (let i = 0; i < operators.length; i += chunkSize) {
    const chunk = operators.slice(i, i + chunkSize);
    const imported = await addOperators(chunk);
    results.push(...imported);

    console.log(`Imported ${results.length}/${operators.length}`);
  }

  return results;
}

საუკეთესო პრაქტიკა

შეცდომის დამუშავება

async function addOperatorsSafely(operators) {
  try {
    return await addOperators(operators);
  } catch (error) {
    if (error.response?.status === 400) {
      console.error('Invalid operator data:', error.response.data);
      // Handle validation errors
    } else if (error.response?.status === 401) {
      console.error('Authentication failed');
      // Refresh token
    } else {
      console.error('Unexpected error:', error);
    }

    throw error;
  }
}

ქეშირება

class CachedOperatorManager extends OperatorManager {
  constructor(companyToken) {
    super(companyToken);
    this.cache = new Map();
    this.cacheTTL = 60000; // 1 minute
  }

  async listOperators(organizationId, useCache = true) {
    const cacheKey = `org_${organizationId}`;
    const cached = this.cache.get(cacheKey);

    if (useCache && cached && Date.now() - cached.time < this.cacheTTL) {
      return cached.data;
    }

    const data = await super.listOperators(organizationId);

    this.cache.set(cacheKey, {
      data,
      time: Date.now()
    });

    return data;
  }

  clearCache(organizationId = null) {
    if (organizationId) {
      this.cache.delete(`org_${organizationId}`);
    } else {
      this.cache.clear();
    }
  }
}

დადასტურება

function validateOperatorData(operators) {
  const errors = [];

  operators.forEach((op, index) => {
    if (!op.organizationId) {
      errors.push(`Operator ${index}: Missing organizationId`);
    }

    if (!op.name || op.name.trim().length === 0) {
      errors.push(`Operator ${index}: Name is required`);
    }

    if (op.name && op.name.length > 100) {
      errors.push(`Operator ${index}: Name too long (max 100 chars)`);
    }
  });

  if (errors.length > 0) {
    throw new Error('Validation failed:\n' + errors.join('\n'));
  }
}

// Usage
try {
  validateOperatorData(operatorData);
  await addOperators(operatorData);
} catch (error) {
  console.error(error.message);
}

რეიტინგის შეზღუდვა

class RateLimitedOperatorManager extends OperatorManager {
  constructor(companyToken, requestsPerSecond = 5) {
    super(companyToken);
    this.minInterval = 1000 / requestsPerSecond;
    this.lastRequest = 0;
  }

  async throttle() {
    const now = Date.now();
    const timeSinceLastRequest = now - this.lastRequest;

    if (timeSinceLastRequest < this.minInterval) {
      await new Promise(resolve =>
        setTimeout(resolve, this.minInterval - timeSinceLastRequest)
      );
    }

    this.lastRequest = Date.now();
  }

  async listOperators(organizationId) {
    await this.throttle();
    return super.listOperators(organizationId);
  }

  async addOperators(operators) {
    await this.throttle();
    return super.addOperators(operators);
  }
}

პრობლემების მოგვარება

ოპერატორები არ დაბრუნებულა

  • დაადასტურეთ, რომ ორგანიზაციის ID არის სწორი
  • შეამოწმეთ ორგანიზაცია არსებობს და ჰყავს ოპერატორები
  • დარწმუნდით, რომ კომპანიის ტოკენს აქვს წვდომა ორგანიზაციაზე

ოპერატორების დამატება ვერ მოხერხდა

  • დაადასტურეთ, რომ ორგანიზაცია Id არსებობს
  • შეამოწმეთ ოპერატორის სახელის ფორმატი
  • დარწმუნდით, რომ კომპანიის ჟეტონი მოქმედებს
  • შეამოწმეთ, რომ JSON ფორმატი სწორია

401 უნებართვო

  • შეამოწმეთ კომპანიის ჟეტონი მოქმედებს
  • ჩეკის ჟეტონს ვადა არ გაუვიდა
  • საჭიროების შემთხვევაში მოითხოვეთ ახალი ჟეტონი

დუბლიკატი ოპერატორები

სინქრონიზაციის საბოლოო წერტილი შეიძლება დაუშვას სახელების დუბლიკატი. განახორციელეთ დედუპლიკაცია:

async function addUniqueOperators(newOperators, organizationId) {
  const existing = await listOperators(organizationId);
  const existingNames = new Set(
    existing.map(op => op.name.toLowerCase())
  );

  const unique = newOperators.filter(op =>
    !existingNames.has(op.name.toLowerCase())
  );

  if (unique.length === 0) {
    return [];
  }

  return await addOperators(unique);
}

შემდეგი ნაბიჯები