Quickstart#
By the end of this page you'll have a source syncing into your lake, a query over
the live data, and a model that rebuilds itself every four hours. The examples use
Skycrane, a fictional freight-software company that runs on Stripe and HubSpot —
substitute your own numbers as you go.
1. Connect a source#
Open Apps and choose Connect app. Pick the source you want — for
Skycrane, Stripe. Each source asks only for what it needs; Stripe wants a single restricted
API key, created read-only in a minute from the Stripe dashboard, so a leaked key
can never change anything in your account. Each source's page walks through its
credentials — Stripe is the one this guide uses.
Save the key and the first sync starts on its own.
2. Watch the data land#
The Sync history tab shows the sync as it runs, table by table. When it
finishes, every table lives in your lake under a schema named for the source:
titan.stripe.charges
titan.stripe.customers
titan.stripe.subscriptions
titan.stripe.invoices
…From now on the source re-syncs every 4 hours. Only what changed is fetched, and
rows deleted at the source are marked, never silently dropped — that's the_deleted column you'll meet in a moment. The Tables tab controls exactly
which tables and columns sync; everything is on by default.
3. Run your first query#
Open Queries and ask the first question every finance dashboard asks:
select
date_trunc('month', created_at) as month,
round(sum(amount) / 100.0, 2) as gross_volume
from titan.stripe.charges
where not _deleted
group by month
order by month desc
limit 4month gross_volume
2026-08-01 291441.00
2026-07-01 338129.50
2026-06-01 331624.00
2026-05-01 319887.25Two things to notice, because they apply to every table in the lake:
Stripe stores
amountin minor units — cents — so we divide by 100. Each
connector page documents quirks like this.where not _deletedexcludes rows that were deleted in Stripe. The lake keeps
them, marked, so history never silently shrinks.
Your lake explains the system columns.
Queries join across sources as easily as within one — Skycrane's open pipeline
next to its billing, one join away:
select
property_dealstage as stage,
count(*) as deals,
round(sum(property_amount)) as pipeline_value
from titan.hubspot.deals
where not _deleted and not property_hs_is_closed
group by stage
order by pipeline_value descstage deals pipeline_value
contractsent 7 412000.0
decisionmakerboughtin 11 280500.0
qualifiedtobuy 19 224000.0
presentationscheduled 9 118750.04. Make it a model#
A query you'll want tomorrow belongs in a model: a select statement in a file
that Supernova keeps materialized as a table. Open Files (or clone your data
repo with git) and create models/monthly_revenue.sql:
-- name: Monthly revenue
select
date_trunc('month', created_at) as month,
round(sum(amount) / 100.0, 2) as gross_volume,
round(sum(amount_refunded) / 100.0, 2) as refunded
from titan.stripe.charges
where not _deleted
group by monthThat's the whole thing. The file's basename is the table name, and models rebuild
every 4 hours in dependency order — a model can select from another model, and
Supernova works out the order from the SQL itself. Query it like any other table:
select * from titan.models.monthly_revenue order by month descWriting models covers the header directives —
output schemas, incremental updates by key, manual cadence, type checking.
Where to go next#
Your lake — how tables, deletes, and snapshots
actually work. Ten minutes that make everything else make sense.Type annotations — add types to exactly the SQL
that deserves them; the checker catches drift before your dashboards do.Limits — every ceiling in one honest table.