---
title: "Adding AI Magic To Your Firestore API"
description: "Ride the AI wave with your Firestore API"
canonicalUrl: "https://zuplo.com/blog/2024/07/12/adding-ai-to-firestore-api"
pageType: "blog"
date: "2024-07-12"
authors: "josh"
tags: "Firestore, Tutorial"
image: "https://zuplo.com/og?text=Adding%20Gemini%20%AI20to%20your%20Firestore%20API"
---
Welcome to the final day of Firebase Week! No tutorial written in 2024 is
complete without a touch of AI magic, so that's precisely what we will do in
this last part. By the end of this tutorial, we will have an AI-infused API that
leverages Google Gemini to summarize our to-do list.

Before we get started, you’ll need to make sure you have the following
prerequisites in place:

- Basic understanding of Firestore and REST APIs
- [Firestore API set up as per Firebase Day 1](/blog/zuplo-plus-firebase-creating-a-simple-crud-api)
- [API key authentication set up using Zuplo, covered in Firebase Day 2](/blog/zuplo-plus-firebase-adding-api-key-auth)
- [Zuplo Developer Portal enabled, covered in Firebase Day 3](/blog/adding-dev-portal-and-request-validation-firebase)
- [Monetization implemented through Zuplo, covered in Firebase Day 4](/blog/adding-monetization-capabilities-to-firestore)

With those checked off, we can wrap up the last part of this series by creating
a new **Get Summary** endpoint.

<YouTubeVideo videoId="CLV2RCBvEYU" />

## Create a Get Summary Endpoint

The first thing on our agenda is creating the **Get summary** endpoint. The AI
logic will be accessible through the **/v1/summary** endpoint that will generate
a summary by feeding the todos saved in Firestore into Gemini. To set up our
endpoint, Under the **Code** section in Zuplo, open up the **routes.oas.json**
file, and on the **Route Designer,** we will:

1. Click **Add Route**.
2. Set the **Summary** as “Get summary”
3. Set the **Path** as “/v1/summary”
4. Set the **Method** as “GET”
5. Set **CORS** as “Anything Goes”
6. In the **Request Handler** section, we will:
   1. Set the **Handler** as “Function”.
   2. Click the **Function** dropdown and select **New Module**.
   3. Set the new module's name as “summary”.
   4. Click **Create**.

The **summary.ts** file will now be added underneath the **modules** directory
in the side menu. Open the file and paste in the following code:

```typescript
import { environment, ZuploContext, ZuploRequest } from "@zuplo/runtime";

export default async function (request: ZuploRequest, context: ZuploContext) {
  const firestoreUrl = `https://firestore.googleapis.com/v1/projects/${environment.PROJECT_ID}/databases/(default)/documents:runQuery`;

  const query = {
    structuredQuery: {
      from: [
        {
          collectionId: "todos",
        },
      ],
      where: {
        fieldFilter: {
          field: {
            fieldPath: "userId",
          },
          op: "EQUAL",
          value: {
            stringValue: request.user.sub,
          },
        },
      },
    },
  };

  context.log.info(query, firestoreUrl);

  // Query Firestore
  const todosResponse = await fetch(firestoreUrl, {
    method: "POST",
    headers: request.headers,
    body: JSON.stringify(query),
  });

  const todosJson = await todosResponse.json();

  context.log.info(todosJson);

  // Collate results
  const todos = todosJson.map(
    (doc) => doc.document.fields.description.stringValue,
  );

  const prompt = {
    contents: [
      {
        parts: [
          {
            text: `Here are some tasks: '${todos.join(", ")}'. Write a funny one-sentence summary. Make me laugh`,
          },
        ],
      },
    ],
  };

  // Send request to Gemini
  const geminiResponse = await fetch(
    `https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=${environment.GEMINI_API_KEY}`,
    {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify(prompt),
    },
  );

  if (!geminiResponse.ok) {
    throw new Error(`Gemini request failed: ${geminiResponse.status} - ${geminiResponse.statusText}


${await geminiResponse.text()}`);
  }
  const geminiData = await geminiResponse.json();

  // Extract summary from Gemini's response
  const summary = geminiData.candidates[0].content.parts[0].text.trim();

  // Send response
  return { response: summary };
}
```

The code above does the following:

**Fetch User's Todos**

- Retrieves the user's unique ID from the request.
- Constructs a query to fetch the user's "todos" from Firestore.
- Executes the query against the Firestore API.

**Prepare for Gemini**

- Extracts the todo descriptions from the Firestore results.
- Creates a prompt for the Gemini AI model, asking for a funny one-sentence
  summary of the todos.

**Generate Summary**

- Sends the prompt to the Gemini API.
- Handles potential errors in the Gemini response.

**Return Summary**

- Extracts the generated summary from Gemini's response.
- Sends the summary back as the final response.

With the code plugged into the **summary.ts** file, click **Save** in the bottom
left corner to save the updated function and endpoint and deploy it to the
gateway and developer portal.

Before wrapping up the endpoint, we must add the necessary policies to the
request pipeline. For this, we will:

1. Go back to the routes.oas.json file and open up the Route Designer.
2. Open the **Get summary** endpoint.
3. Expand the **Policies** section, and under **Requests,** click **Add
   Policy**.
4. In the modal that appears, under **Existing Policies**, select:
   - **api-key-inbound**
   - **upstream-firebase-admin-auth-inbound**
   - **monetize-requests**
5. Click **Save** in the bottom-left of the screen to save the updated endpoint.

Adding these policies will help us secure the API by API key, connect the
Firebase API, and monetize the endpoint by incrementing the **Requests** meter
we created in part 4 of this series. After everything is plugged in as specified
above, the endpoint will look like this in the endpoint designer.

![Zuplo route designer](/media/posts/2024-07-12-adding-ai-to-firestore-api/image-1.png)

Since our **summary.ts** file depends on a Gemini API key, we will need to plug
that into our Zuplo instance next.

## Add Your Gemini API Key Environment Variable

_Make sure to grab a
[Gemini API key](https://ai.google.dev/gemini-api/docs/api-key) before
proceeding._

Similar to how we’ve added other environment variables in Zuplo, we will add the
Gemini API key. To add the key to an environment variable, we will do the
following:

1. While in Zuplo, click on **Settings** in the header menu.
2. On the **Settings** screen, select **Environment Variables** from the
   left-side menu.
3. Click **Add Variable.**
4. In the modal that appears, set the **Name** field as “GEMINI_API_KEY” and the
   **Value** field with your Gemini API key.
5. Check the **Secret** checkbox off.
6. Click **Save**.

Here’s an example of what your environment variable configuration will look like
before submitting it.

![setting the api key environment variable](/media/posts/2024-07-12-adding-ai-to-firestore-api/image-2.png)

With the endpoint created and our API key plugged in for Gemini, let’s give this
new endpoint a go!

## Test The New Endpoint Via The Developer Portal

Similar to other tests we’ve run, let's log back into the Zuplo Developer Portal
and test things out from there.

To test this endpoint, log in to the Developer Portal, go to the **Get summary**
endpoint in the developer docs, and click the **Test** button on the example.

![testing the gemini API in Zuplo docs](/media/posts/2024-07-12-adding-ai-to-firestore-api/image-3.png)

In the **API Playground** modal, click the **Test** button to send off a
request. The returned response should contain a somewhat ridiculous summary of
your tasks for your user, powered by Gemini.

![Zuplo docs API playground](/media/posts/2024-07-12-adding-ai-to-firestore-api/image-4.png)

True to 2024, you now have a Firestore API infused with AI via Google’s Gemini
API.

## Conclusion

Just like that, we’ve finished our five-day, five-tutorial series on using Zuplo
and Firestore to create production-ready APIs in minutes. In this series, we
have covered how to build APIs on top of Firebase, secure and monetize them with
Zuplo, and use AI to create dynamic responses based on data within our Firestore
instance.

Ready to try this out for yourself? Sign up for Zuplo today to build and secure
APIs with developer-first API management.

Check out the [day 5 video walk-through](https://youtu.be/CLV2RCBvEYU).