Tutorial

Connect your app

Make your own product controllable by a worker. Two directions you can mix and match: outbound (a worker calls your API) and inbound (your app triggers a worker).

How it works

  • Outbound — a Generic API connection lets a bound worker call your app's HTTP API (publish content, update a ticket, …) via its api_request tool. Calls are SSRF-guarded by a host allowlist; your credentials are encrypted at rest.
  • Inbound — a Webhook connection gives you a signed endpoint URL. Your app POSTs an event and it becomes a task for the bound worker.

Safety

Worker writes still honor the worker's autonomy level — actions against your app are approval-gated unless the worker is set to auto-execute. SSRF protection blocks private/internal addresses.

Tutorial 1 — let a worker manage your website

Connect your site's API and bind it to a worker:

import { CreateWorker } from "@createworker/sdk";
const cw = new CreateWorker({ apiKey: process.env.CREATEWORKER_API_KEY! });

const conn = await cw.integrations.createApiConnection({
  displayName: "My portfolio",
  baseUrl: "https://api.myportfolio.com",
  allowedHosts: ["api.myportfolio.com"],   // SSRF allowlist (required)
  authMode: "bearer",
  bearerToken: process.env.MY_PORTFOLIO_TOKEN!,
});

await cw.integrations.bind({ workerId: "wrk_…", connectionId: conn.id, purpose: "OUTBOUND" });

Help the worker discover your endpoints by uploading your API reference to its knowledge:

await cw.knowledge.create({
  title: "Portfolio API",
  content: "POST /projects { title, body, coverImageUrl } — create a project. PATCH /projects/{id} …",
});

Now a task can act on your site — the worker emits api_request calls against your API:

const task = await cw.tasks.create({
  workerId: "wrk_…",
  title: "Publish a new project called 'Aurora' with a short write-up about the redesign.",
});
const done = await cw.tasks.waitForTask(task.id);
if (done.status === "PROPOSED") await cw.approvals.create(task.id, { decision: "APPROVE" });

Tutorial 2 — let your app trigger a worker

Create a webhook connection and bind it (inbound):

const wh = await cw.integrations.createWebhookConnection({
  displayName: "Helpdesk",
  inbound: { authMode: "signature", generateSecret: true },
});
await cw.integrations.bind({ workerId: "support_…", connectionId: wh.id, purpose: "INBOUND" });

// Store these (shown once):
//   wh.inbound.endpointUrl   → where your app POSTs events
//   wh.signingSecret         → to HMAC-sign those requests

From your app, POST a signed event when something happens — it becomes a task:

import { signInboundRequest } from "@createworker/sdk";

const { body, headers } = signInboundRequest(
  {
    externalId: "ticket-123",            // idempotency key
    type: "ticket.created",
    task: { title: "New ticket #123", description: "Customer can't reset their password." },
    payload: { ticketId: "123", email: "[email protected]" },
  },
  process.env.CW_INBOUND_SECRET!,        // = wh.signingSecret
);

await fetch(endpointUrl, { method: "POST", headers, body });

Tutorial 3 — the full helpdesk loop

Bind one support worker to both connections (use purpose: "BOTH", or bind the webhook INBOUND and the Generic API OUTBOUND). A new ticket webhook creates a task → the worker drafts a reply → it posts the reply back to your helpdesk with an api_request call. With approvals on, you review each reply before it sends; with auto-execute, it runs unattended.

Same pattern, any app

The same two primitives connect a CMS, a CRM, an internal admin panel, or any HTTP API. Scope the connection to just the hosts and credentials the worker needs.

Reference

See the SDK page for all integrations.* methods, or the API reference for POST /v1/integrations/connections.