← Blog

Claude API Request Logging and Auditing Guide

2026-10-19 · 5 min read · SubToAPI Team

If you're integrating the Claude API into a production system, you eventually hit the same wall: you need to know who called the model, when, with what input, and what it cost. That's request logging and auditing — capturing every API call in a durable, queryable record so you can debug incidents, prove compliance, and track spend by user or feature.

The short answer: Claude's own API doesn't give you a dashboard of historical requests tied to individual end users. Anthropic bills at the API-key level and gives you basic usage stats, but if you need per-request logs — prompts, responses, token counts, latency, status codes — you have to build that layer yourself, or use a gateway that already does it. Below is how to approach both.

Why logging matters for Claude API usage

Three recurring reasons teams ask about this:

None of these are solved by Anthropic's console alone. The console shows aggregate usage, not a per-request log you can filter by customer ID or feature flag.

What to log for every request

A useful audit log captures more than just "a call happened." At minimum, record:

Storing full prompt/response text raises its own compliance questions — if you're logging PII, you need retention policies and encryption at rest, not just a database table.

Building logging yourself with the Anthropic SDK

The straightforward approach is to wrap every call to Claude in a logging function. In Node.js:

import Anthropic from "@anthropic-ai/sdk";
import { randomUUID } from "crypto";

const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });

async function loggedMessageCall({ userId, messages, system }) {
  const requestId = randomUUID();
  const startedAt = Date.now();

  try {
    const response = await anthropic.messages.create({
      model: "claude-sonnet-4-5",
      max_tokens: 1024,
      system,
      messages,
    });

    await saveAuditLog({
      requestId,
      userId,
      model: response.model,
      inputTokens: response.usage.input_tokens,
      outputTokens: response.usage.output_tokens,
      latencyMs: Date.now() - startedAt,
      status: "success",
      promptSnapshot: messages,
      responseSnapshot: response.content,
    });

    return response;
  } catch (err) {
    await saveAuditLog({
      requestId,
      userId,
      latencyMs: Date.now() - startedAt,
      status: "error",
      errorMessage: err.message,
      promptSnapshot: messages,
    });
    throw err;
  }
}

This works, but it's code you now own: the saveAuditLog function, the storage schema, retention rules, and dashboards to query it. If you have a handful of internal services calling Claude, this is manageable. If you have many applications or teams each calling Claude independently, the logging logic gets duplicated and drifts out of sync.

Using a gateway to centralize logging

An alternative is to put a gateway in front of Claude so every request — regardless of which internal app sent it — passes through one place where logging, auditing, and key management already happen.

This is one of the reasons teams adopt SubToAPI: it turns your existing Claude access into a standard HTTPS API with per-application keys (sub_live_...), and every request made through it is tied to usage metadata you can see in one dashboard — which key made the call, token counts, and timing — without writing a separate logging pipeline for each service.

A typical call looks like a normal Messages API request, just pointed at SubToAPI:

curl https://api.subtoapi.app/v1/messages \
  -H "Authorization: Bearer $SUBTOAPI_KEY" \
  -H "content-type: application/json" \
  -d '{
    "model": "claude-sonnet-4-5",
    "max_tokens": 1024,
    "messages": [{"role": "user", "content": "Summarize this ticket."}]
  }'

Because each application or team gets its own sub_live_ key, you get request attribution for free: you know which key made which call without threading a userId field through your own logging code. For teams managing multiple internal apps or client integrations against one Claude account, that's a meaningful reduction in the plumbing you have to maintain. See the quickstart and Messages API docs for the full request format, and pricing for plan details — Solo, Team, and Scale tiers all include key-level usage visibility.

Auditing for compliance, not just debugging

If your use case requires formal audit trails (SOC 2, HIPAA-adjacent workflows, internal security review), logging alone isn't enough — you need:

These are organizational decisions as much as technical ones. Whatever logging approach you choose — custom code or a gateway — make sure it supports exporting data to whatever compliance tooling your organization already uses.

Questions

Does the Claude API provide built-in request logging? Anthropic's console shows aggregate usage and billing data per API key, but it does not provide a per-request log with prompt/response content tied to individual end users. You need to build that layer yourself or use a tool that adds it.

What's the minimum data I should log for Claude API calls? Timestamp, caller identity, model, input/output token counts, latency, and status code. Add full prompt/response content only if you have a retention and privacy policy for it.

Can I attribute Claude API usage to specific users or apps without custom logging code? Yes — issuing separate API keys per application or team, as SubToAPI does with its sub_live_ keys, gives you request attribution and usage metadata in a dashboard without building a custom logging pipeline.

Turn your Claude access into an HTTPS API

SubToAPI gives you application API keys, streaming, tool use and usage insights on top of your existing Claude access — set up in minutes.

Start free  Read the quickstart →