Direct Integration

If you cannot use the Python SDK — different language, different AI provider, or strict SDK version constraints — you can POST events directly to the Intake API.

Fully flexible. You define the event schema. Weflayr stores whatever JSON you send, subject only to event_id and event_type being present. Custom event types are stored and surfaced as-is.

Pattern

  1. Generate a UUID for the call — share it across .before, .after, .error
  2. POST .before immediately (before the LLM call)
  3. POST .after on success, .error on failure — include elapsed_ms

cURL

# Before
curl -X POST https://api.weflayr.com/$CLIENT_ID/ \
  -H "Authorization: Bearer $CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "event_id": "550e8400-e29b-41d4-a716-446655440000",
    "event_type": "custom.inference.before",
    "model": "llama-3.1-70b",
    "provider": "together-ai",
    "tags": {"feature": "translation", "customer": "acme"}
  }'

# After (same event_id)
curl -X POST https://api.weflayr.com/$CLIENT_ID/ \
  -H "Authorization: Bearer $CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "event_id": "550e8400-e29b-41d4-a716-446655440000",
    "event_type": "custom.inference.after",
    "model": "llama-3.1-70b",
    "elapsed_ms": 1230.5,
    "prompt_tokens": 412,
    "completion_tokens": 87,
    "tags": {"feature": "translation", "customer": "acme"}
  }'

Python (httpx)

import httpx, uuid, time

INTAKE_URL = "https://api.weflayr.com"
CLIENT_ID  = "your-client-id"
SECRET     = "your-client-secret"

endpoint = f"{INTAKE_URL}/{CLIENT_ID}/"
headers  = {"Authorization": f"Bearer {SECRET}"}

def track(model, fn, tags=None):
    event_id = str(uuid.uuid4())
    base = {"event_id": event_id, "model": model, "tags": tags or {}}

    with httpx.Client() as client:
        client.post(endpoint, json={**base, "event_type": "my.call.before"}, headers=headers)
        start = time.perf_counter()
        try:
            result = fn()
        except Exception as exc:
            elapsed = round((time.perf_counter() - start) * 1000, 1)
            client.post(endpoint, json={
                **base,
                "event_type": "my.call.error",
                "elapsed_ms": elapsed,
                "error_type": type(exc).__name__,
                "error_message": str(exc),
            }, headers=headers)
            raise
        elapsed = round((time.perf_counter() - start) * 1000, 1)
        client.post(endpoint, json={**base, "event_type": "my.call.after", "elapsed_ms": elapsed}, headers=headers)
        return result

JavaScript (fetch)

const INTAKE = 'https://api.weflayr.com';
const CLIENT_ID = 'your-client-id';
const SECRET = 'your-client-secret';

const endpoint = `${INTAKE}/${CLIENT_ID}/`;
const headers = {
  'Authorization': `Bearer ${SECRET}`,
  'Content-Type': 'application/json',
};

// Fire-and-forget helper
const post = (body) =>
  fetch(endpoint, { method: 'POST', headers, body: JSON.stringify(body) })
    .catch(() => {});

async function track(model, fn, tags = {}) {
  const eventId = crypto.randomUUID();
  const base = { event_id: eventId, model, tags };

  post({ ...base, event_type: 'my.call.before' });
  const start = performance.now();
  try {
    const result = await fn();
    const elapsed_ms = Math.round(performance.now() - start);
    post({ ...base, event_type: 'my.call.after', elapsed_ms });
    return result;
  } catch (err) {
    const elapsed_ms = Math.round(performance.now() - start);
    post({ ...base, event_type: 'my.call.error', elapsed_ms,
           error_type: err.name, error_message: err.message });
    throw err;
  }
}