Help Center अपरेटरहरू

अपरेटरहरू

तपाईंको 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"

प्यारामिटरहरू

प्यारामिटरप्रकारस्थानआवश्यकविवरण
OrganizationIdपूर्णांकप्रश्नहोसंगठन ID

हेडरहरू

हेडरमूल्यआवश्यक
’प्राधिकरण’वाहक {टोकन}हो
’स्वीकार’पाठ/सादाहो

प्रतिक्रिया

[
  {
    "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
organization.nameस्ट्रिङसंस्थाको नाम

अपरेटर स्थिति

स्थितिमूल्यविवरण
सक्रियअपरेटर हाल काम गरिरहेको छ र च्याटहरू प्राप्त गर्न सक्छ
निष्क्रियअपरेटर अस्थायी रूपमा असक्षम छ
मेटाइयोप्रणालीबाट अपरेटर हटाइयो

अपरेटरहरू थप्नुहोस्

सिङ्क्रोनाइज एन्डपोइन्ट प्रयोग गरेर संगठनहरूमा नयाँ अपरेटरहरू थप्नुहोस्।

अन्तिम बिन्दु

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"
  }
]

क्षेत्रहरू अनुरोध गर्नुहोस्

क्षेत्रप्रकारआवश्यकविवरण
OrganizationIdपूर्णांकहोलक्षित संगठन 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 फर्काउँछ।

स्थिति मानहरू

स्थितिमूल्यविवरण
सक्रियअपरेटरले च्याटहरू ह्यान्डल गर्न सक्छ
निष्क्रियअपरेटर अस्थायी रूपमा असक्षम
मेटाइयोप्रणालीबाट अपरेटर हटाइयो

उदाहरण: निष्क्रिय अपरेटर

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

# Usage
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);
  }
}

समस्या निवारण

कुनै अपरेटर फिर्ता भएनन्

  • प्रमाणित संगठन आईडी सही छ
  • जाँच संगठन अवस्थित छ र अपरेटरहरू छन्
  • सुनिश्चित गर्नुहोस् कि कम्पनी टोकन संगठनमा पहुँच छ

अपरेटरहरू थप्न सकिएन

  • प्रमाणित संगठन आईडी अवस्थित छ
  • अपरेटर नाम ढाँचा जाँच गर्नुहोस्
  • सुनिश्चित गर्नुहोस् कि कम्पनी टोकन मान्य छ
  • JSON ढाँचा सही छ भनी प्रमाणित गर्नुहोस्

४०१ अनाधिकृत

  • प्रमाणित कम्पनी टोकन मान्य छ
  • चेक टोकन म्याद सकिएको छैन
  • आवश्यक भएमा नयाँ टोकन अनुरोध गर्नुहोस्

डुप्लिकेट अपरेटरहरू

सिङ्क्रोनाइज अन्त्य बिन्दुले डुप्लिकेट नामहरूलाई अनुमति दिन सक्छ। डुप्लिकेशन लागू गर्नुहोस्:

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);
}

अर्को चरणहरू