> ## 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 Usage

> Code examples for tracking usage events in Python, Node.js, Go, and more.

## The Track Endpoint

```
POST /api/v1/sdk/track
X-API-Key: org_live_<your_key>
```

### Request Body

```json theme={null}
{
  "meter_token": "string (required)",
  "customer_external_id": "string (required)",
  "quantity": 1,
  "timestamp": "2025-01-15T10:30:00Z",
  "idempotency_key": "string",
  "metadata": {
    "key": "value"
  }
}
```

| Field                  | Required | Description                                                 |
| ---------------------- | -------- | ----------------------------------------------------------- |
| `meter_token`          | ✅        | Unique token from your meter                                |
| `customer_external_id` | ✅        | Your customer's ID                                          |
| `quantity`             | ✅        | Usage amount (> 0)                                          |
| `timestamp`            |          | Defaults to now if omitted                                  |
| `idempotency_key`      |          | Prevents duplicate events on retry                          |
| `metadata`             |          | Extra data; required `user_id` key for UNIQUE\_COUNT meters |

***

## Language Examples

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    import requests
    import uuid

    FLUXRATE_API_KEY = "org_live_your_key"
    FLUXRATE_BASE_URL = "https://api.fluxrate.co/api/v1"

    def track_usage(
        meter_token: str,
        customer_external_id: str,
        quantity: float,
        idempotency_key: str = None,
        metadata: dict = None
    ) -> dict:
        """Track a usage event with Fluxrate."""
        payload = {
            "meter_token": meter_token,
            "customer_external_id": customer_external_id,
            "quantity": quantity,
        }
        if idempotency_key:
            payload["idempotency_key"] = idempotency_key
        if metadata:
            payload["metadata"] = metadata

        response = requests.post(
            f"{FLUXRATE_BASE_URL}/sdk/track",
            headers={
                "Content-Type": "application/json",
                "X-API-Key": FLUXRATE_API_KEY,
            },
            json=payload,
            timeout=5,
        )
        response.raise_for_status()
        return response.json()


    # Example usage
    try:
        result = track_usage(
            meter_token="550e8400-e29b-41d4-a716-446655440000",
            customer_external_id="acme-corp-001",
            quantity=100,
            idempotency_key=f"order_{order_id}_api_calls",
        )
        print(f"Tracked event: {result['id']}")
    except requests.exceptions.RequestException as e:
        # Log and handle gracefully — don't fail the main request
        logger.error(f"Failed to track usage: {e}")
    ```
  </Tab>

  <Tab title="Node.js">
    ```javascript theme={null}
    const FLUXRATE_API_KEY = process.env.FLUXRATE_API_KEY;
    const FLUXRATE_BASE_URL = 'https://api.fluxrate.co/api/v1';

    async function trackUsage({
      meterToken,
      customerExternalId,
      quantity,
      idempotencyKey,
      metadata,
    }) {
      const response = await fetch(`${FLUXRATE_BASE_URL}/sdk/track`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'X-API-Key': FLUXRATE_API_KEY,
        },
        body: JSON.stringify({
          meter_token: meterToken,
          customer_external_id: customerExternalId,
          quantity,
          ...(idempotencyKey && { idempotency_key: idempotencyKey }),
          ...(metadata && { metadata }),
        }),
        signal: AbortSignal.timeout(5000),
      });

      if (!response.ok) {
        const error = await response.json();
        throw new Error(`Fluxrate track failed: ${error.detail || response.status}`);
      }

      return response.json();
    }

    // Example usage (fire-and-forget)
    trackUsage({
      meterToken: '550e8400-e29b-41d4-a716-446655440000',
      customerExternalId: 'acme-corp-001',
      quantity: 1,
      idempotencyKey: `req_${requestId}`,
    }).catch(err => console.error('Failed to track usage:', err));
    ```
  </Tab>

  <Tab title="Go">
    ```go theme={null}
    package fluxrate

    import (
        "bytes"
        "encoding/json"
        "fmt"
        "net/http"
        "time"
    )

    type TrackRequest struct {
        MeterToken         string                 `json:"meter_token"`
        CustomerExternalID string                 `json:"customer_external_id"`
        Quantity           float64                `json:"quantity"`
        IdempotencyKey     string                 `json:"idempotency_key,omitempty"`
        Timestamp          *time.Time             `json:"timestamp,omitempty"`
        Metadata           map[string]interface{} `json:"metadata,omitempty"`
    }

    func TrackUsage(apiKey string, req TrackRequest) error {
        body, err := json.Marshal(req)
        if err != nil {
            return fmt.Errorf("marshal: %w", err)
        }

        httpReq, err := http.NewRequest(
            "POST",
            "https://api.fluxrate.co/api/v1/sdk/track",
            bytes.NewReader(body),
        )
        if err != nil {
            return err
        }

        httpReq.Header.Set("Content-Type", "application/json")
        httpReq.Header.Set("X-API-Key", apiKey)

        client := &http.Client{Timeout: 5 * time.Second}
        resp, err := client.Do(httpReq)
        if err != nil {
            return fmt.Errorf("request: %w", err)
        }
        defer resp.Body.Close()

        if resp.StatusCode != http.StatusCreated {
            return fmt.Errorf("unexpected status: %d", resp.StatusCode)
        }

        return nil
    }
    ```
  </Tab>
</Tabs>

***

## Tracking UNIQUE\_COUNT Events

For `UNIQUE_COUNT` meters, include the value to count in `metadata.user_id`:

```json theme={null}
{
  "meter_token": "...",
  "customer_external_id": "acme-corp-001",
  "quantity": 1,
  "metadata": {
    "user_id": "end_user_456"
  }
}
```

***

## Best Practices

<AccordionGroup>
  <Accordion title="Use idempotency keys">
    Always pass a unique `idempotency_key` so it's safe to retry failed requests without double-counting.

    ```python theme={null}
    idempotency_key = f"job_{job_id}_step_3"
    ```
  </Accordion>

  <Accordion title="Track asynchronously">
    Don't block your main request path waiting for Fluxrate's response. Track usage in a background task or fire-and-forget.

    ```python theme={null}
    asyncio.create_task(track_usage(...))
    ```
  </Accordion>

  <Accordion title="Handle failures gracefully">
    Log tracking failures but don't let them break your main workflow. Implement retry logic with exponential backoff for transient errors.
  </Accordion>

  <Accordion title="Batch high-volume events">
    If you have millions of events per day, pre-aggregate at your backend and send totals every minute rather than sending individual events.

    ```python theme={null}
    # Instead of: track(quantity=1) for each request
    # Do: track(quantity=counter.get_and_reset()) every 60 seconds
    ```
  </Accordion>
</AccordionGroup>
