# Quickstart

The conformance bar for this page: **integrate from a bash script, no
dependency, under 5 minutes.** Everything below works from any language
that can make an HTTP request.

### Get a key

Dashboard → **Add app** → copy the `sk_live_` server key it hands you. Or do it
headlessly with the [Control API](/docs/api/apps): `POST /v1/apps` returns the
key.

### Send your first event

```sh
curl -X POST https://in.datagauge.dev/v1/events \
  -H "Authorization: Bearer $DATAGAUGE_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"user_signup","user":"usr_8813"}'
```

`name` is the only required field. `user` is any opaque string you already
have: a cuid, a Firebase uid, an email, a license key. It is never
format-validated.

Your app card in the dashboard flips to **first event received ✓** the
moment this lands.

### Light up metrics with reserved names

| `name` | Powers | Notes |
|---|---|---|
| `user_signup` | Signups + MAU | |
| `payment` | Revenue | needs `props.amount` (integer **cents**) + `props.currency`; `sk` keys only; `id` required |
| anything else | Custom events, MAU | `page_view`, `report_generated`, whatever |

```sh
curl -X POST https://in.datagauge.dev/v1/events \
  -H "Authorization: Bearer $DATAGAUGE_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"payment","user":"usr_8813","id":"order_4711",
       "props":{"amount":4900,"currency":"usd"}}'
```

The `id` makes money idempotent: send that `payment` twice (retries, replays,
an at-least-once queue) and it counts **once**.

### Add MRR with one more call

`POST` your subscription state whenever it changes, from your billing
webhook handler, a nightly job, anywhere:

```sh
curl -X POST https://in.datagauge.dev/v1/objects \
  -H "Authorization: Bearer $DATAGAUGE_KEY" \
  -H "Content-Type: application/json" \
  -d '{"type":"subscription","id":"sub_9","status":"active",
       "mrr":4900,"currency":"usd"}'
```

Upsert semantics, last-write-wins. Only `status: "active"` counts toward
MRR. On Stripe or Polar? [Skip this entirely with a webhook](/docs/api/webhooks).

### Read your numbers back

Metrics lag ingest. A read you make straight after a write returns the **old**
value, and that is the system working, not a lost event:

- Ingest batches before it stores. At the trickle volume of a first
  integration, a batch waits out a **30 s** timeout rather than filling up.
- Metric reads are cached for **300 s** (5 minutes), so the first read after
  your write pins the pre-write answer for the rest of that window.

So budget roughly five minutes, and read again rather than concluding the event
did not land. If you want to confirm the write itself immediately, your app card
in the dashboard flips to **first event received ✓** as soon as ingest accepts
it, before any of the above.

```sh
curl https://api.datagauge.dev/v1/metrics/mrr \
  -H "Authorization: Bearer $DATAGAUGE_KEY"
# {"ok":true,"metric":"mrr","data":[{"currency":"usd","mrr":4900}]}
```

Also: `mau`, `dau`, `signups`, `revenue`, `volume`, with optional
`?date_from=2026-06-19&date_to=2026-07-18`.

A DataGauge app is live by default: **Add app** hands you an `sk_live_` key
and the numbers above are real. To rehearse an integration instead, flip the
dashboard to **test mode** (or mint an `sk_test_` key) and run these same
calls against it. Swap only the prefix, `sk_test_` for `sk_live_`, and
everything else is identical.

The test environment is isolated from live under its own `project_id` and
starts empty, so that first `sk_test_` event is what seeds it. Once you've sent
one, test mode never shows you a blank screen. Point a real integration
at `sk_live_` when you're happy.

Next: the [metrics reference](/docs/api/metrics) for every metric and window, [billing webhooks](/docs/api/webhooks) to get MRR without writing the objects call, or an [SDK](/docs/sdks) if your runtime drops background sends.
