Send events
Start durable work by sending events from your app or a function.
Send an event when an app action should start a durable function. Await the send call so the process stays alive until Inngest accepts the event.
Create a client
Create the Inngest client once, in its own file, and import it wherever you send events.
import { Inngest } from "inngest";
export const inngest = new Inngest({ id: "acme-storefront-app" }); // Use your app's ID
Send one event
import { Inngest } from "inngest";
const inngest = new Inngest({ id: "billing-app" });
const { ids } = await inngest.send({
name: "billing/invoice.paid",
data: { invoiceId: "inv_123", customerId: "cus_456" },
});
The returned event ID lets you find the event in the dashboard. A matching trigger starts its function. One event may start several functions. Unlike a traditional message queue, where one worker consumes each message, every function that matches the event runs. See Fan-out.
Inngest also stores each event. You can find it in the Events tab of the dashboard.
The same send in each SDK:
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: "test@example.com",
},
},
});
In TypeScript, send() returns a Promise. Always use await or .then(). Serverless functions can shut down quickly, and an unawaited send may never reach Inngest.
In Python, send() is async, so call it with await. In synchronous code, use send_sync() instead.
Every event needs a name and a data object. Event payloads and schemas covers the optional fields.
Set an Event Key in production
In production, your app needs an Event Key to send events. The key authenticates your app and routes events to one environment in your Inngest account. See Keys and access to create one.
Set the key in one of two ways:
- Set the
INNGEST_EVENT_KEYenvironment variable. This is the recommended approach. - Pass the key to the client constructor. Avoid hard-coding keys in your code.
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..." });
You don't need an Event Key in local development. Events go to the Inngest Dev Server without one.
Send from a function
Use step.sendEvent() inside a durable function. This records the send as a step and prevents replay of that completed step from sending the event again. Use it instead of inngest.send() inside functions. In Python, use step.send_event(). See step.sendEvent() for details.
await step.sendEvent("notify-accounting", {
name: "billing/invoice.paid",
data: { invoiceId: event.data.invoiceId },
});
A full function in each SDK:
export default inngest.createFunction(
{ id: "user-onboarding", triggers: { event: "app/user.signup" } },
async ({ event, step }) => {
// Do something
await step.sendEvent("send-activation-event", {
name: "app/user.activated",
data: { userId: event.data.userId },
});
// Do something else
}
);
Send typed events
Define a name and schema with eventType(), then use .create() to build a typed payload. Event payloads and schemas shows the schema and send example. Use a runtime schema when incoming data needs validation; staticSchema() provides TypeScript checking without runtime validation.
Send a batch
Pass an array to inngest.send() to send several events in one call. Services without an SDK can send events through the HTTP Event API.
await inngest.send([
{ name: "storefront/cart.checkout.completed", data: { /* ... */ } },
{ name: "storefront/coupon.used", data: { /* ... */ } },
{ name: "storefront/loyalty.program.joined", data: { /* ... */ } },
])
Batch requests have size limits. See Platform limits for the maximum number of events per send request.
A batch that only partly succeeds reports the accepted events.
Batches suit lists of records. Map each item to an event, then send 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 = importedItems.map((item) => ({
name: "storefront/item.imported",
data: {
...item,
}
}));
await inngest.send(events);
Use event IDs
Inngest gives each event a unique ID. inngest.send(), step.sendEvent() and Go's client.SendMany() return these IDs. Log or save them to look up events later in the dashboard or through the REST API.
const { ids } = await inngest.send([
{
name: "app/invoice.created",
data: { invoiceId: "645e9e024befa68763f5b500" }
},
{
name: "app/invoice.created",
data: { invoiceId: "645e9e08f29fb563c972b1f7" }
},
]);
/**
* ids = [
* "01HQ8PTAESBZPBDS8JTRZZYY3S",
* "01HQ8PTFYYKDH1CP3C6PSTBZN5"
* ]
*/
Prevent duplicate starts
Set a unique event id when the sender may retry the same action. The id acts as an idempotency key. When an event is sent again with the same id within 24 hours, the event is still stored, but no new run executes. See Idempotency for event and function idempotency.
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...
}
});
The id is global across all event types. Make it specific to one event type. For example, storefront/item.imported and storefront/item.deleted should not both use the item's ID (9f08sdh84). Combine the ID with the event type instead, such as item-imported-9f08sdh84.
Send events over HTTP
Send events from any language or system with the Event API and an Event Key. The API accepts one event payload or an array of them.
curl -X POST https://inn.gs/e/$INNGEST_EVENT_KEY \
-H 'Content-Type: application/json' \
--data '{
"name": "user.signup",
"data": {
"userId": "645ea8289ad09eac29230442"
}
}'
The response contains the IDs of the events you sent:
{
"ids": ["01H08W4TMBNKMEWFD0TYC532GG"],
"status": 200
}
To send to a branch environment, set the x-inngest-env header to its name, for example x-inngest-env: feature/my-branch.
With the Dev Server, send to http://localhost:8288/e/<fake-key>. If you self-host, use your instance's URL instead.