DEV Community

Alex Spinov
Alex Spinov

Posted on

Zodios Has a Free API — End-to-End Type-Safe REST Client with Zod

Zodios is a type-safe REST API client that uses Zod schemas. Define your API once with Zod schemas — get a fully typed client with autocompletion, runtime validation, and OpenAPI generation.

Why Zodios?

  • Zod-powered — same schema validates AND types
  • Auto-completion — paths, params, body, response — all typed
  • Runtime validation — responses validated against schema
  • OpenAPI — generate docs from your definitions

Quick Start

npm install @zodios/core zod
Enter fullscreen mode Exit fullscreen mode
import { makeApi, Zodios } from '@zodios/core';
import { z } from 'zod';

const userSchema = z.object({
  id: z.number(),
  name: z.string(),
  email: z.string().email(),
});

const api = makeApi([
  {
    method: 'get',
    path: '/users',
    alias: 'getUsers',
    response: z.array(userSchema),
  },
  {
    method: 'get',
    path: '/users/:id',
    alias: 'getUser',
    response: userSchema,
  },
  {
    method: 'post',
    path: '/users',
    alias: 'createUser',
    parameters: [{
      name: 'body',
      type: 'Body',
      schema: z.object({
        name: z.string(),
        email: z.string().email(),
      }),
    }],
    response: userSchema,
  },
]);

const client = new Zodios('https://api.example.com', api);

// Fully typed!
const users = await client.getUsers();
const user = await client.getUser({ params: { id: 1 } });
const newUser = await client.createUser({ name: 'Alice', email: 'a@b.com' });
Enter fullscreen mode Exit fullscreen mode

React Integration

npm install @zodios/react
Enter fullscreen mode Exit fullscreen mode
import { ZodiosHooks } from '@zodios/react';

const hooks = new ZodiosHooks('users', client);

function UserList() {
  const { data: users, isLoading } = hooks.useGetUsers();
  const { mutate: createUser } = hooks.useCreateUser();

  return (
    <div>
      {users?.map(u => <p key={u.id}>{u.name}</p>)}
      <button onClick={() => createUser({ name: 'Bob', email: 'bob@test.com' })}>
        Add User
      </button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Express Server

npm install @zodios/express
Enter fullscreen mode Exit fullscreen mode
import { zodiosApp } from '@zodios/express';

const app = zodiosApp(api);

app.get('/users', async (req, res) => {
  const users = await db.getUsers();
  res.json(users); // Response validated against Zod schema
});

app.post('/users', async (req, res) => {
  // req.body is validated and typed!
  const user = await db.createUser(req.body);
  res.json(user);
});
Enter fullscreen mode Exit fullscreen mode

Building type-safe APIs? Check out my Apify actors for structured data, or email spinov001@gmail.com for custom API solutions.

Zodios, tRPC, or plain fetch — how do you call APIs? Share below!

Top comments (0)