How to build a Snowflake API?
Tags: snowflake, dataapi, analytics, dataplatform
Published: 2023-01-17 16:42:34

_In this post, you’ll see exactly what it takes to create and query an API on top of your Snowflake data warehouse using Propel’s blazing-fast Serverless Analytics API Platform. In five easy steps, you’ll connect to Snowflake, define a Metric, and query it with our GraphQL API._

Are you looking for a way to build a fast, secure API on top of your Snowflake data warehouse? Propel's Serverless Analytics API Platform offers a fast and cost-effective way to create an API on top of your Snowflake data that is secure, performant, and low latency. In this post, we will walk you through the five easy steps to connecting your [Snowflake Data Source](https://www.propeldata.com/docs/data-sources/snowflake), syncing your tables, defining [Metrics](https://www.propeldata.com/docs/metrics), and querying your [API](https://www.propeldata.com/docs/api/about-the-graphql-api) with JavaScript, Python, Java, Go, Ruby, and C#/.NET. Let's get started!

## Why do you need an API on top of Snowflake?

Snowflake typically has the most complete data organizations have. It centralizes data from all the different data silos, whether internal databases or SaaS applications. It is also the right platform to clean and transform your data, making it optimal for visualization and consumption. 

When using the data internally for employees, you can either query the data directly with SQL or through a BI tool like Looker or Tableau; therefore, you don’t typically need an API. 

You need an API on top of Snowflake when you are building customer-facing web or mobile applications that include:

- User-facing dashboards
- Product usage and metering
- Analytics APIs
- Email Reporting
- Customer data sharing

These use cases have unique requirements and require a secure and performant data serving layer with low latency and high concurrency to provide a seamless user experience. 

## What are the requirements for an API on top of Snowflake?

When looking to build an API on top of Snowflake to power data applications and features powered by large-scale analytical data, you should consider the following requirements:

- ⚡️ **Low latency →** Customers expect fast, snappy product experiences. While internal employees may be okay waiting 45 seconds or even minutes for a query to run, this latency is a no-go for customer-facing products where the data analysis is part of the core product experience

- 🌊 **High concurrency →** Products need to support thousands or millions of users. Because data products ultimately serve customers rather than employees, they must support a dramatically higher number of concurrent requests than what internal data tools are designed to handle. And they must do so seamlessly and cost-effectively.

- 💰 **Cost-effectiveness** **→** Data has a fundamental tradeoff between flexibility, cost, and performance. The API should make it easy for users to understand and then make this tradeoff for different use cases.
- 🔐 **Multi-tenant security layer →** Each end-user can see only their own data. In SaaS and consumer products, end-users access their own data from web or mobile applications. This requires a multi-tenant security layer for business-to-business or consumer environments, not just employee-centric role-based access control.

Querying the warehouse directly from customer-facing applications can be slow, costs can get out of control, and it still requires substantial backend service logic to serve this data securely to the frontend.

## Does Snowflake have an API?

Yes, Snowflake offers a pass-through SQL API. It is a REST API that takes SQL statements and executes them against the data warehouse. It is useful if you want to query SQL over REST, but it does not provide any additional abstraction, optimization, or security features to power secure, performant, low-latency customer-facing applications.

## How do I build an API on top of Snowflake?

To build a performant Snowflake API to power your customer-facing web and mobile apps, you can use Propel, a serverless analytics API platform built on top of Snowflake. 

Propel provides the cloud infrastructure, scalability, and security required to power data applications at a massive scale while giving you the flexibility to define the metrics you want to query. You can build your first Snowflake API in minutes by following these five easy steps:

### 1. Connect your Snowflake Data Source

To set up a Snowflake Data Source for Propel, follow our [How to set up a Snowflake Data Source](https://www.propeldata.com/docs/data-sources/snowflake/guides/how-to-set-up-a-snowflake-data-source) guide. If you need a Propel account, [book a demo](https://meetings.hubspot.com/propel/demo), and we'll onboard you as soon as possible. Then, enter your Snowflake connection details in Propel's Console to create the Data Source.

Propel will connect to Snowflake and run a series of checks to ensure the connection has the correct permissions.

![An animated screen capture of the Propel Console, showing how to create a Snowflake Data Source and the numerous checks that confirm the connection is working.](https://assets.website-files.com/62471507c14eae234d6854b1/63bddd334a28df5c287f653c_create-snowflake-data-source-2023-01.gif)

An animated screen capture of the Propel Console, showing how to create a Snowflake Data Source and the numerous checks that confirm the connection is working.

### 2. Sync a table from Snowflake

Once connected, you can see your Snowflake tables in Propel. You can create a Data Pool for the table you want to serve data from. The Data Pool is a synced cache of your table that Propel optimizes for serving data. Propel’s built-in syncing eliminates the need for data pipelines, ETLs, or data engineering.

When creating the Data Pool, you must specify the table, its primary timestamp column (typically when the record was created), and a tenant ID if tenant-level access control is needed for your application.

![An animated screen capture of the Propel Console, showing how to create a Data Pool from a table within a Data Source.](https://assets.website-files.com/62471507c14eae234d6854b1/63bf0b11c939e02e30597879_create-metric-2023-01.gif)

An animated screen capture of the Propel Console, showing how to create a Data Pool from a table within a Data Source.

### 3. Define Metrics

With your data in a Propel Data Pool, you can define the Metrics you want to use in your web or mobile application. Metrics are the analytics measures you want to track, and they can be of different types: SUM, COUNT, COUNT_DISTINCT, MIN, MAX, and AVERAGE.

Once you configure your Metric settings in Propel, you can select the columns you want to expose as dimensions. Dimensions are different ways to filter Metric data to uncover insights. When defining a customer-facing Metric, you can control which columns are exposed to your customer via Dimensions.

![create-metric-2023-01.gif](https://assets.website-files.com/62471507c14eae234d6854b1/63bf0b11c939e02e30597879_create-metric-2023-01.gif)

### 4. Query your Snowflake API

Propel gives you a GraphQL API on top of Snowflake that is always highly available and performant in just a few easy steps. Once you have your Metric defined, you can try [Propel’s GraphQL Explorer](https://propeldata.com/docs/api/graphql-explorer) to query the Metric data in the format you are going to use: a [time series](https://propeldata.com/docs/metrics/time-series), a [counter](https://propeldata.com/docs/metrics/counter), or a [leaderboard](https://propeldata.com/docs/metrics/leaderboard). 

At the top-right of the GraphQL Explorer, you'll see the quick response times Propel's high-performance GraphQL API provides. In this example, querying hundreds of thousands of records takes about 500 milliseconds (end to end).

![An animated screen capture of Propel’s GraphQL explorer, showing how to query a Metric using the GraphQL API with various time granularities and filters.](https://assets.website-files.com/62471507c14eae234d6854b1/62df479898504293ef1e99d5_propel-snowflake-animation4.gif)

An animated screen capture of Propel’s GraphQL explorer, showing how to query a Metric using the GraphQL API with various time granularities and filters.

### 5. Build your analytics product using Propel’s GraphQL API for Snowflake

The Metric you defined previously is now available via the Snowflake GraphQL API. Using the technology stack of your choice, you can build in-product analytics into your app. You didn’t have to do any data engineering beyond loading your data to Snowflake.

![An animated screen capture of Visual Studio Code, showing how to use Propel’s GraphQL API, React, and ECharts to query and visualize Metric data from Snowflake.](https://assets.website-files.com/62471507c14eae234d6854b1/62df481f45e33d1f37c54945_propel-snowflake-animation5.gif)

**API Authentication**

Once you have your Snowflake API up and running with Propel, you’ll need to authenticate your requests. Propel uses OAuth 2.0 client credentials flow to authenticate your requests to the API securely. This flow requires you to provide a client ID and a client secret to authenticate your requests. These credentials are generated in the Propel Console when you create an Application. To learn more, read our [GraphQL Authentication guide](https://www.propeldata.com/docs/api/authentication).

The examples below show how to query your new Snowflake API using different programming languages, frameworks, and tools.

**Example 1: The GraphQL query to your Snowflake API**

An example GraphQL query on top of Snowflake. The first code block contains the GraphQL query and the second code block contains the JSON variables to include. When issuing the GraphQL request, ensure you replace `METXXXXXXXXXXXXXXXXXXXXXXXXXX` with your Metric ID and include your access token in the “Authorization” header as a bearer token.

```graphql
query TimeSeriesQuery($metricId: ID!, $input: TimeSeriesInput!) {
  metric(id: $metricId) {
    timeSeries(input: $input) {
      labels
      values
    }
  }
}
```

```json
{
  "metricId": "METXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "input": {
    "granularity": "DAY",
    "timeRange": {
      "relative": "LAST_N_DAYS",
      "n": 30
    },
    "filters": [{
      "column": "PROMO",
      "operator": "EQUALS"
      "value": "FALSE"
    }]
  }
}
```

**Example 2: Query your Snowflake API with curl**

An example of a Snowflake API request using the command-line tool curl. Ensure you replace `<ACCESS TOKEN>` with your access token and `METXXXXXXXXXXXXXXXXXXXXXXXXXX` with your Metric ID.

```bash
curl https://api.us-east-2.propeldata.com/graphql \
  -H "Authorization: Bearer <ACCESS TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{
  "query": "query TimeSeriesQuery($metricId: ID!, $input: TimeSeriesInput!) { metric(id: $metricId) { timeSeries(input: $input) { labels values } } }",
  "variables": {
    "metricId": "METXXXXXXXXXXXXXXXXXXXXXXXXXX",
    "input": {
      "granularity": "DAY",
      "timeRange": {
        "relative": "LAST_N_DAYS",
        "n": 30
      },
      "filters": [{
        "column": "PROMO",
        "operator": "EQUALS",
        "value": "FALSE"
      }]
    }
  }
}'
```

**Example 3: Query your Snowflake API with JavaScript (Node.js)**

An example of a Snowflake API request using JavaScript. This example uses the [graphql-request](https://github.com/prisma-labs/graphql-request) library to issue the actual GraphQL request. Install the dependency:

```bash
npm i graphql-request
```

Then, copy the following sample to a file, `index.js`, replace `<ACCESS TOKEN>` with your access token, and replace `METXXXXXXXXXXXXXXXXXXXXXXXXXX` with your Metric ID.

```jsx
const { request, gql } = require('graphql-request')

const endpoint = 'https://api.us-east-2.propeldata.com/graphql'
const accessToken = '<ACCESS TOKEN>'

const query = gql`
  query TimeSeriesQuery($metricId: ID!, $input: TimeSeriesInput!) {
    metric(id: $metricId) {
      timeSeries(input: $input) {
        labels
        values
      }
    }
  }
`

const variables = {
  metricId: 'METXXXXXXXXXXXXXXXXXXXXXXXXXX',
  input: {
    granularity: 'DAY',
    timeRange: {
      relative: 'LAST_N_DAYS',
      n: 30
    },
    filters: [{
      column: 'PROMO',
      operator: 'EQUALS',
      value: 'FALSE'
    }],
  }
}

request({
  url: endpoint,
  document: query,
  variables,
  headers: {
    Authorization: `Bearer ${accessToken}`
  }
}).then(data => {
  console.log(JSON.stringify(data))
}, error => {
  console.error(error)
})
```

Finally, run the example:

```bash
node index.js
```

**Example 4: Query your Snowflake API with React**

An example of a Snowflake API request using JavaScript, React, and Chart.js. This example uses [react-chartjs-2](https://github.com/reactchartjs/react-chartjs-2), a wrapper for [Chart.js](https://www.chartjs.org/). Install the dependencies:

```bash
npm i react-chartjs-2 chart.js
```

Then, copy the following sample to a file, `TimeSeries.jsx`, replace `<ACCESS TOKEN>` with your access token, and replace `METXXXXXXXXXXXXXXXXXXXXXXXXXX` with your Metric ID.

```jsx
import React, { useEffect, useState } from 'react'
import {
  Chart as ChartJS,
  CategoryScale,
  LinearScale,
  PointElement,
  LineElement,
  Title,
  Tooltip,
  Legend
} from 'chart.js'
import { Line } from 'react-chartjs-2'

ChartJS.register(
  CategoryScale,
  LinearScale,
  PointElement,
  LineElement,
  Title,
  Tooltip,
  Legend
)

const endpoint = 'https://api.us-east-2.propeldata.com/graphql'
const accessToken = '<ACCESS TOKEN>'

const query = `
  query TimeSeriesQuery($metricId: ID!, $input: TimeSeriesInput!) {
    metric(id: $metricId) {
      timeSeries(input: $input) {
        labels
        values
      }
    }
  }
`

const variables = {
  metricId: 'METXXXXXXXXXXXXXXXXXXXXXXXXXX',
  input: {
    granularity: 'DAY',
    timeRange: {
    relative: 'LAST_N_DAYS',
      n: 30
    },
    filters: [{
      column: 'PROMO',
      operator: 'EQUALS',
      value: 'FALSE'
    }]
  }
}

const options = {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${accessToken}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    query,
    variables
  })
}

export function TimeSeries () {
  const [error, setError] = useState(undefined)
  const [timeSeries, setTimeSeries] = useState(undefined)

  useEffect(() => {
    async function query () {
      const response = await fetch(endpoint, options)
      const { data } = await response.json()
      setTimeSeries(data?.metric?.timeSeries ?? undefined)
    }

    setError(undefined)
    query().catch(setError)
  }, [])

  if (error) return 'An error has occurred: ' + error.message
  if (!timeSeries) return 'Loading...'

  return (
    <Line
      data={{
        labels: timeSeries.labels,
        datasets: [
          {
            label: 'Metric Values',
            data: timeSeries.values
          }
        ]
      }}
    />
  )
}
```

Finally, import your component and mount it in your React app:

```jsx
import React from 'react'
import { createRoot } from 'react-dom/client'

import { TimeSeries } from './TimeSeries.jsx'

const rootElement = document.getElementById('root')
createRoot(rootElement).render(<App />)
```

**Example 5: Query your Snowflake API with Python**

An example of a Snowflake API request using Python. This example uses Python’s built-in `urllib.request` library for issuing the GraphQL request, so it doesn’t require additional dependencies; however, in production, you could use a library like [gql](https://github.com/graphql-python/gql) for stronger typing.

Copy the following sample to a file, `main.py`, replace `<ACCESS TOKEN>` with your access token, and replace `METXXXXXXXXXXXXXXXXXXXXXXXXXX` with your Metric ID.

```python
import json
import urllib.request

endpoint = 'https://api.us-east-2.propeldata.com/graphql'
access_token = '<ACCESS TOKEN>'

query = """
  query TimeSeriesQuery($metricId: ID!, $input: TimeSeriesInput!) {
    metric(id: $metricId) {
      timeSeries(input: $input) {
        labels
        values
      }
    }
  }
"""

variables = {
  'metricId': 'METXXXXXXXXXXXXXXXXXXXXXXXXXX',
  'input': {
    'granularity': 'DAY',
    'timeRange': {
      'relative': 'LAST_N_DAYS',
      'n': 30
    },
    'filters': [{
      'column': 'PROMO',
      'operator': 'EQUALS',
      'value': 'FALSE'
    }]
  }
}

headers = {
  'Content-Type': 'application/json',
  'Authorization': 'Bearer {}'.format(access_token)
}

body = json.dumps({
  'query': query,
  'variables': variables
}).encode('utf-8')

request = urllib.request.Request(endpoint, headers=headers, data=body)
response = urllib.request.urlopen(request)
result = response.read().decode('utf-8')
print(result)
```

Finally, run the example:

```bash
python main.py
```

**Example 6: Query your Snowflake API with Java**

An example of a Snowflake API request using Java. This example uses Java’s built-in HttpClient and constructs JSON manually, so it doesn’t require additional dependencies; however, in production, you should use a library like [Jackson](https://github.com/FasterXML/jackson) for constructing JSON. Additionally, for stronger typing, you could use Apollo’s [Kotlin-based GraphQL client](https://www.apollographql.com/docs/kotlin/).

Copy the following sample to a file, `Main.java`, replace `<ACCESS TOKEN>` with your access token, and replace `METXXXXXXXXXXXXXXXXXXXXXXXXXX` with your Metric ID.

```java
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class Main {
    public static void main(String[] args) throws IOException, InterruptedException {
        final var endpoint = "https://api.us-east-2.propeldata.com/graphql";
        final var accessToken = "<ACCESS TOKEN>";

        final var query = """
                query TimeSeriesQuery($metricId: ID!, $input: TimeSeriesInput!) {
                  metric(id: $metricId) {
                    timeSeries(input: $input) {
                      labels
                      values
                    }
                  }
                }
                """;

        final var variables = """
                {
                  "metricId": "METXXXXXXXXXXXXXXXXXXXXXXXXXX",
                  "input": {
                    "granularity": "DAY",
                    "timeRange": {
                      "relative": "LAST_N_DAYS",
                      "n": 30
                    },
                    "filters": [{
                      "column": "PROMO",
                      "operator": "EQUALS",
                      "value": "FALSE"
                    }]
                  }
                }
                """;

        final var body = "{\"query\":\"" + query.replaceAll("\n", "\\\\n") + "\",\"variables\":" + variables + "}";

        final var client = HttpClient.newHttpClient();
        final var request = HttpRequest.newBuilder(URI.create(endpoint))
                .header("Content-Type", "application/json")
                .header("Authorization", "Bearer " + accessToken)
                .POST(HttpRequest.BodyPublishers.ofString(body))
                .build();

        final var response = client.send(request, HttpResponse.BodyHandlers.ofString());

        System.out.println(response.body());
    }
}
```

Finally, run the example, either from your IDE or from the command-line with `java`.

**Example 7: Query your Snowflake API with Go**

An example of a Snowflake API request using Go. This example uses the Go standard library, so it doesn’t require additional dependencies; however, in production, you could use a library like [shurcooL/graphql](https://github.com/shurcooL/graphql) or [Khan/genqlient](https://github.com/Khan/genqlient) for stronger typing.

Copy the following sample to a file, `main.go`, replace `<ACCESS TOKEN>` with your access token, and replace `METXXXXXXXXXXXXXXXXXXXXXXXXXX` with your Metric ID.

```go
package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
)

type timeRangeInput struct {
	Relative string `json:"relative"`
	N        int    `json:"n"`
}

type filterInput struct {
	Column   string `json:"column"`
	Operator string `json:"operator"`
	Value    string `json:"value"`
}

type timeSeriesInput struct {
	Granularity string         `json:"granularity"`
	TimeRange   timeRangeInput `json:"timeRange"`
	Filters     []filterInput  `json:"filters"`
}

type timeSeriesResponse struct {
	Data struct {
		Metric struct {
			TimeSeries struct {
				Labels []string `json:"labels"`
				Values []string `json:"values"`
			} `json:"timeSeries"`
		} `json:"metric"`
	} `json:"data"`
}

type request struct {
	Query     string         `json:"query"`
	Variables map[string]any `json:"variables"`
}

func main() {
	endpoint := "https://api.us-east-2.propeldata.com/graphql"
	accessToken := "<ACCESS TOKEN>"

	query := `
	  query TimeSeriesQuery($metricId: ID!, $input: TimeSeriesInput!) {
	    metric(id: $metricId) {
	      timeSeries(input: $input) {
	        labels
	        values
	      }
	    }
	  }
	`

	variables := map[string]any{
		"metricId": "METXXXXXXXXXXXXXXXXXXXXXXXXXX",
		"input": timeSeriesInput{
			Granularity: "DAY",
			TimeRange: timeRangeInput{
				Relative: "LAST_N_DAYS",
				N:        30,
			},
			Filters: []filterInput{
				{
					Column:   "PROMO",
					Operator: "EQUALS",
					Value:    "FALSE",
				},
			},
		},
	}

	requestBody, err := json.Marshal(request{
		Query:     query,
		Variables: variables,
	})
	if err != nil {
		panic(err)
	}

	req, err := http.NewRequest("POST", endpoint, bytes.NewBuffer(requestBody))
	if err != nil {
		panic(err)
	}

	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("Authorization", "Bearer "+accessToken)

	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()

	responseBody, err := ioutil.ReadAll(res.Body)
	if err != nil {
		panic(err)
	}

	var response timeSeriesResponse
	err = json.Unmarshal(responseBody, &response)
	if err != nil {
		panic(err)
	}

	fmt.Printf("%+v\n", response)
}
```

Finally, run the example:

```bash
go run main.go
```

**Example 8: Query your Snowflake API with Ruby**

An example of a Snowflake API request using Ruby. This example uses the Ruby standard library, so it doesn’t require additional dependencies; however, in production, you could use a library like GitHub’s own [graphql-client](https://github.com/github/graphql-client) for stronger typing.

Copy the following sample to a file, `main.rb`, replace `<ACCESS TOKEN>` with your access token, and replace `METXXXXXXXXXXXXXXXXXXXXXXXXXX` with your Metric ID.

```ruby
require 'json'
require 'net/http'

endpoint = "https://api.us-east-2.propeldata.com/graphql"
accessToken = "<ACCESS TOKEN>"

query = """
  query TimeSeriesQuery($metricId: ID!, $input: TimeSeriesInput!) {
    metric(id: $metricId) {
      timeSeries(input: $input) {
        labels
        values
      }
    }
  }
"""

variables = {
  metricId: 'METXXXXXXXXXXXXXXXXXXXXXXXXXX',
  input: {
    granularity: 'DAY',
    timeRange: {
      relative: 'LAST_N_DAYS',
      n: 30
    },
    filters: [{
      column: 'PROMO',
      operator: 'EQUALS',
      value: 'FALSE'
    }]
  }
}

body = {
  'query': query,
  'variables': variables
}

res = Net::HTTP.post(URI(endpoint), body.to_json, {
  'Content-Type': 'application/json',
  'Authorization': 'Bearer ' + accessToken
})

puts res.body
```

Finally, run the example:

```bash
ruby main.rb
```

**Example 9: Query your Snowflake API with C#/.NET**

An example of a Snowflake API request using C#/.NET. This example uses the C#/.NET standard library, so it doesn’t require additional dependencies; however, in production, you could use a library like [graphql-client](https://github.com/graphql-dotnet/graphql-client) for stronger typing.

Copy the following sample to a file, `Program.cs`, replace `<ACCESS TOKEN>` with your access token, and replace `METXXXXXXXXXXXXXXXXXXXXXXXXXX` with your Metric ID.

```jsx
using System.Text.Json;

namespace Example
{
    class TimeSeriesResponse
    {
        public DataField data { get; set; }
    }

    class DataField
    {
        public MetricField metric { get; set; }
    }

    class MetricField
    {
        public TimeSeriesField timeSeries { get; set; }
    }

    class TimeSeriesField
    {
        public string[] labels { get; set; }
        public string[] values { get; set; }
    }

    public class Program
    {
        public static void Main()
        {
            var endpoint = "https://api.us-east-2.propeldata.com/graphql";
            var accessToken = "<ACCESS TOKEN>";

            var query = @"
query TimeSeriesQuery($metricId: ID!, $input: TimeSeriesInput!) {
  metric(id: $metricId) {
    timeSeries(input: $input) {
      labels
      values
    }
  }
}
";

            var variables = new
            {
                metricId = "METXXXXXXXXXXXXXXXXXXXXXXXXXX",
                input = new
                {
                    granularity = "DAY",
                    timeRange = new
                    {
                        relative = "LAST_N_DAYS",
                        n = 30
                    },
                    filters = new[]
                    {
                        new
                        {
                            column = "PROMO",
                            @operator = "EQUALS",
                            value = "FALSE"
                        }
                    }
                }
            };

            var body = JsonSerializer.Serialize(new
            {
                query = query,
                variables = variables
            });

            var client = new HttpClient()
            {
                BaseAddress = new Uri(endpoint)
            };

            client.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken);

            var response = client.PostAsync(endpoint, new StringContent(body, System.Text.Encoding.UTF8, "application/json")).Result;
            var responseJson = response.Content.ReadAsStringAsync().Result;

            var timeSeriesResponse = JsonSerializer.Deserialize<TimeSeriesResponse>(responseJson);

            Console.WriteLine(JsonSerializer.Serialize(timeSeriesResponse));
        }
    }
}
```

Finally, run the example either from your IDE or from the command line.

## How to create a Postman collection for your Snowflake API

Below is a step-by-step guide on how to create a Postman collection for your new Snowflake API:

1. Open Postman and create a new collection.
2. Create a new request in the collection and name it "Snowflake API".
3. In the “Authorization” section of your collection, go to “Configure new Token” and follow these steps:
    1. Select Type as “OAuth 2.0”.
    2. Select Add auth data to “Request headers”.
    3. Header prefix: “Bearer”
    4. On “Configure New Token” add the following values:
        - Token name: `{{ $isoTimestamp }}`
        - Grant Type: “Client Credentials”
        - Access Token Token URL: [https://auth.us-east-2.propeldata.com/oauth2/token](https://auth.us-east-2.propeldata.com/oauth2/token)
        - Client ID: The Client ID from your Propel Application created in the Propel Console.
        - Client Secret: The Client secret from your Propel Application created in the Propel Console.
        - Scope: “metric:query”
        - Client Authentication: “Send as Basic Auth header”
    5. Make sure you have “Auto-refresh access token” enabled.
4. In the request URL field, enter the endpoint `https://api.us-east-2.propeldata.com/graphql`.
5. Select the "POST" method in the dropdown menu.
6. In the body of the request, select the "GraphQL" option from the dropdown menu.
7. In the query field, enter the GraphQL query:

```graphql
query TimeSeriesQuery($metricId: ID!, $input: TimeSeriesInput!) {
  metric(id: $metricId) {
    timeSeries(input: $input) {
      labels
      values
    }
  }
}
```

8. In the variables field, enter the variables:

```json
{
  "metricId": "METXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "input": {
    "granularity": "DAY",
    "timeRange": {
      "relative": "LAST_N_DAYS",
      "n": 30
    },
    "filters": [{
        "column": "PROMO",
        "operator": "EQUALS",
        "value": "FALSE"
      }]
  }
}
```

9. Save the request and run it to make the GraphQL request.

Here is the resulting Postman collection in JSON:

```json
{
	"info": 
		"_postman_id": "c316d428-0d89-49e5-bb21-990fae5e252a",
		"name": "Propel API",
		"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
		"_exporter_id": "15021803"
	},
	"item": [
		{
			"name": "Query Metric",
			"event": [
				{
					"listen": "test",
					"script": {
						"exec": [
							"",
							""
						],
						"type": "text/javascript"
					}
				}
			],
			"protocolProfileBehavior": {
				"strictSSL": true
			},
			"request": {
				"method": "POST",
				"header": [],
				"body": {
					"mode": "graphql",
					"graphql": {
						"query": "query TimeSeriesQuery($metricId: ID!, $input: TimeSeriesInput!) {\n  metric(id: $metricId) {\n    timeSeries(input: $input) {\n      labels\n      values\n    }\n  }\n}",
						"variables": "{\n  \"metricId\": \"METXXXXXXXXXXXXXXXXXXXXXXXXXX\",\n  \"input\": {\n    \"granularity\": \"DAY\",\n    \"timeRange\": {\n      \"relative\": \"LAST_N_DAYS\",\n      \"n\": 30\n    },\n    \"filters\": [{\n        \"column\": \"PROMO\",\n        \"operator\": \"EQUALS\",\n        \"value\": \"FALSE\"\n    }]\n  }\n}\n"
					}
				},
				"url": {
					"raw": "https://api.us-east-2.propeldata.com/graphql",
					"protocol": "https",
					"host": [
						"api",
						"us-east-2",
						"propeldata",
						"com"
					],
					"path": [
						"graphql"
					]
				}
			},
			"response": []
		}
	],
	"auth": {
		"type": "oauth2",
		"oauth2": [
			{
				"key": "clientSecret",
				"value": "{{clientSecret}}",
				"type": "string"
			},
			{
				"key": "clientId",
				"value": "{{clientID}}",
				"type": "string"
			},
			{
				"key": "tokenType",
				"value": "",
				"type": "string"
			},
			{
				"key": "accessToken",
				"value": "",
				"type": "string"
			},
			{
				"key": "scope",
				"value": "metric:query",
				"type": "string"
			},
			{
				"key": "accessTokenUrl",
				"value": "{{tokenURL}}",
				"type": "string"
			},
			{
				"key": "tokenName",
				"value": "{{$isoTimestamp}}",
				"type": "string"
			},
			{
				"key": "grant_type",
				"value": "client_credentials",
				"type": "string"
			},
			{
				"key": "addTokenTo",
				"value": "header",
				"type": "string"
			}
		]
	},
	"event": [
		{
			"listen": "prerequest",
			"script": {
				"type": "text/javascript",
				"exec": [
					""
				]
			}
		},
		{
			"listen": "test",
			"script": {
				"type": "text/javascript",
				"exec": [
					""
				]
			}
		}
	]
}
```


## Conclusion

In this post, we have explored the steps to build an API on top of your Snowflake data warehouse using Propel's Serverless Analytics API Platform. We have discussed why an API is necessary for customer-facing applications, the requirements for an API on top of Snowflake, and the five steps to build a Snowflake API: connect Snowflake, sync your tables, define Metrics, query the API, and build your data app.

Propel provides the infrastructure, scalability, and security required to power data applications while giving you the flexibility to define the metrics you want to query. Building an API on top of Snowflake with Propel is a fast, secure, and cost-effective way to power customer-facing web and mobile applications.

## How can I get started building data APIs for Snowflake with Propel?

You can get started with Propel by [reading the documentation](https://www.propeldata.com/docs). If you don't have your Propel Account yet, [book a demo](https://meetings.hubspot.com/propel/demo), and we can get you going!