FabricFabricSDK
Plugins

Asana

Manage tasks and projects with webhook handshake support.

Authentication

TypeDefaultDetails
api_keyPersonal Access Token
oauth_2Asana OAuth with default scope

Endpoints

PathRiskDescription
tasks.listreadList tasks.
tasks.getreadGet a task.
tasks.createwriteCreate a task.
tasks.updatewriteUpdate a task.
tasks.deletedestructiveDelete a task.
tasks.addToProjectwriteAdd a task to a project.
tasks.addCommentwritePost a comment on a task.
projects.listreadList projects.
projects.getreadGet a project.
users.mereadGet the authenticated user.

tasks.list

List tasks in a workspace.

Input:

FieldTypeRequiredDescription
workspacestringWorkspace GID
assigneestringAssignee GID
completed_sincestringISO datetime
limitnumberMax results

Output: AsanaTask[]

tasks.get

Get a single task.

Input:

FieldTypeRequiredDescription
gidstringTask GID

Output: AsanaTask

tasks.create

Create a new task.

Input:

FieldTypeRequiredDescription
namestringTask name
notesstringTask description
assigneestringAssignee GID
due_onstringDue date (YYYY-MM-DD)
projectsstring[]Project GIDs
workspacestringWorkspace GID

Output: AsanaTask

tasks.update

Update an existing task.

Input:

FieldTypeRequiredDescription
gidstringTask GID
namestringNew name
notesstringNew description
completedbooleanMark complete/incomplete
assigneestringNew assignee
due_onstringNew due date

Output: AsanaTask

tasks.delete

Delete a task permanently.

Input:

FieldTypeRequiredDescription
gidstringTask GID

Output: { ok: boolean }

tasks.addToProject

Add a task to a project (optionally a section).

Input:

FieldTypeRequiredDescription
gidstringTask GID
projectstringProject GID
sectionstringSection GID

Output: { ok: boolean }

tasks.addComment

Post a comment (story) on a task.

Input:

FieldTypeRequiredDescription
gidstringTask GID
textstringComment text

Output: { gid: string; text: string }

projects.list

List projects in a workspace.

Input:

FieldTypeRequiredDescription
workspacestringWorkspace GID
archivedbooleanInclude archived projects
limitnumberMax results

Output: AsanaProject[]

projects.get

Get a single project.

Input:

FieldTypeRequiredDescription
gidstringProject GID

Output: AsanaProject

users.me

Get the authenticated user.

Input: None

Output: AsanaUser

Usage

import { createFabric } from "@fabricorg/integrations";
import { asana } from "@fabricorg/integrations/plugins";

const fabric = createFabric({
  plugins: [asana({ apiKey: process.env.ASANA_ACCESS_TOKEN })],
});

// Create a task
const task = await fabric.asana.api.tasks.create({
  workspace: "1234567890",
  name: "Review PR #42",
  due_on: "2026-05-15",
  projects: ["0987654321"],
});

// Add a comment
await fabric.asana.api.tasks.addComment({
  gid: task.gid,
  text: "LGTM, merging now.",
});

Webhooks

Asana webhooks require a handshake: the first POST after subscription carries X-Hook-Secret, which must be echoed back before events flow.

EventPathDescription
HandshakehandshakeInitial subscription handshake (echoes secret).
Task addedtask.addedA task was added to a project.
Task changedtask.changedA task was modified.

Signature verification

import { verifyAsanaSignature } from "@fabricorg/integrations/plugins";

const valid = verifyAsanaSignature({
  rawBody: requestBody,
  signatureHeader: headers["x-hook-signature"],
  secret: webhookSecret,
});

Webhook payload

interface AsanaEvent {
  user?: { gid: string };
  resource: { gid: string; resource_type: string };
  action: "added" | "removed" | "changed" | "deleted" | "undeleted";
  created_at: string;
  change?: { field: string; action: string };
}

Types

interface AsanaTask {
  gid: string;
  name: string;
  notes?: string;
  completed?: boolean;
  due_on?: string | null;
  assignee?: { gid: string; name?: string } | null;
  projects?: Array<{ gid: string; name?: string }>;
  workspace?: { gid: string; name?: string };
}

interface AsanaProject {
  gid: string;
  name: string;
  workspace?: { gid: string; name?: string };
  owner?: { gid: string; name?: string };
}

interface AsanaUser {
  gid: string;
  name: string;
  email?: string;
}