From raw, chaotic CSVs to production-ready APIs in minutes

Transform, join and serve data with familiar SQL queries and documented, secured APIs.

tap flow diagram

Tap into the value of data. Go from:

Data locked away

Valuable datasets trapped in static files, unusable by applications

Weeks of development

Building data pipelines and APIs traditionally takes extensive engineering resources

Isolated datasets

No easy way to combine, enrich, or transform data from multiple sources

To unleashing the value from any data file, all spreadsheet exports, and every public dataset in your applications within minutes.

No backend development required.

See the transformation

Watch messy data become a production-ready API

1. Start with raw data

PostcodeUtf8
AddressLine1Utf8
AddressLine2Utf8
"KA278LF""Lamlash ""Isle of Arran"
"KA128SS"" Kilwinning Road"" Irvine"
"KA280HF""College St ""Millport"
"KA2 0BE"" Kilmarnock Road""Kilmarnock"
"KA120DP"" Warrix Avenue""Irvine"
"KA6 6AB""Dalmellington Road ""Ayr"
"KA9 2HQ""Biggart Road ""Prestwick"
"KA6 6DX"" Dalmellington Road""Ayr"
"KA7 4DW""10 Doonfoot Road ""Ayr"
"KA215RF""Nelson Road""Saltcoats"
Arrow down

2. Clean and transform with SQL

SELECT
regexp_replace("Postcode", '\s*(.3$)', ' \1', 'g') AS "Postcode",
trim("AddressLine1") AS "AddressLine1",
trim("AddressLine2") AS "AddressLine2"
FROM data.example
PostcodeUtf8
AddressLine1Utf8
AddressLine2Utf8
"KA27 8LF""Lamlash""Isle of Arran"
"KA12 8SS""Kilwinning Road""Irvine"
"KA28 0HF""College St""Millport"
"KA2 0BE""Kilmarnock Road""Kilmarnock"
"KA12 0DP""Warrix Avenue""Irvine"
"KA6 6AB""Dalmellington Road""Ayr"
"KA9 2HQ""Biggart Road""Prestwick"
"KA6 6DX""Dalmellington Road""Ayr"
"KA7 4DW""10 Doonfoot Road""Ayr"
"KA21 5RF""Nelson Road""Saltcoats"
Arrow down

3. Join with other datasets

SELECT model.example_cleaned.*,
data.uk_postcode_lookup.latitude AS "Latitude",
data.uk_postcode_lookup.longitude AS "Longitude"
FROM model.example_cleaned
JOIN data.uk_postcode_lookup ON "Postcode" = postcode
PostcodeUtf8
LatitudeFloat64
LongitudeFloat64
AddressLine1Utf8
AddressLine2Utf8
"KA27 8LF"55.54312-5.115521"Lamlash""Isle of Arran"
"KA12 8SS"55.635056-4.676106"Kilwinning Road""Irvine"
"KA28 0HF"55.761296-4.922755"College St""Millport"
"KA2 0BE"55.61394-4.539409"Kilmarnock Road""Kilmarnock"
"KA12 0DP"55.611863-4.660189"Warrix Avenue""Irvine"
"KA6 6AB"55.434174-4.593108"Dalmellington Road""Ayr"
"KA9 2HQ"55.492576-4.604862"Biggart Road""Prestwick"
"KA6 6DX"55.430332-4.595538"Dalmellington Road""Ayr"
"KA7 4DW"55.449149-4.639765"10 Doonfoot Road""Ayr"
"KA21 5RF"55.63957-4.772409"Nelson Road""Saltcoats"
Arrow down

4. Enrich with H3 geospatial indexing

SELECT
model.example_joined.*,
h3_latlng_to_cell("Latitude", "Longitude", 15::INT) AS "H3Res15"
FROM model.example_joined
PostcodeUtf8
H3Res15Utf8
LatitudeFloat64
LongitudeFloat64
AddressLine1Utf8
AddressLine2Utf8
"KA27 8LF""8f19569a8c5c648"55.54312-5.115521"Lamlash""Isle of Arran"
"KA12 8SS""8f19092e6775410"55.635056-4.676106"Kilwinning Road""Irvine"
"KA28 0HF""8f19092b0d119ad"55.761296-4.922755"College St""Millport"
"KA2 0BE""8f190925084439b"55.61394-4.539409"Kilmarnock Road""Kilmarnock"
"KA12 0DP""8f19092e3d467a6"55.611863-4.660189"Warrix Avenue""Irvine"
"KA6 6AB""8f1954598d46a49"55.434174-4.593108"Dalmellington Road""Ayr"
"KA9 2HQ""8f1954598c58ac3"55.492576-4.604862"Biggart Road""Prestwick"
"KA6 6DX""8f1954598c58ac3"55.430332-4.595538"Dalmellington Road""Ayr"
"KA7 4DW""8f19545932d3a66"55.449149-4.639765"10 Doonfoot Road""Ayr"
"KA21 5RF""8f19092f28342c1"55.63957-4.772409"Nelson Road""Saltcoats"
Arrow down

5. Download or serve via a documented, secure and monitored API:

https://example.com/test?Within=[-5.205964198095899,55.50214416203221,-5.079052659295115,55.57395814779818]
{
  "data": [
    {
      "Postcode": "KA27 8LF",
      "H3Res15": "8f19569a8c5c648",
      "Latitude": 55.54312,
      "Longitude": -5.115521,
      "AddressLine1": "Lamlash",
      "AddressLine2": "Isle of Arran"
    }
  ],
  "_meta": {
    "cursor": null,
    "elapsed": 35
  }
}
Try the interactive demo

Everything you need, nothing you don't

Focus on your data and use-case, not infrastructure

Large files of various formats

Upload CSV, JSONL, Parquet and other files of any size.

Full power of SQL

Clean, join, enrich your data using familiar SQL queries.

No infrastructure setup

Zero backend configuration. No servers to manage.

Auto-generated docs

OpenAPI documentation created automatically.

Built-in security

Secure your endpoints with API keys on a unique domain and separate storage.

Geospatial filters

Custom API filters, including location-based via H3 indexing.

Usage monitoring

Track API usage metrics.

High performance

Fast, optimised queries.

No lock-in

Download the transformed data at any point.

Case study: Scottish Energy Performance Certificate (EPC) data

Scotland publishes energy performance certificate data as CSV files only. So we used tap to transform those CSVs into the API behind epcdata.scot.

Raw government data

From a zip of 41 CSV files totalling 3 GB

Beyond ELT

We cleaned, transformed and enriched it with geospatial indexes

Enabled live applications

Our API is used in numerous applications providing real value

Ready to tap into your data?

Transform your CSV files into production APIs in minutes. No backend experience required.

Try tap now

Start building immediately • No credit card required