Usage events are the raw measurements that Fluxrate aggregates into invoices. Send them from your backend whenever a billable action occurs.
Two Ways to Track
Option 1: SDK Endpoint (Recommended)
Use the simplified SDK endpoint with an API key (no user session required):
curl -X POST https://api.fluxrate.co/api/v1/sdk/track \
-H "Content-Type: application/json" \
-H "X-API-Key: org_live_<your_api_key>" \
-d '{
"meter_token": "550e8400-e29b-41d4-a716-446655440000",
"customer_external_id": "your-customer-id",
"quantity": 1,
"idempotency_key": "req_unique_key_123"
}'
Option 2: REST API
Use the full REST API with JWT authentication:
curl -X POST https://api.fluxrate.co/api/v1/usage \
-H "Content-Type: application/json" \
-H "Cookie: access_token=<token>" \
-d '{
"meter_id": "<meter_id>",
"customer_id": "<customer_id>",
"quantity": 100,
"timestamp": "2025-01-15T10:30:00Z"
}'
Request Fields
| Field | Required | Description |
|---|
meter_token | ✅ | Unique token identifying the meter |
customer_external_id | ✅ | Your own customer ID |
quantity | ✅ | Usage quantity (must be > 0) |
timestamp | | Event time (defaults to now if omitted) |
idempotency_key | | Prevents duplicate events on retry |
metadata | | Extra key-value data (required for UNIQUE_COUNT) |
Idempotency
Always include an idempotency_key to safely retry failed requests:
{
"meter_token": "...",
"customer_external_id": "cust_123",
"quantity": 1,
"idempotency_key": "order_789_step_3"
}
If the same key is sent again, the event is silently deduplicated — you won’t get a double charge.
Good idempotency keys combine a unique transaction ID with a descriptive suffix: order_{id}, job_{id}_tokens, request_{uuid}.
Tracking in Different Languages
import requests
def track_usage(meter_token, customer_id, quantity, idempotency_key=None):
response = requests.post(
"https://api.fluxrate.co/api/v1/sdk/track",
headers={
"Content-Type": "application/json",
"X-API-Key": "org_live_your_key"
},
json={
"meter_token": meter_token,
"customer_external_id": customer_id,
"quantity": quantity,
"idempotency_key": idempotency_key
}
)
response.raise_for_status()
return response.json()
async function trackUsage(meterToken, customerId, quantity, idempotencyKey) {
const response = await fetch('https://api.fluxrate.co/api/v1/sdk/track', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': 'org_live_your_key'
},
body: JSON.stringify({
meter_token: meterToken,
customer_external_id: customerId,
quantity: quantity,
idempotency_key: idempotencyKey
})
});
if (!response.ok) {
throw new Error(`Track failed: ${response.status}`);
}
return response.json();
}
func TrackUsage(meterToken, customerID string, quantity float64, idempotencyKey string) error {
payload := map[string]interface{}{
"meter_token": meterToken,
"customer_external_id": customerID,
"quantity": quantity,
"idempotency_key": idempotencyKey,
}
body, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", "https://api.fluxrate.co/api/v1/sdk/track", bytes.NewBuffer(body))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-API-Key", "org_live_your_key")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
return nil
}
Best Practices
- Fire-and-forget — Don’t block your main request path waiting for the tracking response. Send events asynchronously.
- Retry with backoff — Retry failed tracking requests with exponential backoff. Use idempotency keys to stay safe.
- Batch when possible — For extremely high-volume scenarios, pre-aggregate at your backend and send totals periodically.
- Log failures — Log any events that fail to track for manual reconciliation.