Developer Quickstart

Integrate phospho into your AI application in under 5 minutes. Capture every interaction, track sessions, and get production intelligence — all through a simple REST API.

Step 1

Get your API key

Every request to the phospho API is authenticated with a project-scoped API key. You can create and manage keys from your dashboard.

  1. Open the Dashboard → Settings page.
  2. Click Create API Key and give it a name (e.g. "production").
  3. Copy the key — it starts with ph_. You'll only see the full key once.
$export PHOSPHO_API_KEY="ph_your_api_key"
Step 2

Send your first event

The ingestion API accepts a JSON payload with the user's input and the AI model's output. That's all you need to start monitoring.

bash
curl -X POST https://co-phospho.nanocorp.app/api/ingest \
  -H "Authorization: Bearer ph_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "input": "What is the capital of France?",
    "output": "The capital of France is Paris.",
    "metadata": {
      "model": "gpt-4",
      "latency_ms": 850,
      "token_count_input": 12,
      "token_count_output": 18
    }
  }'

A successful response returns 201 with the created event's event_id. You can use this ID to submit feedback later.

Step 3

Python SDK: Wrap an OpenAI call

The pattern is simple: make your model call as usual, then send the interaction to phospho with one HTTP request. Here's a helper function and a complete example using the OpenAI SDK.

Helper function

python
import requests

PHOSPHO_API_KEY = "ph_your_api_key"
PHOSPHO_URL = "https://co-phospho.nanocorp.app/api/ingest"

def log_to_phospho(input_text, output_text, session_id=None, metadata=None):
    """Send a single AI interaction event to phospho."""
    response = requests.post(
        PHOSPHO_URL,
        headers={"Authorization": f"Bearer {PHOSPHO_API_KEY}"},
        json={
            "input": input_text,
            "output": output_text,
            "session_id": session_id,
            "metadata": metadata or {},
        },
    )
    response.raise_for_status()
    return response.json()

Full example with OpenAI

python
import openai
import requests
import time

# ── Config ───────────────────────────────────────────────
PHOSPHO_API_KEY = "ph_your_api_key"
PHOSPHO_URL = "https://co-phospho.nanocorp.app/api/ingest"
client = openai.OpenAI()

def chat_with_logging(user_message, session_id=None):
    """Call OpenAI and automatically log to phospho."""
    start = time.time()

    # 1. Call OpenAI as usual
    response = client.chat.completions.create(
        model="gpt-4",
        messages=[{"role": "user", "content": user_message}],
    )
    latency_ms = int((time.time() - start) * 1000)
    ai_response = response.choices[0].message.content

    # 2. Log the interaction to phospho
    requests.post(
        PHOSPHO_URL,
        headers={"Authorization": f"Bearer {PHOSPHO_API_KEY}"},
        json={
            "input": user_message,
            "output": ai_response,
            "session_id": session_id,
            "metadata": {
                "model": "gpt-4",
                "provider": "openai",
                "latency_ms": latency_ms,
                "token_count_input": response.usage.prompt_tokens,
                "token_count_output": response.usage.completion_tokens,
            },
        },
    )

    return ai_response

# ── Usage ────────────────────────────────────────────────
answer = chat_with_logging(
    "Explain quantum computing in simple terms",
    session_id="user-456-session",
)
print(answer)

Tip: The logging call is fire-and-forget. For production, consider wrapping it in a try/except or sending asynchronously so it never blocks your main response path.

Step 4

Batch event sending

For high-throughput applications, send up to 100 events in a single request using the batch endpoint. This reduces HTTP overhead and improves efficiency.

cURL

bash
curl -X POST https://co-phospho.nanocorp.app/api/ingest/batch \
  -H "Authorization: Bearer ph_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "events": [
      {
        "input": "Summarize this article",
        "output": "The article discusses recent advances in...",
        "session_id": "session-abc",
        "metadata": { "model": "gpt-4", "latency_ms": 1200 }
      },
      {
        "input": "Translate to Spanish",
        "output": "El articulo discute los avances recientes en...",
        "session_id": "session-abc",
        "metadata": { "model": "gpt-4", "latency_ms": 980 }
      }
    ]
  }'

Python

python
import requests

PHOSPHO_API_KEY = "ph_your_api_key"
PHOSPHO_BATCH_URL = "https://co-phospho.nanocorp.app/api/ingest/batch"

def log_batch(events):
    """Send up to 100 events in a single request."""
    response = requests.post(
        PHOSPHO_BATCH_URL,
        headers={"Authorization": f"Bearer {PHOSPHO_API_KEY}"},
        json={"events": events},
    )
    response.raise_for_status()
    return response.json()

# ── Example: batch-send accumulated events ───────────────
events = [
    {
        "input": "Summarize this article",
        "output": "The article discusses recent advances in...",
        "session_id": "session-abc",
        "metadata": {"model": "gpt-4", "latency_ms": 1200},
    },
    {
        "input": "Translate to Spanish",
        "output": "El articulo discute los avances recientes en...",
        "session_id": "session-abc",
        "metadata": {"model": "gpt-4", "latency_ms": 980},
    },
]

result = log_batch(events)
print(result)

Note: Each event in the batch can have its own session_id and metadata. Events are deduplicated by event_id for safe retries.

Step 5

Session tracking

Group related interactions into sessions by passing a session_id. All events sharing the same ID appear together in the dashboard, letting you replay entire conversations and track per-session metrics.

python
import requests
import uuid

PHOSPHO_API_KEY = "ph_your_api_key"
PHOSPHO_URL = "https://co-phospho.nanocorp.app/api/ingest"

def create_session_id(user_id=None):
    """Generate a unique session ID, optionally prefixed with user ID."""
    if user_id:
        return f"{user_id}-{uuid.uuid4().hex[:8]}"
    return str(uuid.uuid4())

# ── Multi-turn conversation with session tracking ────────
session_id = create_session_id(user_id="user-42")

# Turn 1
requests.post(
    PHOSPHO_URL,
    headers={"Authorization": f"Bearer {PHOSPHO_API_KEY}"},
    json={
        "input": "What is machine learning?",
        "output": "Machine learning is a subset of AI that enables...",
        "session_id": session_id,
        "metadata": {
            "model": "gpt-4",
            "user_id": "user-42",
            "tags": ["onboarding", "education"],
        },
    },
)

# Turn 2 — same session_id groups them together
requests.post(
    PHOSPHO_URL,
    headers={"Authorization": f"Bearer {PHOSPHO_API_KEY}"},
    json={
        "input": "Can you give me a real-world example?",
        "output": "A common example is email spam filtering...",
        "session_id": session_id,
        "metadata": {
            "model": "gpt-4",
            "user_id": "user-42",
            "tags": ["onboarding", "education"],
        },
    },
)

# All events with the same session_id appear together
# in the phospho dashboard under Sessions.

Auto-grouping

If no session_id is sent but a user_id exists in metadata, phospho groups events using a 30-minute inactivity window.

Session metrics

Duration, event count, token usage, cost estimate, and success rate are computed automatically for each session.

Dashboard view

The Sessions page shows a filterable list. Click into any session to see the full event timeline.

Bonus

Submit user feedback

Link explicit user feedback (thumbs up/down, ratings) to a specific event. This enriches quality metrics and helps calibrate success/failure detection.

bash
curl -X POST https://co-phospho.nanocorp.app/api/feedback \
  -H "Authorization: Bearer ph_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "event_id": "the-event-uuid",
    "flag": "success",
    "comment": "Great answer!",
    "source": "user"
  }'

Event payload schema

Full schema for the POST /api/ingest endpoint. Only input and output are required — everything else is optional.

json
{
  "event_id":    "uuid-v4 (auto-generated if omitted)",
  "session_id":  "optional — groups events into sessions",
  "project_id":  "required — identified from your API key",
  "input":       "required — the user input / prompt",
  "output":      "required — the AI model response",
  "metadata": {
    "model":              "gpt-4",
    "provider":           "openai",
    "latency_ms":         1230,
    "token_count_input":  150,
    "token_count_output": 420,
    "cost_cents":         2.3,
    "user_id":            "optional — end-user identifier",
    "tags":               ["production", "chatbot"],
    "custom_key":         "any additional metadata"
  },
  "timestamp":   "ISO 8601 (auto-set if omitted)"
}

API endpoints

MethodEndpointDescription
POST/api/ingestIngest a single event
POST/api/ingest/batchIngest up to 100 events
POST/api/feedbackSubmit feedback for an event
GET/api/eventsList / search events
GET/api/events/:idGet event detail
GET/api/sessionsList sessions
GET/api/sessions/:idSession detail with events

Rate limits

Free tier

1,000 events/min

Pro tier

10,000 events/min

All endpoints authenticate via Authorization: Bearer ph_your_api_key. Requests without a valid key receive a 401. Rate-limited requests receive 429.

Ready to get started?

Create your project and start capturing AI interactions in under 5 minutes.