# Integration snippets

Record usage with the REST API or SDKs. Set `VT_KEY` to your tenant's ingest key; account/key provisioning currently goes through the Veritally owner. Public demo reads are keyless, while writes require authentication.

Keep keys on your server and out of browser bundles or source control. A stable `event_key` for each provider charge makes retries idempotent. Check delivery errors before treating a charge as booked.

## Plain curl

```bash
curl --fail-with-body -sS https://api.veritally.ai/v1/events \
  -H "Authorization: Bearer $VT_KEY" -H "Content-Type: application/json" \
  -d '{"model":"gpt-4o","input_tokens":1200,"output_tokens":800,
       "agent":"research-agent","project":"research","event_key":"provider-response-123"}'
```

Reuse that key only for the same upstream response. Use a new key for a distinct charge.

## Veritally SDKs

The SDKs send to `/ingest`. From a checkout of this repository, JavaScript can import the local module:

```js
import { Veritally } from "./product/sdk/veritally.js";

const books = new Veritally({
  apiBase: "https://api.veritally.ai",
  apiKey: process.env.VT_KEY,
  defaults: { principal: "you@company.com", policy: "Research" }
});
await books.track({
  model: "gpt-4o", cost_usd: 0.12,
  agent: "research-agent", event_key: "provider-response-123"
});
```

For Python, put `product/sdk` on the import path:

```python
import os
from veritally import Veritally

books = Veritally(api_base="https://api.veritally.ai", api_key=os.environ["VT_KEY"])
books.track(model="gpt-4o", cost_usd=0.12,
            agent="research-agent", event_key="provider-response-123")
```

JavaScript's immediate `track()` rejects on HTTP/network errors. If you enable `batchMs`, await `flush()` before shutdown; failed sends stay queued in memory for retry. Python sends synchronously and propagates `urllib` errors. Neither queue nor automatic event keys provide durable replay protection across process restarts: preserve the upstream key in your application.

See the repository's SDK README for adapters, context propagation and batching details.

## Anthropic SDK

Record the usage after a successful provider call. Choose your provider model in `ANTHROPIC_MODEL` and preserve the actual model in the event. Supply `cost_usd` if you have the provider's billed cost; otherwise the configured Veritally price book estimates it.

```js
import Anthropic from "@anthropic-ai/sdk";
const anthropic = new Anthropic();
const message = await anthropic.messages.create({
  model: process.env.ANTHROPIC_MODEL,
  max_tokens: 512,
  messages: [{ role: "user", content: "Summarize Q2 spend." }]
});
const booked = await fetch("https://api.veritally.ai/v1/events", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.VT_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({ model: message.model,
    input_tokens: message.usage.input_tokens,
    output_tokens: message.usage.output_tokens,
    agent: "research-agent", event_key: message.id })
});
if (!booked.ok) throw new Error(`Veritally rejected usage: HTTP ${booked.status}`);
```

## OpenAI SDK

```js
import OpenAI from "openai";
const openai = new OpenAI();
const response = await openai.chat.completions.create({
  model: "gpt-4o", messages: [{ role: "user", content: "Draft outreach." }]
});
const booked = await fetch("https://api.veritally.ai/v1/events", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.VT_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({ model: response.model,
    input_tokens: response.usage.prompt_tokens,
    output_tokens: response.usage.completion_tokens,
    agent: "outreach-agent", event_key: response.id })
});
if (!booked.ok) throw new Error(`Veritally rejected usage: HTTP ${booked.status}`);
```

## n8n HTTP Request node

- Method: `POST`, URL: `https://api.veritally.ai/v1/events`
- Header: `Authorization: Bearer {{$env.VT_KEY}}`
- JSON body: map the model, numeric token counts, agent and stable provider response ID to the REST fields above.
- Keep normal error handling enabled so a failed ingestion fails the node; retry with the same `event_key`.

## LiteLLM success callback

Use the supplied callback with the authenticated Python SDK:

```python
import os
import litellm
from veritally import Veritally
from litellm_adapter import install

books = Veritally(api_base="https://api.veritally.ai", api_key=os.environ["VT_KEY"])
install(books, ctx={"principal": "you@company.com", "policy": "Research"})
response = litellm.completion(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Summarize Q2 spend."}],
    metadata={"agent": "research-agent"}
)
```

Explicit `metadata.cost_usd` overrides LiteLLM's calculated `response_cost`; absent both, Veritally estimates from tokens. The SDK raises delivery errors from the callback, while LiteLLM controls callback error handling. Success callbacks receive fresh event keys. If callbacks may be replayed, book with `books.track(..., event_key=response.id)` instead and preserve that key across retries. Do not use both paths for the same charge.
