Sending events

To start, make sure you have installed the Inngest SDK.

In order to send events, you'll need to instantiate the Inngest client. We recommend doing this in a single file and exporting the client so you can import it anywhere in your app. In production, you'll need an event key, which we'll cover below.


import { Inngest } from "inngest";

export const inngest = new Inngest({ id: "acme-storefront-app" }); // Use your app's ID

Now with this client, you can send events from anywhere in your app. You can send a single event, or multiple events at once.


import { inngest } from "../inngest/client";

// This sends an event to Inngest.
await inngest.send({
  // The event name
  name: "storefront/cart.checkout.completed",
  // The event's data
  data: {
    cartId: "ed12c8bde",
    itemIds: ["9f08sdh84", "sdf098487", "0fnun498n"],
    account: {
      id: 123,
      email: "",

👉 send() is an asynchronous method that returns a Promise. You should always use await or .then() to ensure that the method has finished sending the event to Inngest. Serverless functions can shut down very quickly, so skipping await may result in events failing to be sent.

Sending this event, named storefront/cart.checkout.completed, to Inngest will do two things:

  1. Automatically run any functions that are triggered by this specific event, passing the event payload to the function's arguments.
  2. Store the event payload in Inngest cloud. You can find this in the Events tab of the dashboard.

💡 One event can trigger multiple functions, enabling you to consume a single event in multiple ways. This is different than traditional message queues where only one worker can consume a single message. Learn about the fan-out approach here.

Setting an Event Key

In production, your application will need an "Event Key" to send events to Inngest. This is a secret key that is used to authenticate your application and ensure that only your application can send events to a given environment in your Inngest account.

You can learn how to create an Event Key here. Once you have a key, you can set it in one of two ways:

  1. Set an INNGEST_EVENT_KEY environment variable with your Event Key. This is the recommended approach.
  2. Pass the Event Key to the Inngest constructor as the eventKey option:


import { Inngest } from "inngest";

// NOTE - It is not recommended to hard-code your Event Key in your code.
const inngest = new Inngest({ id: "your-app-id", eventKey: "xyz..." });

Event keys are not required in local development with the Inngest Dev Server. You can omit them in development and your events will still be sent to the Dev Server.

Event payload format

The event payload is a JSON object that must contain a name and data property.

Required properties

  • The name is the type or category of event. Event names are used to trigger functions. For example, app/user.created or billing/invoice.paid. See tips for event naming below.
  • data contains any data you want to associate with the event. This data will be serialized to JSON. For example, if you're sending an event for a paid invoice, you might include the invoice's id, the amount, and the customerId in the data property. The data property can contain any nested JSON object, including objects and arrays.

Optional properties

  • user contains any relevant user-identifying data or attributes associated with the event. This data is encrypted at rest. For example, you might include the user's id, email, and name in the user property. The user property can contain any JSON object, including nested objects and arrays.
  • id is a unique identifier for the event used to prevent duplicate events. Learn more about deduplication.
  • ts is the timestamp of the event in milliseconds since the Unix epoch. If not provided, the timestamp will be set to the time the event was received by Inngest.
  • v is the event payload version. This is useful to track changes in the event payload shape over time. For example, "2024-01-14.1"
  "name": "billing/invoice.paid",
  "data": {
    "customerId": "cus_NffrFeUfNV2Hib",
    "invoiceId": "in_1J5g2n2eZvKYlo2C0Z1Z2Z3Z",
    "amount": 1000,
    "metadata": {
      "accountId": "acct_1J5g2n2eZvKYlo2C0Z1Z2Z3Z",
      "accountName": ""
  "user": {
    "email": ""

Tips for event naming

Event names are used to trigger functions. We recommend using a consistent naming convention for your events. This will make it easier to find and trigger functions in the future. Here are some tips for naming events:

  • Object-Action: Use an Object-Action pattern as represented by noun and a verb. This is great for grouping related events on a given object, account.created, account.updated, account.deleted.
  • Past-tense: Use a past-tense verb for the action. For example, uploaded, paid, completed, sent.
  • Separators: Use dot-notation and/or underscores to separate words. For example, user.created or blog_post.published.
  • Prefixes: Use prefixes to group related events. For example, api/user.created, billing/invoice.paid, stripe/customer.created. This is especially useful if you have multiple applications that send events to Inngest.

There is no right or wrong way to name events. The most important thing is to be consistent and use a naming convention that makes sense for your application.

Sending multiple events at once

You can also send multiple events in a single send() call. This enables you to send a batch of events very easily. You can send up to 512kb in a single request which means you can send anywhere between 10 and 1000 typically sized payloads at once. This is the default and can be increased for your account.

await inngest.send([
  { name: "storefront/cart.checkout.completed", data: { ... } },
  { name: "storefront/coupon.used", data: { ... } },
  { name: "storefront/loyalty.program.joined", data: { ... } },

This is especially useful if you have an array of data in your app and you want to send an event for each item in the array:

// This function call might return 10s or 100s of items, so we can use map
// to transform the items into event payloads then pass that array to send:
const importedItems = await api.fetchAllItems();
const events = => ({
  name: "storefront/item.imported",
  data: {
await inngest.send(events);

Sending events from within functions

You can also send events from within your functions using step.sendEvent() to, for example, trigger other functions. Learn more about sending events from within functions. Within functions, step.sendEvent() wraps the event sending request within a step to ensure reliable event delivery and prevent duplicate events from being sent. We recommend using step.sendEvent() instead of inngest.send() within functions.

export default inngest.createFunction(
  { id: "user-onboarding" },
  { event: "app/user.signup" },
  async ({ event, step }) => {
    // Do something
    await step.sendEvent("send-activation-event", {
      name: "app/user.activated",
      data: { userId: },
    // Do something else

Using Event IDs

Each event sent to Inngest is assigned a unique Event ID. These ids are returned from inngest.send() or step.sendEvent(). Event IDs can be used to look up the event in the Inngest dashboard or via the REST API. You can choose to log or save these Event IDs if you want to look them up later.

const { ids } = await inngest.send([
    name: "app/invoice.created",
    data: { invoiceId: "645e9e024befa68763f5b500" }
    name: "app/invoice.created",
    data: { invoiceId: "645e9e08f29fb563c972b1f7" }
 * ids = [
 * ]

Send events via HTTP (Event API)

You can send events from any system or programming language with our API and an Inngest Event Key. The API accepts a single event payload or an array of event payloads.

To send events from Python or Go applications, use our Python SDK or Go SDK.

To send an event to a specific branch environment, set the x-inngest-env header to the name of your branch environment, for example: x-inngest-env: feature/my-branch.

  -H 'Content-Type: application/json' \
  --data '{
    "name": "user.signup",
    "data": {
      "userId": "645ea8289ad09eac29230442"

The response will contain the ids of the events that were sent:


  "ids": ["01H08W4TMBNKMEWFD0TYC532GG"],
  "status": 200


Often, you may need to prevent duplicate events from being processed by Inngest. If your system could possibly send the same event more than once, you will want to ensure that it does not run functions more than once.

To prevent duplicate function runs from events, you can add an id parameter to the event payload. Once Inngest receives an event with an id, any events sent with the same id will be ignored, regardless of the event's payload.

await inngest.send({
  // Your deduplication id must be specific to this event payload.
  // Use something that will not be used across event types, not a generic value like cartId
  id: "cart-checkout-completed-ed12c8bde",
  name: "storefront/cart.checkout.completed",
  data: {
    cartId: "ed12c8bde",
    // ...the rest of the payload's data...

Learn more about this in the handling idempotency guide.

💡 Deduplication prevents duplicate function runs for 24 hours from the first event.

The id is global across all event types, so make sure your id isn't a value that will be shared across different event types.

For example, for two events like storefront/item.imported and storefront/item.deleted, do not use the item's id (9f08sdh84) as the event deduplication id. Instead, combine the item's id with the event type to ensure it's specific to that event (e.g. item-imported-9f08sdh84).

Further reading