# How to See the Failover History of a Request in FreeLLMAPI: Complete Guide with API and SQL Methods

> Discover how to view FreeLLMAPI request failover history. Learn to access this data using the analytics endpoint, SQL queries, and response headers for comprehensive insights.

- Repository: [Tashfeen/freellmapi](https://github.com/tashfeenahmed/freellmapi)
- Tags: how-to-guide
- Published: 2026-08-28

---

**FreeLLMAPI records every hop a request makes through the failover ladder in durable storage, exposing this history via the `/analytics` endpoint, database queries, and optional response headers.**

FreeLLMAPI implements resilient routing through an ordered failover ladder—when your primary provider fails, the system automatically tries alternatives. Understanding how to inspect this failover history helps you debug latency spikes, diagnose provider outages, and optimize your model selection strategy. This guide covers three methods to retrieve the complete attempt trace for any request.

## What Gets Recorded in Failover History

Each request generates an **AttemptTrace** object for every provider/model tried during routing. As defined in [`server/src/lib/attempt-trace.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/server/src/lib/attempt-trace.ts), these traces capture:

- The **provider and model** attempted
- **Start and end timestamps** for precise latency measurement
- The **outcome** (success, timeout, quota-exhausted, rate-limited, etc.)
- A **redacted error summary** for privacy-compliant debugging

All attempts link to their parent request, forming a chronological "failover ladder" you can inspect retroactively.

## Method 1: Query the Analytics API (Recommended)

The standard way to view failover history is through the `/analytics/requests/:id` endpoint implemented in [`server/src/routes/analytics.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/server/src/routes/analytics.ts).

### Step 1: Capture the Request ID

Every response includes the header `x-request-id`. Capture this in your client:

```javascript
const requestId = response.headers.get('x-request-id');
console.log('Request ID:', requestId); // e.g., 'a1b2c3d4-5678-90ab-cdef-Example11'

```

### Step 2: Fetch Failover History

```javascript
const requestId = 'a1b2c3d4-5678-90ab-cdef-Example11';

const resp = await fetch(
  `https://api.freellmapi.com/analytics/requests/${requestId}`,
  {
    headers: {
      Authorization: `Bearer ${process.env.FREELLMAPI_TOKEN}`,
    },
  }
);

const data = await resp.json();
console.log('Failover ladder:', data.attempts);

```

The response contains an `attempts` array with the full sequence:

```json
{
  "id": "a1b2c3d4-5678-90ab-cdef-Example11",
  "created_at": "2024-01-15T09:23:17Z",
  "final_provider": "openrouter",
  "final_model": "anthropic/claude-3-opus",
  "attempts": [
    {
      "attempt_index": 0,
      "provider": "openai",
      "model": "gpt-4-turbo",
      "start_ts": "2024-01-15T09:23:17.123Z",
      "end_ts": "2024-01-15T09:23:19.456Z",
      "outcome": "timeout",
      "error_summary": "Request deadline exceeded (30s)"
    },
    {
      "attempt_index": 1,
      "provider": "openrouter",
      "model": "anthropic/claude-3-opus",
      "start_ts": "2024-01-15T09:23:19.789Z",
      "end_ts": "2024-01-15T09:23:22.101Z",
      "outcome": "success",
      "error_summary": null
    }
  ]
}

```

## Method 2: Direct Database Query

For operational investigations or custom dashboards, query the `request_attempts` table directly. This schema was created by migration [`server/src/db/migrations/20260726_000002_request_attempts.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/server/src/db/migrations/20260726_000002_request_attempts.ts).

### PostgreSQL Query

```sql
SELECT
  attempt_index,
  provider,
  model,
  start_ts,
  end_ts,
  outcome,
  error_summary
FROM request_attempts
WHERE request_id = 'a1b2c3d4-5678-90ab-cdef-Example11'
ORDER BY attempt_index;

```

**Key columns explained:**

| Column | Purpose |
|--------|---------|
| `attempt_index` | Position in failover sequence (0 = first attempt) |
| `outcome` | Result classification used for analytics aggregation |
| `error_summary` | Sanitized error message (PII-redacted) |

## Method 3: Real-Time Failover Trace Headers

For immediate visibility without subsequent API calls, enable the **optional trace header** via [`server/src/lib/fallback-loop.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/server/src/lib/fallback-loop.ts).

### Client-Opt-In Request

Add the `X-Failover-Trace: true` header:

```bash
curl -s -D - \
  -H "Authorization: Bearer $FREELLMAPI_TOKEN" \
  -H "X-Failover-Trace: true" \
  -H "Content-Type: application/json" \
  https://api.freellmapi.com/v1/chat/completions \
  -d '{
    "model": "gpt-4",
    "messages": [{"role": "user", "content": "Hello"}]
  }'

```

### Response Header Inspection

Look for `X-Fallback-Trace` in the response:

```http
HTTP/1.1 200 OK
x-request-id: a1b2c3d4-5678-90ab-cdef-Example11
x-fallback-trace: [{"idx":0,"provider":"openai","model":"gpt-4","outcome":"timeout","ms":23047},{"idx":1,"provider":"openrouter","model":"anthropic/claude-3-opus","outcome":"success","ms":2312}]

```

This compact JSON format is designed for low-overhead logging integration.

## Understanding Failover Budget and Cooldown Data

The failover history reveals operational details beyond simple success/failure:

- **Failover budget consumed**: Each failed attempt deducts from your configured budget; the history shows remaining budget at each hop
- **Cooldown applied**: When providers hit rate limits, the [`fallback-loop.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/fallback-loop.ts) logic inserts calculated delays—visible in timestamp gaps between attempts
- **Exhaustion state**: If all providers fail, the final entry shows `outcome: "exhausted"` with an aggregated error summary

These metrics help you tune [`server/src/lib/fallback-loop.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/server/src/lib/fallback-loop.ts) configuration parameters like `max_attempts` and `per_provider_timeout`.

## Source Code Reference Map

| File | Role in Failover History |
|------|--------------------------|
| [`server/src/lib/attempt-trace.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/server/src/lib/attempt-trace.ts) | Defines **AttemptTrace** structure for per-attempt recording |
| [`server/src/lib/request-log.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/server/src/lib/request-log.ts) | Persists request row and associated attempt array |
| [`server/src/routes/analytics.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/server/src/routes/analytics.ts) | Implements `/analytics/requests/:id` endpoint |
| [`server/src/lib/fallback-loop.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/server/src/lib/fallback-loop.ts) | Sets optional `X-Fallback-Trace` response header |
| [`server/src/db/migrations/20260726_000002_request_attempts.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/server/src/db/migrations/20260726_000002_request_attempts.ts) | Database schema for durable attempt storage |

## Summary

- **Capture `x-request-id`** from every response to enable later history retrieval
- **Use `/analytics/requests/:id`** for the complete, formatted failover ladder with full metadata
- **Query `request_attempts` table directly** for operational dashboards and bulk analysis
- **Enable `X-Failover-Trace: true`** for real-time visibility without additional API calls
- **Inspect `attempt_index`, timestamps, and outcomes** to diagnose provider reliability and routing efficiency

## Frequently Asked Questions

### How long is failover history retained in FreeLLMAPI?

According to the [`server/src/lib/request-log.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/server/src/lib/request-log.ts) implementation, attempt records follow the parent request's retention policy. Typically this is **90 days** for standard tiers and **365 days** for enterprise plans, though you should verify your specific contract. The database migration uses standard PostgreSQL partitioning to manage time-series data efficiently.

### Can I export failover history for multiple requests at once?

Yes. The analytics endpoint supports batch queries via `POST /analytics/requests/batch` with a JSON body containing an array of request IDs. Maximum batch size is enforced by [`server/src/routes/analytics.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/server/src/routes/analytics.ts) (typically 100 IDs). For larger exports, query the `request_attempts` table directly with date-range filters on `start_ts`.

### What does "outcome" value "quota-exhausted" indicate?

This outcome from [`attempt-trace.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/attempt-trace.ts) means the provider rejected the request due to account-level limits—distinct from rate-limiting which shows as `rate_limited`. Quota exhaustion typically requires provider dashboard intervention or tier upgrade, while rate limits resolve after cooldown periods configured in [`fallback-loop.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/fallback-loop.ts).

### Is the X-Fallback-Trace header available on all response statuses?

No. As implemented in [`server/src/lib/fallback-loop.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/server/src/lib/fallback-loop.ts), the header is only attached when: (1) the client sends `X-Failover-Trace: true`, AND (2) the request completes the failover loop (success or exhaustion). Early client errors (400-class) that fail validation before routing will not include trace data since no provider attempts occurred.