Alle .md einmal aufgeräumt
Dieser Commit ist enthalten in:
521
API_REFERENCE.md
Normale Datei
521
API_REFERENCE.md
Normale Datei
@@ -0,0 +1,521 @@
|
||||
# V2-Docker API Reference
|
||||
|
||||
## License Server API
|
||||
|
||||
### Public Endpoints
|
||||
|
||||
#### POST /api/v1/activate
|
||||
Activate a license on a new system.
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"license_key": "XXXX-XXXX-XXXX-XXXX",
|
||||
"hardware_id": {
|
||||
"mac_address": "00:1B:44:11:3A:B7",
|
||||
"cpu_id": "BFEBFBFF000906EA",
|
||||
"system_uuid": "4C4C4544-0052-3410-8036-B8C04F303832"
|
||||
},
|
||||
"machine_name": "DESKTOP-ABC123",
|
||||
"app_version": "1.0.0"
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"activation_id": "act_123456",
|
||||
"features": ["feature1", "feature2"],
|
||||
"max_users": 10,
|
||||
"valid_until": "2026-01-01T00:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
#### POST /api/v1/validate
|
||||
Validate an active license.
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"license_key": "XXXX-XXXX-XXXX-XXXX",
|
||||
"activation_id": "act_123456",
|
||||
"hardware_id": {
|
||||
"mac_address": "00:1B:44:11:3A:B7",
|
||||
"cpu_id": "BFEBFBFF000906EA",
|
||||
"system_uuid": "4C4C4544-0052-3410-8036-B8C04F303832"
|
||||
},
|
||||
"current_users": 5,
|
||||
"app_version": "1.0.0"
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"valid": true,
|
||||
"features": ["feature1", "feature2"],
|
||||
"max_users": 10,
|
||||
"message": "License valid"
|
||||
}
|
||||
```
|
||||
|
||||
#### POST /api/v1/heartbeat
|
||||
Send usage heartbeat.
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"license_key": "XXXX-XXXX-XXXX-XXXX",
|
||||
"activation_id": "act_123456",
|
||||
"current_users": 5,
|
||||
"feature_usage": {
|
||||
"feature1": 150,
|
||||
"feature2": 75
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"next_heartbeat": "2025-01-01T12:30:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
#### POST /api/v1/deactivate
|
||||
Deactivate a license.
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"license_key": "XXXX-XXXX-XXXX-XXXX",
|
||||
"activation_id": "act_123456",
|
||||
"reason": "System upgrade"
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "License deactivated successfully"
|
||||
}
|
||||
```
|
||||
|
||||
### Admin API Endpoints
|
||||
|
||||
#### Authentication
|
||||
All admin endpoints require JWT authentication:
|
||||
```
|
||||
Authorization: Bearer <jwt_token>
|
||||
```
|
||||
|
||||
#### GET /api/v1/admin/licenses
|
||||
List all licenses.
|
||||
|
||||
**Query Parameters:**
|
||||
- `page` (default: 1)
|
||||
- `per_page` (default: 50)
|
||||
- `status` (active, inactive, expired)
|
||||
- `customer_id`
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"licenses": [
|
||||
{
|
||||
"id": 1,
|
||||
"license_key": "XXXX-XXXX-XXXX-XXXX",
|
||||
"customer_name": "ACME Corp",
|
||||
"type": "subscription",
|
||||
"status": "active",
|
||||
"valid_from": "2025-01-01",
|
||||
"valid_until": "2026-01-01",
|
||||
"max_activations": 5,
|
||||
"current_activations": 3
|
||||
}
|
||||
],
|
||||
"total": 100,
|
||||
"page": 1,
|
||||
"per_page": 50
|
||||
}
|
||||
```
|
||||
|
||||
#### POST /api/v1/admin/licenses
|
||||
Create a new license.
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"customer_id": 123,
|
||||
"type": "subscription",
|
||||
"valid_from": "2025-01-01",
|
||||
"valid_until": "2026-01-01",
|
||||
"max_activations": 5,
|
||||
"max_users": 10,
|
||||
"features": ["feature1", "feature2"]
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"id": 456,
|
||||
"license_key": "NEW1-NEW2-NEW3-NEW4",
|
||||
"message": "License created successfully"
|
||||
}
|
||||
```
|
||||
|
||||
#### GET /api/v1/admin/licenses/{id}
|
||||
Get license details.
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"id": 1,
|
||||
"license_key": "XXXX-XXXX-XXXX-XXXX",
|
||||
"customer": {
|
||||
"id": 123,
|
||||
"name": "ACME Corp",
|
||||
"email": "admin@acme.com"
|
||||
},
|
||||
"activations": [
|
||||
{
|
||||
"id": "act_123456",
|
||||
"machine_name": "DESKTOP-ABC123",
|
||||
"activated_at": "2025-01-01T10:00:00Z",
|
||||
"last_heartbeat": "2025-06-19T14:30:00Z",
|
||||
"status": "active"
|
||||
}
|
||||
],
|
||||
"usage_stats": {
|
||||
"total_users": 150,
|
||||
"peak_users": 10,
|
||||
"feature_usage": {
|
||||
"feature1": 5000,
|
||||
"feature2": 2500
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### PUT /api/v1/admin/licenses/{id}
|
||||
Update license.
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"valid_until": "2027-01-01",
|
||||
"max_activations": 10,
|
||||
"features": ["feature1", "feature2", "feature3"]
|
||||
}
|
||||
```
|
||||
|
||||
#### DELETE /api/v1/admin/licenses/{id}
|
||||
Revoke a license.
|
||||
|
||||
#### GET /api/v1/admin/activations
|
||||
List all activations.
|
||||
|
||||
**Query Parameters:**
|
||||
- `license_id`
|
||||
- `status` (active, inactive)
|
||||
- `from_date`
|
||||
- `to_date`
|
||||
|
||||
#### GET /api/v1/admin/statistics
|
||||
Get usage statistics.
|
||||
|
||||
**Query Parameters:**
|
||||
- `from_date`
|
||||
- `to_date`
|
||||
- `customer_id`
|
||||
- `license_id`
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"summary": {
|
||||
"total_licenses": 100,
|
||||
"active_licenses": 85,
|
||||
"total_activations": 250,
|
||||
"active_users": 1500
|
||||
},
|
||||
"usage_trends": [
|
||||
{
|
||||
"date": "2025-06-01",
|
||||
"active_users": 1200,
|
||||
"new_activations": 5
|
||||
}
|
||||
],
|
||||
"feature_usage": {
|
||||
"feature1": 50000,
|
||||
"feature2": 25000
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Lead Management API
|
||||
|
||||
### Institutions
|
||||
|
||||
#### GET /api/institutions
|
||||
List all institutions.
|
||||
|
||||
**Query Parameters:**
|
||||
- `search`: Search term
|
||||
- `tags`: Comma-separated tags
|
||||
- `page`: Page number
|
||||
- `per_page`: Items per page
|
||||
|
||||
#### POST /api/institutions
|
||||
Create new institution.
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"name": "Example University",
|
||||
"type": "university",
|
||||
"address": "123 Main St",
|
||||
"tags": ["education", "research"],
|
||||
"metadata": {
|
||||
"student_count": 5000
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### GET /api/institutions/{id}
|
||||
Get institution details.
|
||||
|
||||
#### PUT /api/institutions/{id}
|
||||
Update institution.
|
||||
|
||||
#### DELETE /api/institutions/{id}
|
||||
Delete institution.
|
||||
|
||||
### Contact Persons
|
||||
|
||||
#### GET /api/institutions/{id}/contacts
|
||||
List contacts for institution.
|
||||
|
||||
#### POST /api/institutions/{id}/contacts
|
||||
Add contact to institution.
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"name": "John Doe",
|
||||
"email": "john@example.com",
|
||||
"phone": "+1234567890",
|
||||
"position": "IT Manager",
|
||||
"is_primary": true
|
||||
}
|
||||
```
|
||||
|
||||
### Notes
|
||||
|
||||
#### GET /api/institutions/{id}/notes
|
||||
Get notes for institution.
|
||||
|
||||
#### POST /api/institutions/{id}/notes
|
||||
Add note to institution.
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"content": "Discussed pricing options",
|
||||
"type": "meeting",
|
||||
"tags": ["sales", "followup"]
|
||||
}
|
||||
```
|
||||
|
||||
## Analytics API
|
||||
|
||||
### GET /api/v1/analytics/usage
|
||||
Get detailed usage analytics.
|
||||
|
||||
**Query Parameters:**
|
||||
- `from_date`: Start date (ISO 8601)
|
||||
- `to_date`: End date (ISO 8601)
|
||||
- `license_id`: Filter by license
|
||||
- `granularity`: hour, day, week, month
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"period": {
|
||||
"from": "2025-06-01T00:00:00Z",
|
||||
"to": "2025-06-19T23:59:59Z"
|
||||
},
|
||||
"metrics": {
|
||||
"total_heartbeats": 50000,
|
||||
"unique_activations": 150,
|
||||
"average_users_per_activation": 8.5,
|
||||
"peak_concurrent_users": 1200
|
||||
},
|
||||
"time_series": [
|
||||
{
|
||||
"timestamp": "2025-06-01T00:00:00Z",
|
||||
"active_users": 800,
|
||||
"heartbeat_count": 2500
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### GET /api/v1/analytics/features
|
||||
Get feature usage statistics.
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"features": [
|
||||
{
|
||||
"name": "feature1",
|
||||
"total_usage": 150000,
|
||||
"unique_users": 500,
|
||||
"usage_trend": "increasing"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Common Response Codes
|
||||
|
||||
- `200 OK`: Successful request
|
||||
- `201 Created`: Resource created
|
||||
- `400 Bad Request`: Invalid request data
|
||||
- `401 Unauthorized`: Missing or invalid authentication
|
||||
- `403 Forbidden`: Insufficient permissions
|
||||
- `404 Not Found`: Resource not found
|
||||
- `409 Conflict`: Resource conflict (e.g., duplicate)
|
||||
- `429 Too Many Requests`: Rate limit exceeded
|
||||
- `500 Internal Server Error`: Server error
|
||||
|
||||
## Rate Limiting
|
||||
|
||||
- Public API: 100 requests per minute per IP
|
||||
- Admin API: 1000 requests per minute per token
|
||||
- Heartbeat endpoint: 1 request per minute per activation
|
||||
|
||||
## Error Response Format
|
||||
|
||||
```json
|
||||
{
|
||||
"error": {
|
||||
"code": "INVALID_LICENSE",
|
||||
"message": "The provided license key is invalid",
|
||||
"details": {
|
||||
"field": "license_key",
|
||||
"reason": "format_invalid"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Client Integration Examples
|
||||
|
||||
### Python
|
||||
```python
|
||||
import requests
|
||||
import json
|
||||
|
||||
class LicenseClient:
|
||||
def __init__(self, base_url):
|
||||
self.base_url = base_url
|
||||
|
||||
def activate(self, license_key, hardware_id):
|
||||
response = requests.post(
|
||||
f"{self.base_url}/api/v1/activate",
|
||||
json={
|
||||
"license_key": license_key,
|
||||
"hardware_id": hardware_id,
|
||||
"machine_name": socket.gethostname(),
|
||||
"app_version": "1.0.0"
|
||||
}
|
||||
)
|
||||
return response.json()
|
||||
|
||||
def validate(self, license_key, activation_id, hardware_id):
|
||||
response = requests.post(
|
||||
f"{self.base_url}/api/v1/validate",
|
||||
json={
|
||||
"license_key": license_key,
|
||||
"activation_id": activation_id,
|
||||
"hardware_id": hardware_id,
|
||||
"app_version": "1.0.0"
|
||||
}
|
||||
)
|
||||
return response.json()
|
||||
```
|
||||
|
||||
### C# Example
|
||||
```csharp
|
||||
public class LicenseClient
|
||||
{
|
||||
private readonly HttpClient _httpClient;
|
||||
private readonly string _baseUrl;
|
||||
|
||||
public LicenseClient(string baseUrl)
|
||||
{
|
||||
_baseUrl = baseUrl;
|
||||
_httpClient = new HttpClient();
|
||||
}
|
||||
|
||||
public async Task<ActivationResponse> ActivateAsync(
|
||||
string licenseKey,
|
||||
HardwareInfo hardwareId)
|
||||
{
|
||||
var request = new
|
||||
{
|
||||
license_key = licenseKey,
|
||||
hardware_id = hardwareId,
|
||||
machine_name = Environment.MachineName,
|
||||
app_version = "1.0.0"
|
||||
};
|
||||
|
||||
var response = await _httpClient.PostAsJsonAsync(
|
||||
$"{_baseUrl}/api/v1/activate",
|
||||
request
|
||||
);
|
||||
|
||||
return await response.Content.ReadFromJsonAsync<ActivationResponse>();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Webhooks
|
||||
|
||||
### Configuration
|
||||
Configure webhooks in the admin panel to receive notifications for:
|
||||
- License activation
|
||||
- License expiration
|
||||
- Suspicious activity
|
||||
- Usage threshold alerts
|
||||
|
||||
### Webhook Payload
|
||||
```json
|
||||
{
|
||||
"event": "license.activated",
|
||||
"timestamp": "2025-06-19T10:30:00Z",
|
||||
"data": {
|
||||
"license_id": 123,
|
||||
"activation_id": "act_456",
|
||||
"customer_id": 789
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
### Test Credentials
|
||||
- License Key: `TEST-TEST-TEST-TEST`
|
||||
- API Key: `test_api_key_123`
|
||||
- JWT Secret: `test_jwt_secret`
|
||||
|
||||
### Test Endpoints
|
||||
- Development: `http://localhost:8080`
|
||||
- Staging: `https://staging-api.example.com`
|
||||
- Production: `https://api.example.com`
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren