RobotRock

Webhooks

RobotRock can notify your application when a task is handled via webhooks.

Configure webhook on the client

Set webhook on createClient in your shared client module. It applies to every action when you call sendToHuman:

// lib/robotrock.ts
import { createClient } from "robotrock";

export const robotrock = createClient({
  app: "my-service",
  webhook: {
    url: "https://your-app.com/api/robotrock/webhook",
    headers: {
      // place your headers here
    },
  },
});
import { robotrock } from "@/lib/robotrock";

const response = await robotrock.sendToHuman({
  type: "approval",
  name: "Budget Approval",
  actions: [
    { id: "approve", title: "Approve" },
    { id: "reject", title: "Reject" },
  ],
});

headers is optional and defaults to {}.

Set app on createClient to control dashboard inbox grouping. When omitted, tasks use your API key name.

Webhook Payload

When a task is handled, RobotRock sends a POST request to your webhook URL:

{
  "taskId": "task_123abc",
  "action": {
    "id": "approve",
    "title": "Approve",
    "data": {
      "notes": "Looks good!"
    }
  },
  "handledBy": "user@example.com",
  "handledAt": "2024-01-15T10:30:00Z",
  "handlerType": "webhook"
}

Next.js API route example

Use a Route Handler in your Next.js app to receive webhook events:

// app/api/robotrock/webhook/route.ts
import { NextResponse } from "next/server";
import {
  verifyRobotRockWebhook,
  RobotRockWebhookError,
  type RobotRockWebhookPayload,
} from "robotrock";

export async function POST(req: Request) {
  let payload: RobotRockWebhookPayload;
  try {
    payload = await verifyRobotRockWebhook(req);
  } catch (error) {
    if (error instanceof RobotRockWebhookError) {
      // Use `error.code` in your own audit logs and monitoring.
      return NextResponse.json({ error: error.code }, { status: 401 });
    }
    return NextResponse.json({ error: "Unknown error" }, { status: 500 });
  }

  if (payload.action.id === "approve") {
    // TODO: run your approved flow
  } else if (payload.action.id === "reject") {
    // TODO: run your rejection flow
  }

  // Request headers are included in payload.headers
  console.log("RobotRock request id:", payload.headers["x-request-id"]);

  return NextResponse.json({ ok: true });
}

Audit Trail

Each webhook execution creates an audit log entry with:

  • Handler type (webhook)
  • URL called
  • HTTP status code
  • Success/failure status
  • Error message (if failed)
  • Response time in milliseconds

Verifying Webhooks

Use the SDK helper instead of implementing crypto verification yourself:

import { verifyRobotRockWebhook } from "robotrock";

const payload = await verifyRobotRockWebhook(request);

verifyRobotRockWebhook():

  • validates x-robotrock-signature
  • reads ROBOTROCK_WEBHOOK_SECRET
  • parses and validates required payload fields
  • returns typed payload data including request headers
  • throws RobotRockWebhookError with machine-readable error codes

Webhook signing secret

You must set ROBOTROCK_WEBHOOK_SECRET in your app environment. For example in Next.js:

# .env.local
ROBOTROCK_WEBHOOK_SECRET=rrwhsec_your_shared_secret

Create or rotate this secret in the RobotRock app from your workspace settings where webhook secrets are managed, then update your deployment env vars to match.

Trigger.dev Integration

When you use the Trigger.dev tasks in the SDK, you do not need to configure a client webhook yourself. sendToHumanTask creates a wait token and sets the token URL as the client webhook automatically.

Vercel Workflow Integration

When you use sendToHumanInWorkflow, the SDK creates a workflow webhook and sets webhook.url as the RobotRock handler URL automatically. See Vercel Workflow.

No webhook?

If you omit webhook on createClient, sendToHuman() blocks and polls the API until the task is handled. You cannot set webhook and polling on the same client. See Polling for intervalMs, timeoutMs, and error handling.

On this page