返回 Skill 列表
extension
分类: 开发与工程无需 API Key

splynx-api

Splynx REST API客户端,用于对ISP管理数据进行验证操作。在Splynx中创建、更新或删除客户、服务、资费、发票、文档或票据时使用。在写入前验证数据。参考:src/apis/splynx_client.py

person作者: jakexiaohubgithub

Splynx REST API

REST API client for Splynx ISP management platform.

Authentication

import base64

# HTTP Basic Auth
credentials = base64.b64encode(f"{api_key}:{api_secret}".encode()).decode()
headers = {
    "Authorization": f"Basic {credentials}",
    "Content-Type": "application/json",
    "Accept": "application/json"
}

Environment variables:

  • SPLYNX_URL - Base URL (e.g., http://localhost or https://splynx.example.com)
  • SPLYNX_API_KEY - API key
  • SPLYNX_PASSWORD - API secret/password

Base endpoint: {SPLYNX_URL}/api/2.0/

Using the Client

from src.apis.splynx_client import SplynxAPIClient, SplynxConfig
from src.config.settings import config

splynx_config = SplynxConfig(
    base_url=config.splynx_url,
    api_key=config.splynx_api_key,
    api_secret=config.splynx_password
)
client = SplynxAPIClient(splynx_config)

# Test connection
result = client.test_connection()
if result['success']:
    print("Connected!")

Request Methods

# GET - Retrieve data
result = client.get('admin/tariffs/internet', params={'limit': 100})

# POST - Create new record
result = client.post('admin/tariffs/internet', data={'title': 'Basic Plan', 'price': 49.99})

# PUT - Update existing record
result = client.put('admin/customers/customer/123', data={'name': 'Updated Name'})

# DELETE - Remove record
result = client.delete('admin/tariffs/internet/456')

# OPTIONS - Get schema/metadata
result = client.options('admin/tariffs/internet')

# POST Multipart - File upload
result = client.post_multipart('admin/customers/customer-documents/123--upload',
    files={'file': ('doc.pdf', content, 'application/pdf')})

Response Format

All methods return:

{
    'success': True,           # or False
    'status_code': 200,        # HTTP status code
    'data': {...},             # On success
    'error': {...}             # On failure
}

Working Endpoints

Tariffs (Full CRUD)

# Internet tariffs
client.get('admin/tariffs/internet')
client.post('admin/tariffs/internet', {'title': 'Plan', 'price': 50})
client.put('admin/tariffs/internet/1', {'price': 55})
client.delete('admin/tariffs/internet/1')

# Voice tariffs
client.get('admin/tariffs/voice')
client.post('admin/tariffs/voice', {...})

# Bundle tariffs
client.get('admin/tariffs/bundle')
client.post('admin/tariffs/bundle', {...})

# One-time tariffs
client.get('admin/tariffs/one-time')
client.post('admin/tariffs/one-time', {...})

# Recurring tariffs
client.get('admin/tariffs/recurring')

Networking

# Routers
client.get('admin/networking/routers')
client.get('admin/networking/routers/1')
client.put('admin/networking/routers/1', {'title': 'Main Router'})

Documents

# Create document record
result = client.post('admin/customers/customer-documents', {
    'customer_id': 123,
    'type': 'uploaded',
    'title': 'Contract',
    'description': 'Service agreement'
})
doc_id = result['data']['id']

# Upload file content
client.post_multipart(f'admin/customers/customer-documents/{doc_id}--upload',
    files={'file': ('contract.pdf', pdf_bytes, 'application/pdf')})

Administration

# API check
client.get('admin/api/check')

# Administrators
client.get('admin/administration/administrators')
client.post('admin/administration/administrators', {...})

# Custom fields
client.get('admin/config/additional-fields/customers')
client.post('admin/config/additional-fields/customers', {...})

Restricted Endpoints (May Return 403)

These require additional API permissions:

# Customers - often restricted
client.get('admin/customers/customer')
client.post('admin/customers/customer', {...})

# Finance - often restricted
client.get('admin/finance/invoices')
client.get('admin/finance/payments')
client.get('admin/finance/transactions')

# Tickets - often restricted
client.get('admin/support/tickets')

Workaround: Use direct MySQL for restricted operations (faster anyway).

Pagination

# First page
result = client.get('admin/tariffs/internet', params={'limit': 100, 'offset': 0})

# Next page
result = client.get('admin/tariffs/internet', params={'limit': 100, 'offset': 100})

# Fetch all
all_items = []
offset = 0
while True:
    result = client.get('admin/tariffs/internet', params={'limit': 100, 'offset': offset})
    if not result['success'] or not result['data']:
        break
    all_items.extend(result['data'])
    if len(result['data']) < 100:
        break
    offset += 100

File Upload Pattern

from src.apis.splynx_client import SplynxAPIClient

def upload_document(client, customer_id, filename, content, mime_type):
    # Step 1: Create document record
    doc_result = client.post('admin/customers/customer-documents', {
        'customer_id': customer_id,
        'type': 'uploaded',
        'title': filename,
        'visible_by_customer': '0'
    })

    if not doc_result['success']:
        return None

    doc_id = doc_result['data']['id']

    # Step 2: Upload file content
    upload_result = client.post_multipart(
        f'admin/customers/customer-documents/{doc_id}--upload',
        files={'file': (filename, content, mime_type)}
    )

    if not upload_result['success']:
        # Rollback on failure
        client.delete(f'admin/customers/customer-documents/{doc_id}')
        return None

    return doc_id

Error Handling

result = client.post('admin/tariffs/internet', tariff_data)

if result['success']:
    tariff_id = result['data']['id']
    print(f"Created tariff {tariff_id}")
else:
    error = result.get('error', {})
    status = result.get('status_code')

    if status == 403:
        print("Permission denied - check API permissions")
    elif status == 404:
        print("Endpoint not found")
    elif status == 422:
        print(f"Validation error: {error}")
    else:
        print(f"Error {status}: {error}")

Customer Operations (via PUT)

Customers are typically created via MySQL, but updated via API:

# Update customer (set portal password)
result = client.put(f'admin/customers/customer/{customer_id}', {
    'id': customer_id,
    'name': 'John Doe',
    'login': 'johndoe',
    'password': 'new_password',
    'password_confirm': 'new_password'
})

Schema Discovery

# Get field definitions for an endpoint
schema = client.options('admin/tariffs/internet')
if schema['success']:
    fields = schema['data']
    for field_name, field_info in fields.items():
        print(f"{field_name}: {field_info.get('type')}")

When to Use API vs MySQL

| Use API | Use MySQL | |---------|-----------| | Creating documents | Bulk customer imports | | Setting passwords | Reading large datasets | | Validated writes | Invoice/payment inserts | | Schema discovery | Service assignments | | Router updates | Custom field values |

Reference

  • Client implementation: src/apis/splynx_client.py
  • Config: src/config/settings.py
  • Test: python -c "from src.apis.splynx_client import SplynxAPIClient, SplynxConfig; from src.config.settings import config; c = SplynxAPIClient(SplynxConfig(config.splynx_url, config.splynx_api_key, config.splynx_password)); print(c.test_connection())"