Skip to main content

Overview

ConvexHttpClient is a stateful client that runs queries and mutations over HTTP instead of WebSocket. This is appropriate for server-side code (like serverless functions, API routes, or backend services) or non-reactive web applications.
This client is stateful (it has user credentials and queues mutations), so take care to avoid sharing it between requests in a server. Create a new instance per request when using in server-side code.

Constructor

Create a new ConvexHttpClient instance.
import { ConvexHttpClient } from "convex/browser";

const client = new ConvexHttpClient(process.env.CONVEX_URL);

Parameters

address
string
required
The URL of your Convex deployment, often provided by an environment variable. For example: https://small-mouse-123.convex.cloud
options
object
Optional configuration object for the client.

Methods

query

Execute a Convex query function.
const messages = await client.query(
  api.messages.list,
  { channel: "#general" }
);
query
FunctionReference<'query'>
required
A function reference for the public query to run, like api.dir1.dir2.filename.func.
args
object
An arguments object for the query. If omitted, the arguments will be {}.
Returns: A promise of the query’s result.

mutation

Execute a Convex mutation function. Mutations are queued by default.
const taskId = await client.mutation(
  api.tasks.create,
  { text: "New task", completed: false }
);
mutation
FunctionReference<'mutation'>
required
A function reference for the public mutation to run.
args
object
An arguments object for the mutation. If omitted, the arguments will be {}.
options
HttpMutationOptions
Returns: A promise of the mutation’s result.
By default, mutations are queued and executed sequentially. This ensures mutations are applied in order. Set skipQueue: true to execute mutations in parallel.

action

Execute a Convex action function. Actions are not queued.
const summary = await client.action(
  api.ai.generateSummary,
  { text: "Some long text..." }
);
action
FunctionReference<'action'>
required
A function reference for the public action to run.
args
object
An arguments object for the action. If omitted, the arguments will be {}.
Returns: A promise of the action’s result.

setAuth

Set the authentication token to be used for subsequent queries and mutations.
const token = await getAuthToken();
client.setAuth(token);
value
string
required
JWT-encoded OpenID Connect identity token.
Should be called whenever the token changes (e.g., due to expiration and refresh).

clearAuth

Clear the current authentication token if set.
client.clearAuth();

Properties

url

Return the address for this client.
const deploymentUrl = client.url;
Returns: The Convex deployment URL as a string.
Not guaranteed to match the address used in the constructor as it may be canonicalized.

Example usage

Basic usage in a serverless function

import { ConvexHttpClient } from "convex/browser";
import { api } from "../convex/_generated/api";

export async function handler(request) {
  const client = new ConvexHttpClient(process.env.CONVEX_URL);
  
  // Fetch data
  const tasks = await client.query(api.tasks.list, {});
  
  // Create a new task
  const newTaskId = await client.mutation(api.tasks.create, {
    text: "New task from API",
    completed: false
  });
  
  return {
    statusCode: 200,
    body: JSON.stringify({ tasks, newTaskId })
  };
}

With authentication

import { ConvexHttpClient } from "convex/browser";
import { api } from "../convex/_generated/api";

export async function handler(request) {
  const client = new ConvexHttpClient(process.env.CONVEX_URL);
  
  // Extract JWT from request headers
  const authToken = request.headers.authorization?.replace("Bearer ", "");
  
  if (authToken) {
    client.setAuth(authToken);
  }
  
  // Now queries and mutations run with the authenticated user's context
  const userTasks = await client.query(api.tasks.listMine, {});
  
  return {
    statusCode: 200,
    body: JSON.stringify({ tasks: userTasks })
  };
}

Parallel mutations with skipQueue

import { ConvexHttpClient } from "convex/browser";
import { api } from "../convex/_generated/api";

const client = new ConvexHttpClient(process.env.CONVEX_URL);

// Execute mutations in parallel
const results = await Promise.all([
  client.mutation(api.tasks.create, { text: "Task 1" }, { skipQueue: true }),
  client.mutation(api.tasks.create, { text: "Task 2" }, { skipQueue: true }),
  client.mutation(api.tasks.create, { text: "Task 3" }, { skipQueue: true })
]);

Next.js API route

import type { NextApiRequest, NextApiResponse } from "next";
import { ConvexHttpClient } from "convex/browser";
import { api } from "../../convex/_generated/api";

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse
) {
  const client = new ConvexHttpClient(process.env.CONVEX_URL!);
  
  if (req.method === "GET") {
    const tasks = await client.query(api.tasks.list, {});
    return res.status(200).json({ tasks });
  }
  
  if (req.method === "POST") {
    const { text } = req.body;
    const taskId = await client.mutation(api.tasks.create, {
      text,
      completed: false
    });
    return res.status(201).json({ taskId });
  }
  
  return res.status(405).json({ error: "Method not allowed" });
}

Comparison with ConvexReactClient

FeatureConvexHttpClientConvexReactClient
TransportHTTPWebSocket
Use caseServer-side, API routesReact applications
ReactivityNo (one-time fetch)Yes (automatic updates)
Mutation queuingYes (configurable)Yes
React hooksNoYes
SubscriptionsNoYes
Use ConvexHttpClient for server-side code and ConvexReactClient for React applications. If you need to use Convex in a non-React frontend, consider using ConvexHttpClient with polling or use the WebSocket-based BaseConvexClient (advanced usage).

Build docs developers (and LLMs) love