Docs/Framework integrations

Find the framework route, component prop, SDK method, or HTTP contract you need.

Next.js App Router

Create a server-only integration module, mount the allowlisted browser proxy, and keep signed background delivery on a separate webhook route.

Create the integration

src/lib/incld.ts ts
import "server-only"
import { createIncld, defineActions } from "@incld/client/next"

export const incld = createIncld({
 apiKey: process.env.INCLD_SECRET_KEY!,
 webhookSecret: process.env.INCLD_WEBHOOK_SECRET!,
 baseUrl: process.env.INCLD_API_URL,
 actions: defineActions({
  generate_report: {
   displayName: "Generate report",
   async run({ payload, event }) {
    await reports.enqueue(payload, event.idempotencyKey)
   },
  },
 }),
 async resolveContext(_request) {
  const session = await auth()
  return session?.organizationId
   ? {
      user: { id: session.user.id },
      organization: { id: session.organizationId },
     }
   : null
 },
 async authorize({ context, operation }) {
  return canUseIncld(context.user.id, operation)
 },
})

Mount the routes

app/api/incld/v1/[...path]/route.ts ts
import { incld } from "@/lib/incld"

export const dynamic = "force-dynamic"
export const { GET, POST, PATCH, DELETE } = incld.routes
app/api/incld/webhook/route.ts ts
import { incld } from "@/lib/incld"

export const dynamic = "force-dynamic"
export const POST = incld.webhook

Keep the integration in a server-only module

Import the integration only from Route Handlers, Server Actions, startup tasks, or other server modules. Client Components import @incld/react*, never this file.

Add the browser provider

"use client"
import { IncldProvider } from "@incld/react"

export function IncldProviders({ children }) {
 return <IncldProvider baseUrl="/api/incld">{children}</IncldProvider>
}

The client appends /v1, so the catch-all route lives beneath /api/incld/v1.

Keep privileged mutations on the server

Browser proxying intentionally excludes action definition and Bulk creation. Perform those operations through incld.client after your server authorizes the user. Approval Policy management can use the browser components only when authorize explicitly permits the operation. Include the trusted active organization on tenant-bound server writes, then return only safe identifiers to the browser.

import { Incld } from "@incld/client"

export async function POST(request: Request) {
 const session = await auth()
 if (!session?.organizationId) {
  return Response.json({ error: "forbidden" }, { status: 403 })
 }
 if (!session.permissions.includes("bulk:create")) {
  return Response.json({ error: "forbidden" }, { status: 403 })
 }
 const tenantIncld = new Incld({
  apiKey: process.env.INCLD_SECRET_KEY!,
  scope: { organizationId: session.organizationId, userId: session.user.id },
 })
 const operation = await tenantIncld.bulkOperations.create(
  {
   action: "sync_contacts",
   items: await request.json(),
  },
  { idempotencyKey: request.headers.get("idempotency-key") ?? crypto.randomUUID() },
 )
 return Response.json({ operationId: operation.id }, { status: 202 })
}