Metrics
Endpoints for defining reward metrics, assignment sources, and previewing metric data.
Metrics define what Levered reads from your warehouse. Reward metrics tell the model what counts as success. Assignment sources tell it where exposure data lives. All metric endpoints are under /api/v2/warehouse and require an Authorization: Bearer <token> header.
Create metric
POST /api/v2/warehouse/metricsAuth: Required
Creates a new metric backed by a SQL query against your warehouse.
Request body:
{
"name": "Signup Conversion",
"sql": "SELECT user_id AS anonymous_id, converted_at AS timestamp FROM conversions",
"column_mapping": {
"anonymous_id": "anonymous_id",
"timestamp": "timestamp",
"reward_type": "bool"
}
}| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Human-readable metric name |
sql | string | Yes | SQL query that produces the metric data. Must return at least the columns specified in column_mapping. |
column_mapping | object | Yes | Maps query output columns to Levered's expected fields |
column_mapping.anonymous_id | string | Yes | Column containing the user identifier |
column_mapping.timestamp | string | Yes | Column containing the event timestamp |
column_mapping.reward_type | string | No | Type of reward: bool (binary conversion) or numeric (continuous value) |
Response (201):
{
"id": "metric-uuid",
"name": "Signup Conversion",
"sql": "SELECT user_id AS anonymous_id, converted_at AS timestamp FROM conversions",
"column_mapping": {
"anonymous_id": "anonymous_id",
"timestamp": "timestamp",
"reward_type": "bool"
},
"created_at": "2026-03-28T14:00:00Z",
"updated_at": null,
"meta": {
"request_id": "req_abc123",
"organization_id": "org_xyz"
}
}List metrics
GET /api/v2/warehouse/metricsAuth: Required
Returns all metrics in the organization.
Response:
{
"metrics": [
{
"id": "metric-uuid",
"name": "Signup Conversion",
"sql": "SELECT user_id AS anonymous_id, converted_at AS timestamp FROM conversions",
"column_mapping": {
"anonymous_id": "anonymous_id",
"timestamp": "timestamp",
"reward_type": "bool"
},
"created_at": "2026-03-28T14:00:00Z",
"updated_at": null
}
],
"meta": {
"request_id": "req_abc123",
"organization_id": "org_xyz"
}
}Get metric
GET /api/v2/warehouse/metrics/:idAuth: Required
Path parameters:
| Parameter | Type | Description |
|---|---|---|
id | string (UUID) | Metric ID |
Response: Returns the full metric object including sql and column_mapping.
Preview metric
POST /api/v2/warehouse/metrics/:id/previewAuth: Required
Executes the metric's SQL query and returns a sample of the results. Useful for validating that the query returns the expected data before linking it to an optimization.
Path parameters:
| Parameter | Type | Description |
|---|---|---|
id | string (UUID) | Metric ID |
Response:
{
"rows": [
{ "anonymous_id": "user-abc", "timestamp": "2026-03-28T14:00:00Z" },
{ "anonymous_id": "user-def", "timestamp": "2026-03-28T14:05:00Z" }
],
"meta": {
"request_id": "req_abc123",
"organization_id": "org_xyz"
}
}Delete metric
DELETE /api/v2/warehouse/metrics/:idAuth: Required
Deletes a metric. If the metric is referenced by guardrails, the request will fail with 409 Conflict.
Path parameters:
| Parameter | Type | Description |
|---|---|---|
id | string (UUID) | Metric ID |
Response: 204 No Content
Assignment source
Assignment sources define where Levered reads exposure (variant assignment) data from your warehouse. Each organization has one active assignment source.
Create or update assignment source
POST /api/v2/warehouse/assignment-sourceAuth: Required
Request body:
{
"name": "Exposure Events",
"sql": "SELECT anonymous_id, timestamp, headline, cta_text FROM exposures",
"column_mapping": {
"anonymous_id": "anonymous_id",
"timestamp": "timestamp"
}
}| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Human-readable name |
sql | string | Yes | SQL query that returns exposure rows. Must include the design factor columns. |
column_mapping.anonymous_id | string | Yes | Column containing the user identifier |
column_mapping.timestamp | string | Yes | Column containing the event timestamp |
column_mapping.variant | string | No | Column containing a JSON-serialized variant object (e.g., {"headline": "A", "cta": "B"}) |
column_mapping.context | string | No | Column containing JSON context attributes |
column_mapping.factors | object | No | Maps design factor names to warehouse column names (e.g., {"headline": "headline_col"}) |
Response (201):
{
"id": "source-uuid",
"name": "Exposure Events",
"sql": "SELECT anonymous_id, timestamp, headline, cta_text FROM exposures",
"column_mapping": {
"anonymous_id": "anonymous_id",
"timestamp": "timestamp"
},
"created_at": "2026-03-28T14:00:00Z",
"updated_at": null,
"meta": {
"request_id": "req_abc123",
"organization_id": "org_xyz"
}
}Get assignment source
GET /api/v2/warehouse/assignment-sourceAuth: Required
Returns the current assignment source configuration.
Delete assignment source
DELETE /api/v2/warehouse/assignment-sourceAuth: Required
Removes the assignment source. Optimizations will not be able to train until a new source is configured.
Response: 204 No Content
Preview assignment source
POST /api/v2/warehouse/assignment-source/previewAuth: Required
Executes the assignment source SQL and returns a sample of rows.
Response:
{
"rows": [
{ "anonymous_id": "user-abc", "timestamp": "2026-03-28T14:00:00Z", "headline": "Ship faster", "cta_text": "Start free" },
{ "anonymous_id": "user-def", "timestamp": "2026-03-28T14:01:00Z", "headline": "Build better", "cta_text": "Try it now" }
],
"meta": {
"request_id": "req_abc123",
"organization_id": "org_xyz"
}
}