URL: /code/apps/analytics-and-experiments/define · Id: `page:/code/apps/analytics-and-experiments/define`

# Metric.define

> Compiles a number from your Events and lists every Event it reads, so no one types it in.

POST https://api.sb/&#123;your-domain&#125;/metrics/define

Compiles a number from your [Events](https://startupbuilder.dev/business/nouns/event) and lists every Event it reads, so no one types it in.

- **Action class:** None
- **Approval:** Runs on its own
- **Emits:** `Metric.defined`
- **Price:** Free

```text title="Run it · Ask"
Define activation as a portfolio with 10 units imported and one rent payment logged within 7 days.
```

```ts title="Run it · SDK"
import { $ } from 'startup-builder'

const result = await $.try.Metric.define({ name: 'activation-rate', query: 'share of new portfolios with 10 units imported and 1 payment logged within 7 days of signup', unit: 'share' })
```

```json title="Run it · Response"
{
  "api": "https://api.sb/leaseline.app",
  "metric": {
    "$id": "https://api.sb/leaseline.app/metrics/metric_activation-rate",
    "$type": "Metric",
    "name": "activation-rate",
    "unit": "share"
  },
  "action": {
    "operation": "Metric.define",
    "mode": "try",
    "status": "done"
  }
}
```

Its Inputs, Outputs, Effects and guards quote [the hub’s `Metric.define`](https://startupbuilder.dev/business/nouns/metric/define); this page adds what each Venue honors, its limits and a worked call. It is one of the [Verbs](https://startupbuilder.dev/business/nouns/verb) of [Analytics and experiments](/code/apps/analytics-and-experiments#verbs).

## Inputs
| Name | Type | Default | Meaning |
| --- | --- | --- | --- |
| `name` | `string` | Required | The Metric’s name. |
| `query` | `text` | Required | The query, over Events and Entries. |
| `unit` | `string` | Required | What one unit of it is. |

## Outputs
| Field | Type | What `null` means |
| --- | --- | --- |
| `metric` | `Metric` | Never null: the defined Metric. |

## Effects
**Action class**

None: no approval rule names it, so it runs within its seat’s Permissions and Limits

**Modes**

- `try`: Runs every check and returns the record as it would be; nothing is stored.
- `send`: Returns a pending Action at once; `Metric.defined` fires when it is done.
- `do`: Waits for the Action to finish and returns the record.

**Idempotency**

Only with a key: the same `Idempotency-Key` and input return the first Action, and the same key with other input returns `409`.

**Saved or shared**

A Change that renames or removes an Event this Metric reads must map it to a new Event, or the Change is refused.

**Emits**

`Metric.defined` with `{ metric }`

**Performed by**

[Analyst](https://startupbuilder.dev/agents/marketing/analyst)

**Price**

Free on your own account: the platform charges nothing for the call.

## On each Venue
It acts on your own records and reaches no Venue, so every account answers the same way.

## What try does
Runs every check the call meets and returns the record as it would be; nothing is stored, sent or posted.

## Refuses when
| Guard | Refuses | Error |
| --- | --- | --- |
| `known-events` | Refuses a query that names an Event no Verb emits. | `invalid-input` |

## When it waits
Returns in one response; nothing waits.

## Example
In `send` mode the call returns its pending Action at once, and `Metric.defined` delivers the result.

**Ask**

```text
Define activation as a portfolio with 10 units imported and one rent
payment logged within 7 days.
```

**API**

```bash
curl -X POST "https://api.sb/leaseline.app/metrics/define?mode=send" \
  -H "Authorization: Bearer $SB_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "activation-rate",
  "query": "share of new portfolios with 10 units imported and 1 payment logged within 7 days of signup",
  "unit": "share"
}'
```

**CLI**

```bash
npx startup-builder do Metric.define --send --data '{
  "name": "activation-rate",
  "query": "share of new portfolios with 10 units imported and 1 payment logged within 7 days of signup",
  "unit": "share"
}'
```

`--send` returns the pending Action at once.

**MCP**

```json
{
  "name": "do",
  "arguments": {
    "mode": "send",
    "code": "return await $.Metric.define({ name: 'activation-rate', query: 'share of new portfolios with 10 units imported and 1 payment logged within 7 days of signup', unit: 'share' })"
  }
}
```

**SDK**

```ts
import { $ } from 'startup-builder'

const result = await $.send.Metric.define({
  name: 'activation-rate',
  query: 'share of new portfolios with 10 units imported and 1 payment logged within 7 days of signup',
  unit: 'share',
})
```


```json title="Response, in send mode"
{
  "mode": "send",
  "action": {
    "$id": "https://api.sb/leaseline.app/actions/action_Sd3kQ9vT2w",
    "operation": "Metric.define",
    "status": "pending",
    "reason": "running"
  }
}
```

To retry, send the same `Idempotency-Key`: the retry returns the first answer for $0. A new key reads again.

## Used by
- **Jobs:** [Keep and grow customers](/capabilities/keep-and-grow) · [Measure](/capabilities/measure)

## Related
[`Metric.query`](/code/apps/analytics-and-experiments/query) · [`Metric.watch`](/code/apps/analytics-and-experiments/watch) · [`Experiment.start`](/code/apps/analytics-and-experiments/start) · [`Experiment.conclude`](/code/apps/analytics-and-experiments/conclude) · [`Dashboard.ask`](/code/apps/analytics-and-experiments/ask) · [`Event.capture`](/code/apps/analytics-and-experiments/capture) · [`Hypothesis.test`](/code/apps/analytics-and-experiments/test) · [`Dashboard.schedule`](/code/apps/analytics-and-experiments/schedule)