Usage Tracking
Query aggregated usage statistics across services for customers and IP addresses. Usage tracking helps monitor consumption against subscription tier limits.
Get Aggregated User Usage
Retrieve aggregated usage statistics across all services for the authenticated user’s customer account.
Endpoint: https://apis.threatwinds.com/api/billing/v1/limits/usage
Method: GET
Parameters
Headers
| Header | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Optional* | Bearer token for session authentication |
| api-key | string | Optional* | API key for key-based authentication |
| api-secret | string | Optional* | API secret for key-based authentication |
Note: You must use either Authorization header OR API key/secret combination.
Required Roles
Required role: owner, admin, or user
All authenticated customer members can query their usage statistics.
Request
To retrieve user usage, use a GET request:
curl -X 'GET' \
'https://apis.threatwinds.com/api/billing/v1/limits/usage' \
-H 'accept: application/json' \
-H 'Authorization: Bearer <token>'
Or using API key and secret:
curl -X 'GET' \
'https://apis.threatwinds.com/api/billing/v1/limits/usage' \
-H 'accept: application/json' \
-H 'api-key: your-api-key' \
-H 'api-secret: your-api-secret'
Response
A successful response will return aggregated usage statistics organized by service.
Success Response (200 OK)
{
"identifier": "550e8400-e29b-41d4-a716-446655440000",
"identifierType": "user",
"totalFeatures": 5,
"fetchedAt": 1704067200,
"services": {
"search-api": {
"serviceName": "search-api",
"features": [
{
"identifier": "550e8400-e29b-41d4-a716-446655440000",
"identifierType": "user",
"featureKey": "max_searches_per_minute",
"tierName": "Professional",
"window": "minute",
"currentUsage": 45,
"limit": 100,
"remaining": 55,
"resetAt": 1704067260,
"isLocked": false
}
]
},
"ingest-api": {
"serviceName": "ingest-api",
"features": [
{
"identifier": "550e8400-e29b-41d4-a716-446655440000",
"identifierType": "user",
"featureKey": "max_ingests_per_hour",
"tierName": "Professional",
"window": "hour",
"currentUsage": 200,
"limit": 500,
"remaining": 300,
"resetAt": 1704070800,
"isLocked": false
}
]
}
}
}
Response Schema
| Field | Type | Description |
|---|---|---|
| identifier | string (UUID) | User unique identifier |
| identifierType | string | Type of identifier: “user” or “ip” |
| totalFeatures | integer | Total number of features tracked |
| fetchedAt | integer | Unix timestamp when usage was fetched |
| services | object | Usage statistics by service |
| services.{service} | object | Service-specific usage data |
| services.{service}.serviceName | string | Service identifier |
| services.{service}.features | array | Array of feature usage details |
| features[].identifier | string | User ID or IP address for this usage entry |
| features[].identifierType | string | Type of identifier: “user” or “ip” |
| features[].featureKey | string | Feature/limit key name |
| features[].tierName | string | Subscription tier name |
| features[].window | string | Time window: “minute”, “hour”, “day”, “month” |
| features[].currentUsage | integer | Current usage count |
| features[].limit | integer | Maximum allowed (-1 for unlimited) |
| features[].remaining | integer | Remaining quota (-1 for unlimited) |
| features[].resetAt | integer | Unix timestamp when usage resets |
| features[].isLocked | boolean | Whether feature is locked due to limit exceeded |
Error Codes
| Status Code | Description | Possible Cause |
|---|---|---|
| 200 | OK | Request successful |
| 400 | Bad Request | Invalid request |
| 401 | Unauthorized | Missing or invalid authentication |
| 403 | Forbidden | Insufficient permissions |
| 500 | Internal Server Error | Server error |
Get Aggregated IP Usage
Retrieve aggregated usage statistics across all services for the requester’s IP address. This is a public endpoint that doesn’t require authentication.
Endpoint: https://apis.threatwinds.com/api/billing/v1/limits/usage/ip
Method: GET
Authentication
This is a public endpoint and does not require authentication. The endpoint automatically detects the requester’s IP address.
Request
To retrieve IP usage, use a GET request:
curl -X 'GET' \
'https://apis.threatwinds.com/api/billing/v1/limits/usage/ip' \
-H 'accept: application/json'
Response
Success Response (200 OK)
{
"identifier": "192.168.1.100",
"identifierType": "ip",
"totalFeatures": 2,
"fetchedAt": 1704067200,
"services": {
"search-api": {
"serviceName": "search-api",
"features": [
{
"identifier": "192.168.1.100",
"identifierType": "ip",
"featureKey": "max_searches_per_minute",
"tierName": "Free",
"window": "minute",
"currentUsage": 8,
"limit": 10,
"remaining": 2,
"resetAt": 1704067260,
"isLocked": false
}
]
}
}
}
Response Schema
| Field | Type | Description |
|---|---|---|
| identifier | string | IP address being queried |
| identifierType | string | Always “ip” for this endpoint |
| totalFeatures | integer | Total number of features tracked |
| fetchedAt | integer | Unix timestamp when usage was fetched |
| services | object | Usage statistics by service |
| services.{service} | object | Service-specific usage data |
| services.{service}.serviceName | string | Service identifier |
| services.{service}.features | array | Array of feature usage details |
| features[].identifier | string | IP address for this usage entry |
| features[].identifierType | string | Always “ip” for this endpoint |
| features[].featureKey | string | Feature/limit key name |
| features[].tierName | string | Tier name (typically “Free” for IPs) |
| features[].window | string | Time window: “minute”, “hour”, “day”, “month” |
| features[].currentUsage | integer | Current usage count |
| features[].limit | integer | Maximum allowed |
| features[].remaining | integer | Remaining quota |
| features[].resetAt | integer | Unix timestamp when usage resets |
| features[].isLocked | boolean | Whether feature is locked due to limit exceeded |
Error Codes
| Status Code | Description | Possible Cause |
|---|---|---|
| 200 | OK | Request successful |
| 400 | Bad Request | Invalid IP address format |
| 500 | Internal Server Error | Server error |
Usage Monitoring Best Practices
For Application Developers
- Monitor Proactively: Check usage regularly before hitting limits
- Display to Users: Show usage statistics in dashboards
- Set Warnings: Alert users at 80% and 90% of limits
- Graceful Degradation: Handle 402 Payment Required errors gracefully
Example: Usage Dashboard
# 1. Get customer limits
curl -X 'GET' \
'https://apis.threatwinds.com/api/billing/v1/limits' \
-H 'Authorization: Bearer <token>'
# 2. Get current usage
curl -X 'GET' \
'https://apis.threatwinds.com/api/billing/v1/limits/usage' \
-H 'Authorization: Bearer <token>'
# 3. Calculate percentage and display:
# - Green: 0-70%
# - Yellow: 71-90%
# - Red: 91-100%
# - Show upgrade option when approaching limits
Example: IP Rate Limit Check
# Check if your IP is rate limited before making requests
curl -X 'GET' \
'https://apis.threatwinds.com/api/billing/v1/limits/usage/ip' \
-H 'accept: application/json'
# If status shows "rate_limited", implement backoff strategy
Integration with Limits
Usage tracking works in conjunction with the Limits API:
| Limits Endpoints | Purpose | Usage Endpoints | Purpose |
|---|---|---|---|
GET /limits | Get tier limits | GET /limits/usage | Get current usage |
GET /limits/{service} | Get service limits | Compare usage vs limits | Calculate percentage |
GET /limits/ip | Get IP rate limits | GET /limits/usage/ip | Get IP usage |
Example: Complete Limit Check
# 1. Get current usage
curl 'https://apis.threatwinds.com/api/billing/v1/limits/usage' \
-H 'Authorization: Bearer <token>'
# Response includes all usage details:
# {
# "services": {
# "search-api": {
# "features": [{
# "featureKey": "max_searches_per_minute",
# "currentUsage": 85,
# "limit": 100,
# "remaining": 15,
# "window": "minute"
# }]
# }
# }
# }
# 2. Calculate: 85 / 100 = 85% used
# 3. Display warning: "You've used 85% of your per-minute search quota"
# 4. Show resetAt timestamp: "Resets in 15 seconds"