Define triggers and actions for the Bondi automation engine — bring your own API into Bondi workflows.
| Resource | Link |
|---|---|
| 📚 API Reference | integration-sdk.heybondi.com |
| 🚀 Examples | github.com/heybondi/integration-sdk-examples |
| 📝 Changelog | CHANGELOG.md |
| 🐛 Issues | github.com/heybondi/monorepo/issues |
npm install @bondi-labs/integration-sdk
# 1. Authenticate and create an integration in your workspace.
npx bondi init
# 2. Define your integration in code.
# 3. Sync the definition to Bondi.
npx bondi sync
npx bondi init opens your browser for authentication, then writes:
BONDI_API_URL=https://automation.heybondi.com
BONDI_WORKSPACE_ID=ws-...
BONDI_INTEGRATION_TOKEN=bnd_tok_...
import {
defineIntegration,
defineAction,
defineTrigger,
createBondiClient,
} from "@bondi-labs/integration-sdk/core";
import { z } from "zod";
const contactCreated = defineTrigger({
name: "contact.created",
label: "Contact Created",
payload: z.object({ id: z.string(), email: z.string().email() }),
});
const myCRM = defineIntegration({
name: "My CRM",
slug: "my-crm",
baseUrl: "https://api.mycrm.com/v1",
services: [
{
name: "contacts",
label: "Contacts",
actions: [
defineAction({
name: "createContact",
label: "Create Contact",
method: "POST",
endpoint: "/contacts",
body: z.object({ name: z.string(), email: z.string() }),
response: z.object({ id: z.string() }),
}),
],
triggers: [contactCreated],
},
],
});
export default myCRM; // CLI sync reads `default` export
// Runtime — emit events from your app
const client = createBondiClient({
workspaceId: process.env.BONDI_WORKSPACE_ID,
token: process.env.BONDI_INTEGRATION_TOKEN,
apiUrl: process.env.BONDI_API_URL,
});
const bondi = client.bind(myCRM);
bondi.triggers["contact.created"].emit({ id: "123", email: "john@example.com" });
emit() is fire-and-forget. Use emitAndWait() to await acknowledgement, or pass onEmitError to the client config to capture failures.
import {
BondiModule,
BondiTrigger,
BondiTriggerBase,
BondiService,
BondiAction,
BondiGuard,
} from "@bondi-labs/integration-sdk/nestjs";
import { Module, Controller, Injectable, Post, Body, UseGuards } from "@nestjs/common";
import { z } from "zod";
const contactPayload = z.object({ id: z.string(), email: z.string() });
@BondiTrigger({ name: "contact.created", label: "Contact Created", payload: contactPayload })
export class ContactCreatedTrigger extends BondiTriggerBase<typeof contactPayload> {}
@Injectable()
export class ContactsService {
constructor(private contactCreated: ContactCreatedTrigger) {}
create(dto: { id: string; email: string }) {
this.contactCreated.emit(dto); // type-safe via Zod
}
}
@BondiService({ name: "contacts", label: "Contacts" })
@Controller("contacts")
export class ContactsController {
@UseGuards(BondiGuard)
@BondiAction({ name: "createContact", label: "Create Contact" })
@Post()
async create(@Body() dto: unknown) {
/* ... */
}
}
@Module({
imports: [
BondiModule.forRoot({
integration: { name: "My CRM", slug: "my-crm", category: "crm" },
triggers: [ContactCreatedTrigger],
}),
],
})
export class AppModule {}
BondiModule.forRoot reads BONDI_* env vars by default. To override, pass values directly:
BondiModule.forRoot({
integration: { /* ... */ },
workspaceId: "ws-abc-123", // hard-coded
token: { envKey: "MY_BONDI_TOKEN" }, // custom env var
apiUrl: () => configService.get("BONDI_API_URL"), // factory
})
When Bondi calls your BondiAction endpoints, requests are signed with HMAC-SHA256 over {timestamp}.{action}.{rawBody}. The SDK's BondiGuard verifies this for you in NestJS. For other stacks, here's the equivalent in Python:
import hmac, hashlib, time
def verify_bondi(headers, raw_body, token):
ts = headers["x-bondi-timestamp"]
action = headers["x-bondi-action"]
sig = headers["x-bondi-signature"]
if abs(time.time() - int(ts)) > 300:
return False
expected = hmac.new(token.encode(), f"{ts}.{action}.{raw_body}".encode(), hashlib.sha256).hexdigest()
return hmac.compare_digest(sig.removeprefix("sha256="), expected)
| Var | Description |
|---|---|
BONDI_API_URL |
Bondi automation engine URL (set by npx bondi init) |
BONDI_WORKSPACE_ID |
Your workspace ID |
BONDI_INTEGRATION_TOKEN |
HMAC signing key — never sent over the wire |
| Topic | Link |
|---|---|
| Getting started — NestJS | docs/getting-started/nestjs.md |
| Getting started — plain Node / Express | docs/getting-started/plain-node.md |
| Verifying webhooks (Python, Go, Ruby) | docs/guides/webhook-verification.md |
| Error handling, retries, dry-run | docs/guides/error-handling.md |
| Token rotation | docs/guides/token-rotation.md |
internalMode (Bondi-only) |
docs/guides/internal-mode.md |
| HTTP header reference | docs/reference/headers.md |
MIT — see LICENSE.