# Record application usage by anonymous user

Add your own request identifiers and minimal usage events without assuming a MandAPI analytics API.

## Decide what the application needs

This recipe writes a local event for one model request. It assigns an anonymous application user, a feature name and an application-generated request ID. These are your application's records; the example does not create MandAPI organization analytics or promise that arbitrary metadata appears in the dashboard.

Use this pattern when you need to understand which feature is active or investigate a failed request. For a real service, assign anonymous identifiers on the server using your existing account system. Do not accept another customer's identity directly from an untrusted browser.

## Save a minimal event

Install the OpenAI Python client and set `MANDAPI_API_KEY` and `MANDAPI_MODEL_ID`. Save the following as `tracked_request.py`. The example uses a synthetic user and message. Running it makes one real request and writes `usage-events.jsonl` in the current folder.

```python
# tracked_request.py
import json
import os
import time
import uuid
from datetime import datetime, timezone
from openai import OpenAI

request_id = uuid.uuid4().hex
started = time.monotonic()
record = {
    "request_id": request_id,
    "anonymous_user_id": "demo-user-a",
    "feature": "support-demo",
    "time": datetime.now(timezone.utc).isoformat(),
}

with OpenAI(
    api_key=os.environ["MANDAPI_API_KEY"],
    base_url="https://api.mandapi.com/v1",
    timeout=30.0,
    max_retries=0,
) as client:
    try:
        result = client.chat.completions.create(
            model=os.environ["MANDAPI_MODEL_ID"],
            messages=[{"role": "user", "content": "Say hello in Spanish."}],
        )
        record.update(status="ok", response_id=result.id, model=result.model)
        if result.usage:
            record.update(
                prompt_tokens=result.usage.prompt_tokens,
                completion_tokens=result.usage.completion_tokens,
            )
    except Exception as error:
        record.update(status="error", error_type=type(error).__name__)
        raise RuntimeError("MandAPI request failed: " + type(error).__name__) from None
    finally:
        record["duration_ms"] = round((time.monotonic() - started) * 1000)
        with open("usage-events.jsonl", "a", encoding="utf-8") as log:
            log.write(json.dumps(record, ensure_ascii=False) + "\n")
print("Saved local event:", request_id)
```

The event contains status and duration even when the request fails. Token counts are included only if returned. The generated request ID is different from the model response ID, and neither should be treated as a monetary charge.

## Use the record carefully

Open the JSONL file and verify that each run adds one event. Compare events using your application's request ID, anonymous user and feature. If you estimate cost, keep the rate date and billing assumptions beside the estimate. Reconcile actual credits with the [MandAPI dashboard](https://app.mandapi.com/console).

The example does not send customer identifiers to MandAPI. It also omits prompt bodies, responses, email addresses and API keys. Set access and retention appropriate to your service before collecting real customer activity.

## Check the result

A successful call should save an `ok` event with a response ID and any returned usage; a failure should save an `error` event without inventing tokens. In a multi-worker service, replace the demonstration file with a database or logging system that supports concurrent writes. Build reports from your own events instead of assuming an unverified platform analytics endpoint exists.

## References

- [https://mandapi.com/en/docs/quickstart](https://mandapi.com/en/docs/quickstart)
- [https://mandapi.com/es/docs/quickstart](https://mandapi.com/es/docs/quickstart)
- [https://github.com/openai/openai-python](https://github.com/openai/openai-python)
