Blog/Inside Steep

A builder's guide to the Steep API

January 28, 2026·6 min read

In this blog, I'll share a developer's perspective on what the new API enables, my learnings from experimenting, and some practical tips and use cases for getting started.

Hanna Kjellén
Hanna Kjellén
Engineer, Steep

The problem: business logic is scattered

In most organisations, business logic is fractured. Some of it lives in dashboards that don't quite agree, lives in internal tools, scripts, and one-off integrations, each quietly re-implementing business logic in its own way. Even with the best intentions, numbers start to drift over time.

Steep already solves this problem for analytics. By centralising definitions in one semantic model, all numbers stay consistent, understandable, and easy to govern.

With the Steep API, that same semantic model is now available beyond the app itself. Internal tools, custom workflows, and integrations can query data using the same trusted definitions your analysts already rely on.

What the Steep API unlocks

As of writing this post, we've just released the first version of the API which lets you:

  • Execute queries using your established business language, instead of SQL.
  • Browse metrics, dimensions, entities, and other parts of your semantic model programmatically.
  • Power custom apps, tools, notebooks, agents, automation, etc.

Making your first metric call

Let's get started with a simple example. Inside the Steep app, open up Settings → API, and generate an API key. For now, we'll only need the “Read metrics” and “Query metric data” scopes, but feel free to pick as many as you feel might be useful.

💡 API keys can't be edited, and the key itself will be encrypted and never shown to you again in the UI, so make sure to save it. More details can be found in the help center.

Let’s start by listing the metrics available in your semantic layer. To authorize the request using the API key, set the Authorization header to your API key prefixed with ApiKey . I’ll use curl in the command line for these examples, but the same principles apply when calling the API programmatically.

curl https://api.steep.app/v1/metrics \
-H "Authorization: ApiKey <Your API key>" \
-G

You should receive a response that follows this structure.

{
 "cacheTtlInSeconds": 14400,
 "refreshedAt": "2026-01-15T10:13:35.994Z",
 "sql": "SELECT
 SUM("orders"."order_amount")::float8 AS "metric",
 DATE_TRUNC('month', "orders"."order_date")::date AS "time"
FROM
 "public"."orders" "orders"
WHERE
 "orders"."order_date"::date >= '2025-01-01' AND "orders"."order_date"::date <= '2026-02-01'
GROUP BY
 2
ORDER BY
 2",
 "total": 13,
 "data": [
   {
     "time": "2025-01-01T00:00:00.000Z",
     "metric": 35285
   },
   {
     "time": "2025-02-01T00:00:00.000Z",
     "metric": 97407
   },
   ...
 ]
}

💡 Many fields will be returned as null, because by default, joined resources such as dimensions, modules, slices, etc. aren’t resolved. If you want the full details of your metrics, add expand=true as a query parameter.

Now let’s pick a metric and run a query. This time, it’s a POST request with a JSON body. Make sure to pick a timeGrain supported by the metric definition, and include a fromDate and a toDate.

curl https://api.steep.app/v1/metrics/<Your metric ID>/query 
-H "Authorization: ApiKey <Your API key>" 
-H "Content-type: application/json" 
-d '{"timeGrain":"monthly","fromDate":"2025-01-01T00:00:00.000Z","toDat

You should receive a response that follows this structure, with one data point for each month. Note that the generated SQL is also included, which makes it easy to debug and understand exactly what is being executed against your data source.

{

"cacheTtlInSeconds": 14400,
"refreshedAt": "2026-01-15T10:13:35.994Z",
"sql": "SELECT
SUM("orders"."order_amount")::float8 AS "metric",
DATE_TRUNC('month', "orders"."order_date")::date AS"time"
FROM
"public"."orders" "orders"
WHERE
"orders"."order_date"::date >= '2025-01-01' AND "orders"."order_date"::date <= '2026-02-01'
GROUP BY
2
ORDER BY
2",
"total": 13,
"data": [
 {
   "time": "2025-01-01T00:00:00.000Z",
   "metric": 35285
 },
 {
   "time": "2025-02-01T00:00:00.000Z",
   "metric": 97407
 },
 ...
]
}

Now, go build

Now that you have the data, it’s up to you to decide what to do with it. The sky is the limit.

Want to set up a leaderboard and rank everyone in the team based on how much the company’s revenue has increased since they joined?

Easy: Get the join date from Slack → Query the revenue metric between those specific dates and now → Sort and compare in a list.

Are you managing a shopping center and want to see store performance overlaid on your custom indoor map?

Easy: Map store IDs to custom map locations → Query metrics with a breakdown on store IDs → Show results on the map.

In both cases, the metric logic is defined in the same semantic model, and every tool gets the same answer.

Learnings from real-world experimentation

But custom bespoke software must be really expensive and time-consuming to build, right? That’s not necessarily true, I was surprised to learn how straightforward it was and how little glue code was needed. Once the semantic model is there, most of the work becomes product thinking rather than data plumbing.

  • Set up a React app with a single command using a template (there are some in the official docs, bun has one, etc.)
  • Install some sort of type-safe fetch client (I used openapi-react-query, hooked up to https://api.steep.app/openapi/json)
  • Open up Cursor/Claude Code/ChatGPT and explain what you want the app to do. You might have to give it some pointers or help it along the way, but with access the full API schema, it’ll get surprisingly far on its own. The biggest issue I had was getting the colors to work 😅

Active users

Active users by workspace. Quite evenly distributed.

Query volume

Query volume by workspace. One of these is not like the others 🧐

Another experiment was this viz: Monthly order volume, displayed as dollar bills falling from the sky. Anything is possible.

Monthly order volume

The roadmap ahead

This initial version of the API is only the beginning, and we’ll be expanding it over time.

We’re starting with read and query use cases, and plan to expand into write and management workflows over time. We want to ensure we’re heading in the right direction and are prioritising the right things, so don’t hesitate to reach out with your feedback and ideas.

Start building

The API has just been released for all users, and we’re excited to see what you’ll create with it. Head on over to the documentation to get started, and begin hacking away at your ideas and experiments today.

You can create a workspace here if you don't already have one.

Book a demo

Get help with exploring the platform and discussing use cases for your team.

Get started

Explore for free. Get your own workspace or try the demo setup.

More posts

New in Steep: API – Metrics power anything

By Nino Höglund·Product updates

Define in code

By Nino Höglund·Product updates

5 key requirements for a successful semantic layer

By Johan Baltzar·Data culture

Steep at Coalesce 2025

By Deanne Anderson·Events

More flexibility, better control

By Nino Höglund·Product updates

Put your metrics on the map

By Nino Höglund·Product updates