---
title: "Ingest External Usage"
method: POST
path: "/v1/usage/external-events"
tags: ["usage"]
---

# Ingest External Usage

`POST /v1/usage/external-events`

Ingest a batch of externally-observed usage events (standalone).

Authenticated with either an API key or the master key. Usage binds to the
authenticated principal: an API key attributes to its own user (and stamps its
id on the rows); the master key may name any user via ``user_id``. Records
subscription-backed usage (e.g. Claude Code) as usage-log rows tagged with their
``source``, priced at the effective API rate for each event's timestamp.
Imported usage is real cost, but never counts toward budgets or mutates
``users.spend`` (it is retrospective, so it cannot be reserved). Idempotent by
``(source, source_event_id)``. The payload is content-free; any
prompt/completion/tool field is rejected (422), not stored.

## Request body

- ExternalEventsRequest — A batch of imported usage events sharing a source and default user. ``extra="forbid"`` here mirrors the per-event schema: a stray content field at the batch level (e.g. a top-level ``prompt``) is a 422, not silently ignored.
  - `events` ExternalUsageEvent[], required
    - `cache_read_tokens` integer
    - `cache_tokens_in_prompt` boolean
    - `cache_write_1h_tokens` integer
    - `cache_write_tokens` integer
    - `duration_ms` integer, nullable
    - `input_tokens` integer
    - `model` string, required
    - `output_tokens` integer
    - `provider` string, required
    - `session_label` string, nullable
    - `source_event_id` string, required
    - `status` string
    - `timestamp` string, date-time, required
    - `user_id` string, nullable
  - `source` string, required
  - `user_id` string, nullable

## Response `200`

Successful Response

- ExternalIngestResult — Per-batch outcome. Re-submitting is safe: prior events count as duplicates.
  - `accepted` integer
  - `duplicate` integer
  - `errors` ExternalIngestError[]
    - `detail` string, required
    - `index` integer, required
    - `source_event_id` string, nullable, required
  - `rejected` integer

## Other responses

- `422` — Validation Error

---

[API](https://skmtc.net/mozilla-ai/apis/otari.md) · [All operations](https://skmtc.net/mozilla-ai/apis/otari/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/mozilla-ai/otari/revisions/3f47ecc61aff/schema)
