Tasks

Define background tasks that are triggered via fan-out, programmatically from your code, or manually from the dashboard.

API

task(name: string, handler: Function, options?: Options)

name — unique identifier for this task.

handler — async function receiving context and payload.

options — optional retries, timeout, concurrency (same as cron).

Defining a Task

Tasks are defined the same way as crons, but without a schedule. They receive a payload as the second argument:

import { task } from "@usepingback/next";

export const sendEmail = task(
  "send-email",
  async (ctx, { id }: { id: string }) => {
    const email = await getEmail(id);
    await deliver(email);
    ctx.log(`Sent email to ${email.to}`);
  },
  { retries: 2, timeout: "15s" }
);

Fan-Out Pattern

Use ctx.task() inside a cron to dispatch independent sub-tasks. Each task runs with its own retries, timeout, and tracking:

import { cron, task } from "@usepingback/next";

// Parent cron — runs every 15 minutes
export const sendEmails = cron(
  "send-emails",
  "*/15 * * * *",
  async (ctx) => {
    const pending = await getPendingEmails();

    for (const email of pending) {
      await ctx.task("send-email", { id: email.id });
    }

    ctx.log(`Dispatched ${pending.length} emails`);
    return { dispatched: pending.length };
  }
);

// Child task — runs independently per email
export const sendEmail = task(
  "send-email",
  async (ctx, { id }: { id: string }) => {
    const email = await getEmail(id);
    await deliver(email);
    ctx.log(`Sent email to ${email.to}`);
  },
  { retries: 2, timeout: "15s" }
);

How Fan-Out Works

1. The cron handler calls ctx.task("send-email", payload) which collects the task request in memory.

2. When the cron handler finishes, the SDK returns the collected tasks in the response.

3. The platform creates a child execution for each task, linked to the parent.

4. Each child task is dispatched independently via the queue with its own retry policy.

5. Child tasks appear nested under the parent execution in the dashboard.

Programmatic Triggering

Use PingbackClient to trigger tasks from your own code — no cron schedule or fan-out required. This is useful for event-driven workflows like sending a welcome email after signup, processing a webhook, or kicking off a pipeline from an API route.

import { PingbackClient } from "@usepingback/next";

const pingback = new PingbackClient({
  apiKey: process.env.PINGBACK_API_KEY!,
});

// Trigger a task from anywhere in your app
const { executionId } = await pingback.trigger("send-email", {
  to: "user@example.com",
  subject: "Welcome!",
});

console.log("Triggered execution:", executionId);

NestJS

In NestJS, PingbackClient is an injectable service — just add it to your constructor:

import { Injectable } from '@nestjs/common';
import { PingbackClient } from '@usepingback/nestjs';

@Injectable()
export class AuthService {
  constructor(private readonly pingback: PingbackClient) {}

  async register(email: string, password: string) {
    const user = await this.createUser(email, password);

    // Trigger the onboarding email task
    const { executionId } = await this.pingback.trigger(
      "send-onboarding-email",
      { userId: user.id },
    );

    return user;
  }
}

API Reference

const client = new PingbackClient(options);
const { executionId } = await client.trigger(taskName, payload?);
ParameterTypeDescription
options.apiKeystringYour Pingback API key.
options.platformUrlstring?Defaults to https://api.pingback.lol.
taskNamestringName of a registered task in your project.
payloadany?Optional JSON payload passed to the task handler.

Returns { executionId: string }. Throws if the task name doesn't exist in your project or the API key is invalid.

Note: Tasks can also be triggered manually from the Pingback dashboard. Navigate to your task in the dashboard and click "Run" to dispatch it with a custom payload — useful for testing and one-off executions.