Skip to main content

Transparent LLM usage tracking — OpenAI and Anthropic wrappers that send cost and token metrics to Nightswatch.

Project description

Nightswatch SDK — Installation & Integration Guide

Base URL: https://api.nightswatch.dev


Requirements

  • Python 3.9+
  • An active Nightswatch account and API key (nw_ prefix)

Installation

pip install nightswatch

To enable NER-based PII redaction (recommended for production):

pip install nightswatch spacy
python -m spacy download en_core_web_sm

Without spacy, PII redaction falls back to regex-only (SSN, credit cards, emails, phones, IP addresses still redacted).


Quick Start

1. Initialize

Call nightswatch.init() once at application startup, before any LLM calls.

import nightswatch

nightswatch.init(
    api_key="nw_your_api_key_here",
    default_team="backend",
    default_service="chat-api",
)

Parameters

Parameter Type Required Default Description
api_key string Yes Your API key from the Nightswatch dashboard
default_team string No "unknown" Team label applied to all events unless overridden per-call
default_service string No "unknown" Service/product label applied to all events

2. Wrap your LLM client

Pass your existing client to nightswatch.wrap(). The returned object is a drop-in replacement — all existing call signatures remain unchanged.

client = nightswatch.wrap(client)

Provider Integration

OpenAI

import nightswatch
from openai import OpenAI

nightswatch.init(api_key="nw_your_api_key_here", default_team="backend", default_service="chat-api")

client = nightswatch.wrap(OpenAI())

response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Explain async/await in Python"}],
)
print(response.choices[0].message.content)

Anthropic

import nightswatch
import anthropic

nightswatch.init(api_key="nw_your_api_key_here", default_team="ml-team", default_service="summarizer")

client = nightswatch.wrap(anthropic.Anthropic())

message = client.messages.create(
    model="claude-3-5-sonnet-20241022",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Summarize this document..."}],
)
print(message.content[0].text)

Google Gemini

import nightswatch
import google.generativeai as genai

nightswatch.init(api_key="nw_your_api_key_here", default_team="product", default_service="search")

genai.configure(api_key="your_gemini_key")
model = nightswatch.wrap(genai.GenerativeModel("gemini-1.5-flash"))

response = model.generate_content("What is the capital of France?")
print(response.text)

REST API (Manual Instrumentation)

If you are not using Python, or need to instrument a language without a native SDK, send events directly to the ingestion endpoint.

POST /v1/events
Authorization: Bearer nw_your_api_key_here
Content-Type: application/json

Request body

Field Type Required Description
provider string Yes LLM provider: openai, anthropic, google, etc.
model string Yes Model name, e.g. gpt-4o, claude-3-5-sonnet-20241022
prompt_tokens integer Yes Input token count
completion_tokens integer Yes Output token count
total_tokens integer Yes Sum of prompt + completion tokens
cost_usd float No Cost in USD (computed server-side from token counts if 0)
team string No Team label for cost attribution
service string No Service/product label
user_id string No End-user identifier (for per-user analytics)
metadata object No Arbitrary key-value pairs; PII is redacted before storage

Example

curl -X POST https://api.nightswatch.dev/v1/events \
  -H "Authorization: Bearer nw_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "provider": "openai",
    "model": "gpt-4o",
    "prompt_tokens": 142,
    "completion_tokens": 89,
    "total_tokens": 231,
    "cost_usd": 0.0,
    "team": "backend",
    "service": "chat-api"
  }'

Response 200

{
  "status": "ok",
  "event_id": "64d3f2a1-..."
}

Errors

Code Reason
401 Missing or invalid API key
422 Required field missing or wrong type

Batch Ingestion

Send up to 100 events in a single request.

POST /v1/events/batch
Authorization: Bearer nw_your_api_key_here
Content-Type: application/json

Request body

{
  "events": [
    { "provider": "openai", "model": "gpt-4o", "prompt_tokens": 100, "completion_tokens": 50, "total_tokens": 150 },
    { "provider": "anthropic", "model": "claude-3-haiku-20240307", "prompt_tokens": 200, "completion_tokens": 80, "total_tokens": 280 }
  ]
}

Configuration Options

Per-call overrides

Override default_team or default_service for a specific call by passing keyword arguments (where supported by the provider wrapper):

response = client.chat.completions.create(
    model="gpt-4o",
    messages=[...],
    nightswatch_team="data-science",
    nightswatch_service="embeddings",
)

Data Retention

Retention is configured per-tenant via the API. Valid values: 7, 30, or 90 days.

# Get current retention setting
curl https://api.nightswatch.dev/v1/tenants/retention \
  -H "Authorization: Bearer nw_your_api_key_here"

# Update retention to 30 days
curl -X PUT https://api.nightswatch.dev/v1/tenants/retention \
  -H "Authorization: Bearer nw_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{"retention_days": 30}'

Response

{ "tenant_id": "...", "retention_days": 30 }

Events older than the configured window are automatically deleted nightly.


PII Redaction

All prompt text and metadata values are automatically redacted before storage and AI analysis. The following are detected and replaced with [REDACTED]:

PII Type Examples
SSN 123-45-6789
Credit card numbers Visa, Mastercard, Amex (with or without spaces/dashes)
Email addresses alice@example.com
Phone numbers US, UK, Indian formats
IP addresses 192.168.1.1
Aadhaar / PAN Indian government IDs
Named entities Person names, organizations, locations (requires spacy)

Raw prompt text is never stored. The Nightswatch AI risk classifier only receives token counts, model name, provider, cost, team, and service — never prompt content.

To verify redaction is active in your environment:

from backend.services.pii_redactor import redact

print(redact("Contact alice@example.com or call 555-867-5309"))
# → "Contact [REDACTED] or call [REDACTED]"

Troubleshooting

Symptom Cause Fix
401 Unauthorized Invalid or missing API key Confirm key starts with nw_ and is passed in Authorization: Bearer header
422 Unprocessable Entity Required field missing Ensure provider, model, prompt_tokens, completion_tokens, total_tokens are present
Events not appearing in dashboard Clock skew on event timestamp Use UTC timestamps; Nightswatch rejects events more than 24 h in the past
Cost shows 0.0 cost_usd not sent Either send cost_usd from your LLM client, or Nightswatch computes it from token counts automatically for known models
spaCy NER not running Package not installed pip install spacy && python -m spacy download en_core_web_sm; falls back to regex if unavailable
ValueError: retention_days must be... Invalid retention value Only 7, 30, or 90 are accepted

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

nightswatch_sdk-0.1.0.tar.gz (69.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

nightswatch_sdk-0.1.0-py3-none-any.whl (9.5 kB view details)

Uploaded Python 3

File details

Details for the file nightswatch_sdk-0.1.0.tar.gz.

File metadata

  • Download URL: nightswatch_sdk-0.1.0.tar.gz
  • Upload date:
  • Size: 69.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.4

File hashes

Hashes for nightswatch_sdk-0.1.0.tar.gz
Algorithm Hash digest
SHA256 4acd9780da4073ba416fe84b51e9146b0833238b4219ee4465bfbf99f07e9f32
MD5 0b08a7d4d99e29e4944452f3843de3c9
BLAKE2b-256 b38780701bcec74a56b63defdf15f39f0d20deaa46ab42b0af5464a9bfc9fce8

See more details on using hashes here.

File details

Details for the file nightswatch_sdk-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for nightswatch_sdk-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0bc75338a702f26d1e0721680e57ebc4e736a0051a5936aa7ccc40e6b10a7173
MD5 d3e307889fb4271801c2cd413a7ca560
BLAKE2b-256 14b3dab0ee3c3aad03002705be4aac01aebc23f43c33b95ac2e3f7983060b9ac

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page