> ## Documentation Index
> Fetch the complete documentation index at: https://docs.velatir.com/llms.txt
> Use this file to discover all available pages before exploring further.

# AI usage data specification

> For software providers integrating their AI features with Velatir.

Velatir gives organisations a single view of how AI is used across their business: oversight, compliance, and insight. To include your product in that view, Velatir connects to your system and retrieves a defined set of data describing how their people use its AI features.

This specification defines the data Velatir consumes and the shape it expects. The transport is your choice; the data model is what is normative.

<Note>
  Access is strictly read-only. Velatir retrieves data on a schedule and never sits in the path of a live request, so an integration cannot affect your users' experience.
</Note>

## Resources

Velatir consumes four independent resource types. Implement those your system supports; apart from identifiers and timestamps, all fields are optional.

### 1. Conversations

One record per AI interaction: a conversation, or a single request and response exchange for stateless systems. This is the content Velatir's compliance agents review.

<ResponseField name="id" type="string">
  Stable, unique identifier for the interaction.
</ResponseField>

<ResponseField name="conversationId" type="string">
  Thread identifier, where the interaction is part of a multi-turn conversation.
</ResponseField>

<ResponseField name="startedAt" type="timestamp">
  When the interaction began. RFC 3339, UTC.
</ResponseField>

<ResponseField name="updatedAt" type="timestamp">
  When the record was last modified.
</ResponseField>

<ResponseField name="deletedAt" type="timestamp">
  Present when the interaction has been deleted.
</ResponseField>

<ResponseField name="user" type="object">
  The person who ran the interaction.

  <Expandable title="user">
    <ResponseField name="id" type="string" />

    <ResponseField name="email" type="string" />

    <ResponseField name="department" type="string" />

    <ResponseField name="groups" type="string[]" />
  </Expandable>
</ResponseField>

<ResponseField name="assistant" type="object">
  The custom assistant used, if any. See [Assistants](#3-assistants).

  <Expandable title="assistant">
    <ResponseField name="id" type="string" />

    <ResponseField name="name" type="string" />
  </Expandable>
</ResponseField>

<ResponseField name="model" type="string">
  Model used, for example `gpt-4o`.
</ResponseField>

<ResponseField name="modelProvider" type="string">
  Underlying LLM vendor, for example `openai`.
</ResponseField>

<ResponseField name="parameters" type="object">
  Sampling configuration: `temperature`, `topP`, `maxTokens`, and similar.
</ResponseField>

<ResponseField name="systemPrompt" type="string">
  The system prompt in effect. Provide `systemPromptHash` instead where the text cannot be shared.
</ResponseField>

<ResponseField name="messages" type="object[]">
  The turns of the interaction.

  <Expandable title="message">
    <ResponseField name="id" type="string" />

    <ResponseField name="role" type="enum">
      `user`, `assistant`, `system`, or `tool`.
    </ResponseField>

    <ResponseField name="content" type="string" />

    <ResponseField name="createdAt" type="timestamp" />
  </Expandable>
</ResponseField>

<ResponseField name="tools" type="object[]">
  Tools or skills invoked during the interaction.

  <Expandable title="tool">
    <ResponseField name="id" type="string" />

    <ResponseField name="name" type="string" />

    <ResponseField name="type" type="string" />
  </Expandable>
</ResponseField>

<ResponseField name="attachments" type="object[]">
  Files exchanged during the interaction.

  <Expandable title="attachment">
    <ResponseField name="id" type="string" />

    <ResponseField name="kind" type="enum">
      `uploaded` or `generated`.
    </ResponseField>

    <ResponseField name="filename" type="string" />

    <ResponseField name="mimeType" type="string" />

    <ResponseField name="hash" type="string" />
  </Expandable>
</ResponseField>

<ResponseField name="usage" type="object">
  Token counts and cost: `inputTokens`, `outputTokens`, `totalTokens`, `cost`.
</ResponseField>

<ResponseField name="status" type="string">
  Outcome of the interaction.
</ResponseField>

<ResponseField name="metadata" type="object">
  Any additional provider-specific fields, preserved as received.
</ResponseField>

### 2. Usage and cost

Aggregated, time-bucketed usage, for adoption and cost reporting.

<ResponseField name="startAt" type="timestamp">
  Start of the bucket.
</ResponseField>

<ResponseField name="endAt" type="timestamp">
  End of the bucket.
</ResponseField>

<ResponseField name="granularity" type="enum">
  `hour` or `day`.
</ResponseField>

<ResponseField name="dimensions" type="object">
  The grouping keys present in the bucket, any subset of the following.

  <Expandable title="dimensions">
    <ResponseField name="model" type="string" />

    <ResponseField name="assistantId" type="string" />

    <ResponseField name="userId" type="string" />

    <ResponseField name="department" type="string" />
  </Expandable>
</ResponseField>

<ResponseField name="metrics" type="object">
  The measured values for the bucket.

  <Expandable title="metrics">
    <ResponseField name="requests" type="integer" />

    <ResponseField name="conversations" type="integer" />

    <ResponseField name="activeUsers" type="integer" />

    <ResponseField name="inputTokens" type="integer" />

    <ResponseField name="outputTokens" type="integer" />

    <ResponseField name="cost" type="number" />
  </Expandable>
</ResponseField>

### 3. Assistants

Where your product allows customers to configure their own assistants, agents, or custom GPTs, one record per assistant describing its configuration.

<ResponseField name="id" type="string" />

<ResponseField name="name" type="string" />

<ResponseField name="description" type="string" />

<ResponseField name="status" type="string">
  For example `active` or `archived`.
</ResponseField>

<ResponseField name="createdAt" type="timestamp" />

<ResponseField name="updatedAt" type="timestamp" />

<ResponseField name="owner" type="object">
  The user who owns the assistant.
</ResponseField>

<ResponseField name="visibility" type="enum">
  `private`, `team`, `organisation`, or `public`.
</ResponseField>

<ResponseField name="model" type="string">
  Default model.
</ResponseField>

<ResponseField name="parameters" type="object">
  Default sampling configuration.
</ResponseField>

<ResponseField name="instructions" type="string">
  The assistant's instructions. Provide `instructionsHash` instead where the text cannot be shared.
</ResponseField>

<ResponseField name="skills" type="object[]">
  Tools or skills installed on the assistant.

  <Expandable title="skill">
    <ResponseField name="id" type="string" />

    <ResponseField name="name" type="string" />

    <ResponseField name="type" type="enum">
      `builtin`, `mcp`, `plugin`, or `function`.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="connectors" type="object[]">
  Integrations and data sources connected to the assistant.

  <Expandable title="connector">
    <ResponseField name="id" type="string" />

    <ResponseField name="type" type="string" />

    <ResponseField name="scopes" type="string[]" />
  </Expandable>
</ResponseField>

<ResponseField name="knowledge" type="object[]">
  Attached knowledge or reference files.
</ResponseField>

<ResponseField name="usage" type="object">
  Rollup: `conversationCount`, `userCount`, `lastUsedAt`.
</ResponseField>

### 4. Events

One record per notable action, forming an audit trail. Your native event type is preserved verbatim; the normalised fields are best-effort.

<ResponseField name="id" type="string" />

<ResponseField name="occurredAt" type="timestamp" />

<ResponseField name="type" type="string">
  Your native event type.
</ResponseField>

<ResponseField name="actor" type="object">
  Who performed the action.

  <Expandable title="actor">
    <ResponseField name="type" type="enum">
      `user`, `apiKey`, `serviceAccount`, or `system`.
    </ResponseField>

    <ResponseField name="id" type="string" />

    <ResponseField name="email" type="string" />
  </Expandable>
</ResponseField>

<ResponseField name="category" type="enum">
  `Authentication`, `Access`, `Configuration`, `DataMovement`, `ResourceLifecycle`, `Integration`, `Policy`, or `Other`.
</ResponseField>

<ResponseField name="action" type="enum">
  `Created`, `Updated`, `Deleted`, `Enabled`, `Disabled`, `Exported`, `Shared`, and similar.
</ResponseField>

<ResponseField name="target" type="object">
  What the action affected.

  <Expandable title="target">
    <ResponseField name="kind" type="string">
      For example an assistant, a skill, or a file.
    </ResponseField>

    <ResponseField name="id" type="string" />

    <ResponseField name="name" type="string" />
  </Expandable>
</ResponseField>

<ResponseField name="payload" type="object">
  The raw event body, preserved as received.
</ResponseField>

## Access and synchronisation

**Transport.** A read-only REST/JSON API is recommended and the simplest to integrate. An MCP server, a scheduled export, or webhooks are equally acceptable; the resource shapes above are what is normative.

**Authentication.** A single credential (bearer token or API key) per customer, scoped to that customer's data only. Per-resource scopes, for example `read:usage` or `read:conversations`, allow a customer to share usage metrics without exposing conversation content.

**Synchronisation.** Velatir retrieves data by polling on a schedule. The following are recommended rather than required; where they are absent, Velatir performs a full re-pull.

* **Stable identifiers.** A stable `id` on every record allows Velatir to update records in place rather than duplicate them on re-sync.
* **Timestamps.** RFC 3339, UTC. `updatedAt` and `occurredAt` allow Velatir to request only records that changed since the previous poll.
* **Pagination.** Lists that return `{ data[], hasMore, nextCursor }` with an opaque, retry-safe cursor allow Velatir to page through large histories reliably.
* **Incremental retrieval.** Filtering lists by `updatedSince` (conversations, assistants) and `occurredAfter` (events) avoids re-reading the full history on each poll.
* **Forward compatibility.** Fields and enum values may be added at any time. Velatir ignores unknown fields and never discards an unrecognised event `type`.

## Reference API

A minimal REST implementation consists of the following read-only endpoints:

```
GET /usage          ?startAt&endAt&granularity&groupBy
GET /assistants     ?updatedSince&cursor
GET /assistants/{id}
GET /conversations  ?updatedSince&startedAfter&cursor
GET /conversations/{id}
GET /events         ?occurredAfter&category&cursor
```

An example conversation record:

```json theme={null}
{
  "id": "conv_8f21a0",
  "conversationId": "thread_5521",
  "startedAt": "2026-07-03T09:15:00Z",
  "updatedAt": "2026-07-03T09:16:12Z",
  "user": { "id": "u_204", "email": "user@company.com", "department": "Operations" },
  "assistant": { "id": "asst_44", "name": "Support Assistant" },
  "model": "gpt-4o",
  "modelProvider": "openai",
  "parameters": { "temperature": 0.4, "maxTokens": 1024 },
  "systemPrompt": "You are a helpful assistant that ...",
  "messages": [
    { "id": "m1", "role": "user", "content": "How do I process this request?", "createdAt": "2026-07-03T09:15:00Z" },
    { "id": "m2", "role": "assistant", "content": "First, you ...", "createdAt": "2026-07-03T09:15:04Z" }
  ],
  "tools": [{ "id": "search", "name": "Knowledge search", "type": "builtin" }],
  "usage": { "inputTokens": 320, "outputTokens": 210, "totalTokens": 530 }
}
```
