Integration reference

Connect an AI agent to OliverDB.

One endpoint, one key, one table. An agent can record what it did and ask questions about it in SQL, and the key it holds only ever sees its own rows. There is nothing to provision — write something, then ask about it.

Model Context Protocol HTTP API bearer key AWS us‑west‑2
01 · Get a key

Sign in, copy the key, send it as a bearer token.

Sign in at dogfood.olivercloud.ai. Your key is shown once, begins ohv_, and goes on every call:

Authorization: Bearer <your key>

Each key opens exactly one table and sees only the rows written with that key. Service is hosted in AWS us-west-2. Free and Pro plans; Pro is $19 a month, billed on our site.

A call without a key is refused rather than emptied:

HTTP 401
{"error":"missing_key",
 "message":"send your key as Authorization: Bearer ohv_…"}
Base URL
https://dogfood.olivercloud.ai
Endpoints
POST /mcpModel Context Protocol
POST /v1/eventswrite events
POST /v1/querySQL over your events
GET  /v1/schemathe table’s columns
GET  /v1/manifestdocs for your key
GET  /v1/meplan and usage today
02 · MCP

The preferred door for agents.

Model Context Protocol over streamable HTTP, at https://dogfood.olivercloud.ai/mcp. Stateless — there is no session to open, every call carries the key. Three tools, each the same audited path as the HTTP doors, so an agent gets identical answers whichever it uses.

oliver_write

Write events to your table. Send an array of objects; only name is required. Any field you send that is not a column is kept under attrs.

oliver_query

Run one SQL statement over your rows in the events table. Scoped to you automatically — never filter on user_id.

oliver_onboard

Returns the manifest for this key: the table, how to write, how to ask, the plan and today’s usage. Read it once at the start.

Claude Desktop, Cursor, Windsurf
{
  "mcpServers": {
    "oliver": {
      "url": "https://dogfood.olivercloud.ai/mcp",
      "headers": {
        "Authorization": "Bearer <your key>"
      }
    }
  }
}
Command line
claude mcp add --transport http oliver \
  https://dogfood.olivercloud.ai/mcp \
  --header "Authorization: Bearer <your key>"
codex mcp add oliver \
  --url https://dogfood.olivercloud.ai/mcp \
  --bearer-token-env-var OLIVER_KEY
Clients that cannot send a header

Use the key-in-path form and select no authentication:

https://dogfood.olivercloud.ai/mcp/<your key>
03 · HTTP API

Two calls do almost everything.

Write — POST /v1/events

One object or an array, up to 10,000 events per request. Only name is required. ts is optional — send seconds, milliseconds or RFC 3339, or leave it out and the service stamps the current time.

curl -X POST https://dogfood.olivercloud.ai/v1/events \
  -H "Authorization: Bearer <your key>" \
  -H "content-type: application/json" \
  -d '[
    {"name":"signup","app":"myapp","plan":"pro"},
    {"kind":"metric","name":"latency_ms","value":182.5,
     "app":"myapp","attrs":{"route":"/checkout"}},
    {"kind":"note","name":"decision",
     "text":"We chose Postgres for billing.",
     "session_id":"chat-42"}
  ]'

Answer: {"ingested": 3, "dropped": []}. Rows land within a few seconds.

Read — POST /v1/query

Send {"sql": "..."}. The table is events. No time filter means your plan’s whole window.

-- what happened in the last 24 hours, by name
SELECT name, count(*) FROM events
WHERE ts >= now() - interval '24 hours'
GROUP BY name ORDER BY count(*) DESC LIMIT 20
-- a value summed by one of your own properties, per day
SELECT time_bucket('1d', ts), attrs.region, sum(value)
FROM events WHERE kind = 'metric' AND name = 'order_total'
GROUP BY time_bucket('1d', ts), attrs.region
-- range of a metric over a window
SELECT min(value), max(value), avg(value)
FROM events
WHERE name = 'latency_ms' AND ts >= '2026-09-01'
The SQL surface

Aggregates count(*), sum(value), avg, min, max, and percentile_cont(0.95) WITHIN GROUP (ORDER BY value) for p50/p95/p99. Time buckets with time_bucket('1h', ts)'5m', '1h', '1d', or a number of seconds. Full text with text_match(text, 'word'). Your own fields with attrs.key = 'value'. Date literals like ts >= '2026-09-01'. Rows are immutable: there is no update or delete, you write a new row.

04 · Data model

One table. Nothing to design.

Everything lands in events. Anything you send that is not a column below is kept under attrs and stays queryable as attrs.key, so you never migrate a schema to record something new.

columnmeaning
namewhat happened, or the metric or note name — the only required field
tswhen; send it or let the service stamp now
kindevent · metric · log · note · trace
appyour project or app slug
session_idthread, request or conversation id, for replay
leveldebug · info · warn · error
valuea number: metric value, duration, score
textmessage, note body, memory — full-text searchable
attrsany other field you send, queryable as attrs.key
05 · Plans and limits

What each plan allows per day.

 FreePro — $19/month
rows written per day10,0001,000,000
queries per day1,00020,000
results read per day1 GB50 GB
concurrent queries24
query window7 days90 days
groups per answer1,0005,000
seconds per query1020
When you hit one

Quotas are per key per day and reset at 00:00 UTC. Over quota returns 429 with the count so far and the time until reset, plus Retry-After: 60. More than 10,000 events in one request returns 413. An answer larger than a few megabytes also returns 413 — add a LIMIT, ask for fewer columns, or narrow the window. Windows wider than your plan are clamped rather than refused, and results are capped at the plan’s group count.

06 · What people ask it

Things an agent can answer once it is connected.

“Show me revenue by region by week from the orders I uploaded.” “How many signups yesterday, and how many bought within 24 hours?” “Which products had the biggest week‑over‑week change?” “Daily active users for 90 days, and flag the unusual days.” “Which sensors went outside their normal range in the last six hours?” “What did my agents spend on tokens, by agent and model?” “Compare conversion for the two checkout variants.” “Log this event.” “What happened in my app in the last hour, by event name?”

Give your agent a database of its own.