StrikeOff API Documentation

Complete reference for coding agents

Overview

StrikeOff is a collaborative task management platform. The API allows external systems to create, read, update, and manage tasks programmatically. When you create tasks via this API, they are automatically tagged with your API key name as their source, enabling webhook notifications back to your system when those tasks change.

Base URL

https://strikeoffapp.com/api/external/v1

Authentication

All requests require a Bearer token in the Authorization header:

Authorization: Bearer sk_live_your_api_key

API keys are organization-scoped and can be created from Organization Settings → Integrations & API. Each API key has access only to boards, lists, and tasks within its organization. Keep your API keys secret - they provide full access to your organization's data.

Rate Limits

1,000 requests per hour per API key. Check the following response headers to monitor your usage:

X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 950
X-RateLimit-Reset: 2024-01-15T12:00:00Z

If you exceed the rate limit, you will receive a 429 response. Wait until the reset time before making more requests.

Data Hierarchy

Organization
  └── Board (project or department workspace)
        └── List (column like "To Do", "In Progress", "Done")
              └── Task (individual work item)

Understanding this hierarchy is essential. When creating a task, you need a list ID. To get list IDs, you need a board ID. Use the endpoints in order: first list boards, then get lists for a board, then create tasks in a list.

Key Concepts

Task Archiving

Tasks can be archived instead of deleted. Archived tasks are hidden from the UI but preserved in the database. When you archive a task, the archivedAt timestamp is automatically set. When you unarchive, it is cleared.

Auto-Unarchive Behavior

Important: If a task created via your API was accidentally archived by a user in StrikeOff, any update you send (PATCH, assign, or unassign) will automatically unarchive it. This ensures your external system stays in sync and tasks don't get "lost" in the archived state.

External Source Tracking

Tasks created via the API are automatically tagged with your API key name as their externalSource. This enables webhooks to notify your system when those tasks change, and powers the auto-unarchive feature.

Boards

GET/boards

Returns all boards in the organization.

Overview

Boards are the top-level containers for organizing work in StrikeOff. Each board belongs to an organization and contains multiple lists (columns), which in turn contain tasks. Think of a board as a project or a department's workspace. This endpoint returns every board your API key has access to within your organization, giving you a complete view of all available workspaces. Use this as your starting point when integrating with StrikeOff - first fetch boards to understand how work is organized, then drill down into specific boards to find lists and create tasks.

When to Use This

  • Discovering available boards when setting up your integration for the first time
  • Building a dropdown or selector in your app that lets users choose which StrikeOff board to sync with
  • Auditing or reporting on all boards in an organization
  • Finding the right board ID before fetching its lists or members
  • Displaying a dashboard that shows task counts across all boards

Request

curl -X GET "https://strikeoffapp.com/api/external/v1/boards" \
  -H "Authorization: Bearer sk_live_your_api_key"

Response

{
  "success": true,
  "data": {
    "boards": [
      {
        "id": "clxxx123...",
        "name": "Development",
        "description": "Engineering tasks and projects",
        "createdAt": "2024-01-15T10:00:00Z",
        "updatedAt": "2024-01-15T10:00:00Z",
        "listCount": 5,
        "memberCount": 12
      },
      {
        "id": "clyyy456...",
        "name": "Marketing",
        "description": "Marketing campaigns and content",
        "createdAt": "2024-02-01T09:00:00Z",
        "updatedAt": "2024-02-01T09:00:00Z",
        "listCount": 3,
        "memberCount": 8
      }
    ]
  }
}

Response Fields

  • id - Unique board identifier (use this for other API calls)
  • name - Display name of the board
  • description - Optional description text
  • listCount - Number of lists (columns) in the board
  • memberCount - Number of users with access to the board

GET/boards/:boardId/lists

Returns all lists within a board.

Overview

Lists are the columns within a board that organize tasks into categories or stages. Common examples include "To Do", "In Progress", and "Done" - but teams can create any lists they need. Each list has a unique ID that you need when creating tasks, because every task must belong to exactly one list. Lists are returned in their display order (left to right as shown in StrikeOff), and each includes a count of how many active (non-archived) tasks it contains. The customer field allows lists to be associated with specific clients when using StrikeOff for client work.

When to Use This

  • Finding the correct list ID to use when creating a new task via the API
  • Understanding how a board is structured before syncing tasks
  • Building a workflow that routes tasks to specific lists based on their type or status
  • Displaying list names and task counts in your integration UI
  • Mapping your external system categories to StrikeOff lists

Path Parameters

  • boardId (required) - The unique identifier of the board

Request

curl -X GET "https://strikeoffapp.com/api/external/v1/boards/clxxx123/lists" \
  -H "Authorization: Bearer sk_live_your_api_key"

Response

{
  "success": true,
  "data": {
    "board": {
      "id": "clxxx123...",
      "name": "Development"
    },
    "lists": [
      {
        "id": "cllist001...",
        "name": "Backlog",
        "order": 0,
        "customer": null,
        "createdAt": "2024-01-15T10:00:00Z",
        "updatedAt": "2024-01-15T10:00:00Z",
        "taskCount": 24
      },
      {
        "id": "cllist002...",
        "name": "In Progress",
        "order": 1,
        "customer": null,
        "createdAt": "2024-01-15T10:00:00Z",
        "updatedAt": "2024-01-15T10:00:00Z",
        "taskCount": 8
      },
      {
        "id": "cllist003...",
        "name": "Done",
        "order": 2,
        "customer": null,
        "createdAt": "2024-01-15T10:00:00Z",
        "updatedAt": "2024-01-15T10:00:00Z",
        "taskCount": 156
      }
    ]
  }
}

Response Fields

  • id - Unique list identifier (use this when creating tasks)
  • name - Display name of the list
  • order - Position in the board (0 = leftmost)
  • customer - Optional client association (may be null)
  • taskCount - Number of active (non-archived) tasks

GET/boards/:boardId/members

Returns all users with access to a board.

Overview

This endpoint returns all users who can view and work on tasks within a specific board. Members can have access in two ways: EXPLICIT means they were directly added to the board, while IMPLICIT means they have access through organization-level permissions (like being an org admin). You need user IDs from this endpoint to assign people to tasks - you cannot assign someone who is not a board member. Each member includes their role (ADMIN, MEMBER, or VIEWER) which determines what actions they can perform on the board.

When to Use This

  • Getting a list of valid user IDs before assigning someone to a task
  • Building a people picker or dropdown for task assignment in your app
  • Understanding who has access to a board for security or audit purposes
  • Syncing board membership with your external user directory
  • Displaying team members associated with a project in your integration

Path Parameters

  • boardId (required) - The unique identifier of the board

Request

curl -X GET "https://strikeoffapp.com/api/external/v1/boards/clxxx123/members" \
  -H "Authorization: Bearer sk_live_your_api_key"

Response

{
  "success": true,
  "data": {
    "board": {
      "id": "clxxx123...",
      "name": "Development"
    },
    "members": [
      {
        "id": "cluser001...",
        "name": "Jane Smith",
        "email": "jane@example.com",
        "profilePic": "https://...",
        "role": "ADMIN",
        "accessType": "EXPLICIT"
      },
      {
        "id": "cluser002...",
        "name": "Bob Wilson",
        "email": "bob@example.com",
        "profilePic": null,
        "role": "MEMBER",
        "accessType": "EXPLICIT"
      },
      {
        "id": "cluser003...",
        "name": "Alice Johnson",
        "email": "alice@example.com",
        "profilePic": "https://...",
        "role": "ADMIN",
        "accessType": "IMPLICIT"
      }
    ]
  }
}

Response Fields

  • id - Unique user identifier (use this when assigning tasks)
  • name - User's display name
  • email - User's email address
  • role - Board role: ADMIN, MEMBER, or VIEWER
  • accessType - EXPLICIT (directly added) or IMPLICIT (org-level access)

Tasks

POST/tasks

Create a new task in a list.

Overview

This is the primary endpoint for creating work items in StrikeOff from your external system. When you create a task via this API, it is automatically tagged with your API key name as its "externalSource" - this allows StrikeOff to know which tasks came from your integration and enables webhook notifications back to your system when those tasks change. The returned task ID is permanent and stable - save it in your system to track and update this task later. Tasks are created without any assignees by default; use the assign endpoint after creation to add team members.

When to Use This

  • Creating a task in StrikeOff when a new ticket is opened in your helpdesk system
  • Syncing issues from your bug tracker or project management tool
  • Automatically creating tasks from form submissions or customer requests
  • Building a two-way sync between StrikeOff and your existing workflow tools
  • Creating tasks from CI/CD pipeline events (e.g., failed builds, deployment issues)

Request Body

FieldTypeRequiredDescription
titlestringrequiredTask title (max 500 characters)
listIdstringrequiredID of the list to add the task to (get from /boards/:id/lists)
descriptionstringoptionalTask description (supports plain text)
priorityenumoptionalHIGH, MEDIUM_HIGH, MEDIUM, LOW, FUTURE (default: FUTURE)
statusenumoptionalOPEN, DOING, CLOSED (default: OPEN)
dueDateISO 8601optionalDue date in ISO 8601 format (e.g., 2024-12-31T23:59:59Z)
hashtagsstring[]optionalArray of hashtag names. Leading # is stripped automatically.

Request Example

curl -X POST "https://strikeoffapp.com/api/external/v1/tasks" \
  -H "Authorization: Bearer sk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Review Q4 financial report",
    "description": "Review and approve the quarterly report before Friday",
    "listId": "cllist001...",
    "dueDate": "2024-12-31T23:59:59Z",
    "priority": "HIGH",
    "status": "OPEN",
    "hashtags": ["finance", "quarterly-review", "urgent"]
  }'

Response (201 Created)

{
  "success": true,
  "data": {
    "task": {
      "id": "cltask001...",
      "title": "Review Q4 financial report",
      "description": "Review and approve the quarterly report before Friday",
      "status": "OPEN",
      "priority": "HIGH",
      "dueDate": "2024-12-31T23:59:59Z",
      "archived": false,
      "archivedAt": null,
      "createdAt": "2024-12-15T10:30:00Z",
      "updatedAt": "2024-12-15T10:30:00Z",
      "list": {
        "id": "cllist001...",
        "name": "Backlog",
        "board": {
          "id": "clxxx123...",
          "name": "Development",
          "organization": {
            "id": "clorg001...",
            "name": "Acme Corp"
          }
        }
      },
      "assignedTo": [],
      "hashtags": [
        { "id": "clhash001...", "name": "finance", "color": "#3B82F6" },
        { "id": "clhash002...", "name": "quarterly-review", "color": "#8B5CF6" },
        { "id": "clhash003...", "name": "urgent", "color": "#EF4444" }
      ]
    }
  }
}

Important Notes

  • Save the returned task.id in your system - you'll need it for updates
  • New tasks start with an empty assignee list - use /tasks/:id/assign to add people
  • Hashtag colors are auto-generated based on name for consistency
  • The task will appear at the end of the specified list

GET/tasks/:taskId

Get details of a specific task.

Overview

Use this endpoint to fetch the complete current state of a task. The response includes everything about the task: its title, description, status, priority, due date, who created it, who is assigned to it, what hashtags are attached, and which list/board/organization it belongs to. This is essential for syncing task state back to your system or verifying that an update was applied correctly. The task ID is permanent - even if users move the task to a different list or board within StrikeOff, the ID stays the same and this endpoint will always return its current location.

When to Use This

  • Checking the current status of a task before deciding whether to update it
  • Syncing task details back to your external system on a schedule
  • Verifying that a previous create or update operation succeeded
  • Fetching task data to display in your application UI
  • Debugging webhook payloads by comparing them to the full task data

Path Parameters

  • taskId (required) - The unique identifier of the task

Request

curl -X GET "https://strikeoffapp.com/api/external/v1/tasks/cltask001" \
  -H "Authorization: Bearer sk_live_your_api_key"

Response

{
  "success": true,
  "data": {
    "task": {
      "id": "cltask001...",
      "title": "Review Q4 financial report",
      "description": "Review and approve the quarterly report before Friday",
      "status": "DOING",
      "priority": "HIGH",
      "dueDate": "2024-12-31T23:59:59Z",
      "archived": false,
      "archivedAt": null,
      "closedDate": null,
      "createdAt": "2024-12-15T10:30:00Z",
      "updatedAt": "2024-12-16T09:00:00Z",
      "list": {
        "id": "cllist002...",
        "name": "In Progress",
        "board": {
          "id": "clxxx123...",
          "name": "Development",
          "organization": {
            "id": "clorg001...",
            "name": "Acme Corp"
          }
        }
      },
      "createdBy": {
        "id": "cluser001...",
        "name": "Jane Smith",
        "email": "jane@example.com"
      },
      "assignedTo": [
        {
          "user": {
            "id": "cluser002...",
            "name": "Bob Wilson",
            "email": "bob@example.com"
          }
        }
      ],
      "hashtags": [
        { "id": "clhash001...", "name": "finance", "color": "#3B82F6" },
        { "id": "clhash002...", "name": "urgent", "color": "#EF4444" }
      ]
    }
  }
}

Response Fields

  • archived - Whether the task is hidden from UI (true/false)
  • archivedAt - Timestamp when archived (null if not archived)
  • closedDate - Timestamp when status changed to CLOSED (null if not closed)
  • assignedTo - Array of assigned users (can have multiple)
  • list.board.organization - Full hierarchy showing where task lives

PATCH/tasks/:taskId

Update an existing task. All fields are optional.

Overview

This endpoint allows you to modify any aspect of an existing task. Send only the fields you want to change - omitted fields remain unchanged. This is the main way to keep tasks in sync between your system and StrikeOff. When you update the status to CLOSED, the closedDate is automatically set. When you archive a task, the archivedAt timestamp is recorded.

Auto-unarchive: If a task created via your API was accidentally archived by a user in StrikeOff, any update you send will automatically unarchive it. This ensures your external system stays in sync and tasks don't get "lost" in the archived state.

When to Use This

  • Updating task status when the corresponding item changes in your system (e.g., ticket resolved)
  • Syncing priority or due date changes from your project management tool
  • Marking tasks as complete when work is finished in your external workflow
  • Adding or updating hashtags to categorize tasks
  • Archiving tasks that are no longer relevant without permanently deleting them

Path Parameters

  • taskId (required) - The unique identifier of the task to update

Request Body (all fields optional)

FieldTypeDescription
titlestringNew task title (max 500 characters)
descriptionstringNew task description
priorityenumHIGH, MEDIUM_HIGH, MEDIUM, LOW, FUTURE
statusenumOPEN, DOING, CLOSED (setting to CLOSED sets closedDate automatically)
dueDateISO 8601 | nullNew due date, or null to clear
archivedbooleanArchive (true) or unarchive (false) the task. archivedAt is set automatically.
hashtagsstring[]Replace all hashtags. Use empty array [] to remove all.

Request Example

curl -X PATCH "https://strikeoffapp.com/api/external/v1/tasks/cltask001" \
  -H "Authorization: Bearer sk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "status": "CLOSED",
    "priority": "MEDIUM",
    "hashtags": ["completed", "finance"]
  }'

Response

{
  "success": true,
  "data": {
    "task": {
      "id": "cltask001...",
      "title": "Review Q4 financial report",
      "status": "CLOSED",
      "priority": "MEDIUM",
      "archived": false,
      "archivedAt": null,
      "closedDate": "2024-12-20T14:30:00Z",
      "updatedAt": "2024-12-20T14:30:00Z",
      "hashtags": [
        { "id": "clhash004...", "name": "completed", "color": "#10B981" },
        { "id": "clhash001...", "name": "finance", "color": "#3B82F6" }
      ]
      // ... other fields
    }
  }
}

DELETE/tasks/:taskId

Permanently delete a task.

Overview

This endpoint permanently removes a task from StrikeOff. Unlike archiving, deletion is irreversible - the task and all its associated data (comments, checklists, attachments, assignment history) will be completely removed from the database. Use this only when you are certain the task should be permanently destroyed. For tasks you might need later, consider using the update endpoint to set archived:true instead, which hides the task but preserves all its data.

When to Use This

  • Removing a task that was created by mistake
  • Cleaning up test tasks created during integration development
  • Deleting tasks when the corresponding item is permanently deleted in your external system
  • Removing spam or invalid tasks that should not exist

Path Parameters

  • taskId (required) - The unique identifier of the task to delete

Request

curl -X DELETE "https://strikeoffapp.com/api/external/v1/tasks/cltask001" \
  -H "Authorization: Bearer sk_live_your_api_key"

Response

{
  "success": true,
  "data": {
    "message": "Task deleted successfully"
  }
}

Warning: This action is permanent and cannot be undone. All task data including comments, checklists, and attachments will be permanently deleted.

POST/tasks/:taskId/assign

Assign a user to a task.

Overview

This endpoint assigns a team member to a task, making them responsible for completing it. Assigned users see the task in their personal task list and receive notifications about changes. Tasks can have multiple assignees - call this endpoint multiple times with different user IDs to add more people. The user must be a member of the organization (get valid user IDs from the Get Board Members endpoint). If the task was accidentally archived by a user in StrikeOff, assigning someone to it will automatically unarchive it, ensuring your external system stays in sync.

When to Use This

  • Assigning the appropriate team member when creating a task from an external ticket
  • Routing tasks to specific users based on your external system's assignment rules
  • Adding additional team members to collaborate on a task
  • Implementing round-robin or load-balanced task assignment from your automation
  • Syncing assignment changes from your project management tool to StrikeOff

Path Parameters

  • taskId (required) - The unique identifier of the task

Request Body

  • userId (required) - ID of the user to assign (get from /boards/:boardId/members)

Request Example

curl -X POST "https://strikeoffapp.com/api/external/v1/tasks/cltask001/assign" \
  -H "Authorization: Bearer sk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "cluser002..."
  }'

Response (201 Created)

{
  "success": true,
  "data": {
    "assignment": {
      "id": "classign001...",
      "user": {
        "id": "cluser002...",
        "name": "Bob Wilson",
        "email": "bob@example.com"
      },
      "assignedBy": {
        "id": "cluser001...",
        "name": "John Doe",
        "email": "john@example.com"
      },
      "assignedAt": "2024-01-20T10:00:00Z"
    }
  }
}

Error Cases

  • 400: "User is not a member of this organization" - User ID not found in org
  • 400: "User is already assigned to this task" - Duplicate assignment
  • 404: "Task not found" - Invalid task ID

POST/tasks/:taskId/unassign

Remove a user from a task.

Overview

This endpoint removes a user's assignment from a task. After unassignment, the task will no longer appear in that user's personal task list, and they will stop receiving notifications about it. The task itself remains unchanged - only the assignment is removed. Other assignees (if any) remain assigned. Use this when responsibility for a task shifts to someone else, or when the original assignee is no longer available. If the task was accidentally archived by a user in StrikeOff, unassigning someone from it will automatically unarchive it, ensuring your external system stays in sync.

When to Use This

  • Removing an assignee when the corresponding assignment is removed in your external system
  • Reassigning work by unassigning the current person before assigning someone new
  • Cleaning up assignments when a team member leaves or changes roles
  • Syncing unassignment actions from your project management tool
  • Removing an assignee who was added by mistake

Path Parameters

  • taskId (required) - The unique identifier of the task

Request Body

  • userId (required) - ID of the user to unassign

Request Example

curl -X POST "https://strikeoffapp.com/api/external/v1/tasks/cltask001/unassign" \
  -H "Authorization: Bearer sk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "cluser002..."
  }'

Response

{
  "success": true,
  "data": {
    "message": "User unassigned successfully",
    "unassignedUser": {
      "id": "cluser002...",
      "name": "Bob Wilson",
      "email": "bob@example.com"
    }
  }
}

Error Cases

  • 400: "User is not assigned to this task" - User wasn't assigned
  • 404: "Task not found" - Invalid task ID

Error Codes

All API responses use standard HTTP status codes. Error responses include a descriptive message to help you debug issues.

200 - Success (GET, PATCH, DELETE)
201 - Created (POST)
400 - Bad request (invalid parameters, validation errors)
401 - Unauthorized (invalid or missing API key)
403 - Forbidden (no access to resource)
404 - Not found (resource doesn't exist)
429 - Rate limit exceeded
500 - Server error

Error response format:
{
  "success": false,
  "error": "Description of what went wrong"
}

Common Error Messages by Endpoint

Boards:
  GET /boards/:boardId/lists    → 404: "Board not found"
  GET /boards/:boardId/members  → 404: "Board not found"

Tasks:
  POST /tasks                   → 400: "Task title is required"
                                → 400: "List ID is required"
                                → 404: "List not found"
  GET /tasks/:taskId            → 404: "Task not found"
  PATCH /tasks/:taskId          → 404: "Task not found"
                                → 400: "No valid fields to update"
  DELETE /tasks/:taskId         → 404: "Task not found"

Assignments:
  POST /tasks/:taskId/assign    → 404: "Task not found"
                                → 400: "User ID is required"
                                → 400: "User is not a member of this organization"
                                → 400: "User is already assigned to this task"
  POST /tasks/:taskId/unassign  → 404: "Task not found"
                                → 400: "User ID is required"
                                → 400: "User is not assigned to this task"

Webhooks

Overview

Webhooks allow StrikeOff to notify your system when events occur on tasks that were created via your API. This enables real-time two-way sync - your system creates tasks in StrikeOff, and StrikeOff notifies you when users interact with those tasks.

Configuration

To configure webhooks: Go to your organization → click the menu (⋮) → Integrations & API → click the webhook icon on your API key. You can set the webhook URL and select which events to subscribe to.

Available Events

EventDescription
task.status.changedFires when a task moves between OPEN, DOING, and CLOSED states
task.assignedFires when a user is assigned to a task
task.unassignedFires when a user is removed from a task

Webhook Payload

{
  "event": "task.status.changed",
  "timestamp": "2024-01-20T10:00:00Z",
  "apiKeyId": "clxxx123...",
  "task": {
    "id": "cltask001...",
    "title": "Fix login bug",
    "status": "DOING",
    "previousStatus": "OPEN",
    "listId": "cllist001...",
    "listName": "In Progress",
    "boardId": "clboard001...",
    "boardName": "Development"
  },
  "changedBy": {
    "id": "cluser001...",
    "name": "John Doe",
    "email": "john@example.com"
  }
}

Request Headers

Content-Type: application/json
X-StrikeOff-Event: task.status.changed
X-StrikeOff-Timestamp: 2024-01-20T10:00:00Z

Important Notes

  • Only API-created tasks: Webhooks only fire for tasks created via the external API (tasks with matching externalSource). Tasks created directly in StrikeOff UI do not trigger webhooks.
  • Verification: Use the apiKeyId in the payload to verify the request came from StrikeOff
  • Timeout: Webhooks timeout after 10 seconds. Ensure your endpoint responds quickly.
  • No retries: Failed webhooks are logged but not retried automatically. Monitor your endpoint for failures.
  • HTTPS required: Webhook URLs must use HTTPS in production.

Common Workflows

1. Create a task from external system

When a ticket is created in your helpdesk, create a corresponding task in StrikeOff:

1. GET /boards                    → Find target board by name
2. GET /boards/:boardId/lists     → Find target list (e.g., "To Do")
3. POST /tasks                    → Create task with title and listId
4. Store the returned task.id     → You'll need this for updates

2. Assign task to team member

Route the task to the appropriate person:

1. GET /boards/:boardId/members   → Get list of available users
2. Find user by email or name     → Match with your system's user
3. POST /tasks/:taskId/assign     → Assign using the user ID

3. Sync status changes both ways

Keep your system and StrikeOff in sync:

Your system → StrikeOff:
  When ticket status changes → PATCH /tasks/:taskId with new status

StrikeOff → Your system:
  Configure webhook for task.status.changed event
  When webhook received → Update ticket status in your system

4. Clean up completed tasks

Archive or delete tasks that are no longer needed:

Option A - Archive (recommended, preserves data):
  PATCH /tasks/:taskId with { "archived": true }

Option B - Delete (permanent, cannot undo):
  DELETE /tasks/:taskId

Example: Complete Integration Flow

Here's a complete example showing how to create a task and assign someone to it:

# Step 1: Find the board
curl -X GET "https://strikeoffapp.com/api/external/v1/boards" \
  -H "Authorization: Bearer sk_live_your_api_key"

# Step 2: Get lists from the board (use board ID from step 1)
curl -X GET "https://strikeoffapp.com/api/external/v1/boards/clboard001/lists" \
  -H "Authorization: Bearer sk_live_your_api_key"

# Step 3: Get board members (for assignment)
curl -X GET "https://strikeoffapp.com/api/external/v1/boards/clboard001/members" \
  -H "Authorization: Bearer sk_live_your_api_key"

# Step 4: Create the task (use list ID from step 2)
curl -X POST "https://strikeoffapp.com/api/external/v1/tasks" \
  -H "Authorization: Bearer sk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Fix critical login bug",
    "listId": "cllist001",
    "priority": "HIGH",
    "description": "Users unable to login with SSO",
    "hashtags": ["bug", "critical"]
  }'

# Step 5: Assign user (use task ID from step 4, user ID from step 3)
curl -X POST "https://strikeoffapp.com/api/external/v1/tasks/cltask001/assign" \
  -H "Authorization: Bearer sk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{ "userId": "cluser002" }'

# Step 6: Later, mark as complete
curl -X PATCH "https://strikeoffapp.com/api/external/v1/tasks/cltask001" \
  -H "Authorization: Bearer sk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{ "status": "CLOSED" }'