Documentation
Query the database
API functions

API functions

API functions are user-defined TypeScript functions that handle web requests. You can use them to customize the API layer of your app with complex SQL queries, authentication, data from external sources, and more.

API functions are built on top of Hono, a fast and lightweight routing framework.

Example projects

These example apps demonstrate how to use API functions.

  • Basic - An ERC20 app that responds to GET requests and uses Drizzle to build custom SQL queries.
  • tRPC - An app that creates a tRPC server and a script that uses a tRPC client with end-to-end type safety.

Get started

Upgrade to >=0.5.0

API functions are available starting from version 0.5.0. Read the migration guide for more details.

Create src/api/index.ts file

To enable API functions, create a file named src/api/index.ts with the following code. You can register API functions in any .ts file in the src/api/ directory.

src/api/index.ts
import { Hono } from "hono";
 
const app = new Hono();
 
app.get("/hello", (c) => {
  return c.text("Hello, world!");
});
 
export default app;

Send a request

Visit http://localhost:42069/hello in your browser to see the response.

Response
Hello, world!

Register GraphQL middleware

⚠️

Starting from version 0.9.0, API functions are required and no GraphQL API is served by default.

To use the standard GraphQL API, register the graphql middleware exported from ponder. Read more about GraphQL in Ponder.

src/api/index.ts
import { db } from "ponder:api";
import schema from "ponder:schema";
import { Hono } from "hono";
import { graphql } from "ponder";
 
const app = new Hono();
 
app.use("/", graphql({ db, schema }));
app.use("/graphql", graphql({ db, schema }));
 
export default app;

Query the database

The API function context includes a ready-to-use Drizzle database client exported from ponder:api. To query the database, import table objects from ponder:schema and pass them to db.select() or use relational queries.

Select

Here's a simple query using the Drizzle select query builder.

src/api/index.ts
import { db } from "ponder:api";
import schema from "ponder:schema";
import { Hono } from "hono";
 
const app = new Hono();
 
app.get("/account/:address", async (c) => {
  const address = c.req.param("address");
 
  const account = await db
    .select()
    .from(schema.accounts)
    .where(eq(schema.accounts.address, address))
    .limit(1);
 
  return c.json(account);
});
 
export default app;

To build more complex queries, use join, groupBy, where, orderBy, limit, and other methods. Drizzle's filter & conditional operators (like eq, gte, and or) are re-exported by ponder. Visit the Drizzle documentation for more details.

Relational queries

Drizzle's relational query builder (AKA Drizzle Queries) offers a great developer experience for complex queries. The db.query object exposes the raw Drizzle relational query builder.

Here's an example that uses the relational query builder in an API function to find the 10 largest trades in the past hour joined with the account that made the trade. Visit the Drizzle Queries documentation for more details.

src/api/index.ts
import { db } from "ponder:api";
import { accounts, tradeEvents } from "ponder:schema";
import { Hono } from "hono";
import { eq, and, gte, inArray, sql } from "drizzle-orm";
 
const app = new Hono();
 
app.get("/hot-trades", async (c) => {
  const trades = await db.query.tradeEvents.findMany({
    where: (table, { gt, gte, and }) =>
      and(
        gt(table.amount, 1_000n),
        gte(table.timestamp, Date.now() - 1000 * 60 * 60)
      ),
    limit: 10,
    with: { account: true },
  });
 
  return c.json(trades);
});
 
export default app;

Reserved routes

If you register API functions that conflict with these internal routes, the build will fail.

  • /health: Returns a 200 status code immediately after the app starts running. Read more about healthchecks.
  • /ready: Returns a 200 status code after the app has completed the historical backfill and is available to serve traffic. Read more about heatlthchecks.
  • /metrics: Returns Prometheus metrics. Read more about metrics.
  • /status: Returns indexing status object. Read more about indexing status.