> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fluxrate.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Tracking Events

> Send usage events from your backend to Fluxrate using the SDK endpoint or REST API.

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):

```bash theme={null}
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**:

```bash theme={null}
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:

```json theme={null}
{
  "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.

<Tip>
  Good idempotency keys combine a unique transaction ID with a descriptive suffix: `order_{id}`, `job_{id}_tokens`, `request_{uuid}`.
</Tip>

## Tracking in Different Languages

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    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()
    ```
  </Tab>

  <Tab title="Node.js">
    ```javascript theme={null}
    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();
    }
    ```
  </Tab>

  <Tab title="Go">
    ```go theme={null}
    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
    }
    ```
  </Tab>
</Tabs>

## Best Practices

1. **Fire-and-forget** — Don't block your main request path waiting for the tracking response. Send events asynchronously.
2. **Retry with backoff** — Retry failed tracking requests with exponential backoff. Use idempotency keys to stay safe.
3. **Batch when possible** — For extremely high-volume scenarios, pre-aggregate at your backend and send totals periodically.
4. **Log failures** — Log any events that fail to track for manual reconciliation.
