ClickUp Upgrade & Migration
Overview
Guide for migrating between ClickUp API versions. API v2 is the current stable version (/api/v2/). API v3 endpoints are gradually being introduced with terminology and structural changes.
Key v2 vs v3 Terminology Changes
| Concept | API v2 Term | API v3 Term |
|---|
| Workspace | Team (team_id) | Workspace (workspace_id) |
| User Group | Team | Group (group_id) |
| Get workspaces | GET /team | GET /v3/workspaces |
Pre-Migration Assessment
#!/bin/bash
echo "=== ClickUp API Usage Audit ==="
echo "API v2 endpoints found:"
grep -rn "api/v2/" src/ --include="*.ts" --include="*.js" | \
sed 's/.*api\/v2\///' | cut -d'"' -f1 | cut -d"'" -f1 | \
sort | uniq -c | sort -rn
echo ""
echo "Unique endpoints:"
grep -rohn "api/v2/[a-z_/]*" src/ --include="*.ts" | sort -u
echo ""
echo "Deprecated patterns:"
grep -rn "team_id\|getauthorizedteams" src/ --include="*.ts" -i || echo " None found"
Migration Strategy: Adapter Pattern
interface ClickUpAdapter {
getWorkspaces(): Promise<Workspace[]>;
getSpaces(workspaceId: string): Promise<Space[]>;
createTask(listId: string, task: CreateTaskInput): Promise<Task>;
}
class ClickUpV2Adapter implements ClickUpAdapter {
async getWorkspaces() {
const data = await this.request('/team');
return data.teams.map((t: any) => ({ id: t.id, name: t.name }));
}
async getSpaces(workspaceId: string) {
const data = await this.request(`/team//space`);
data.;
}
() {
.(, {
: ,
: .(task),
});
}
() {
res = (, {
...options,
: {
: process..!,
: ,
},
});
res.();
}
}
{
() {
data = .();
data.;
}
}
Feature Flag for Gradual Migration
function getAdapter(): ClickUpAdapter {
const useV3 = process.env.CLICKUP_API_V3 === 'true';
return useV3 ? new ClickUpV3Adapter() : new ClickUpV2Adapter();
}
const adapter = getAdapter();
const workspaces = await adapter.getWorkspaces();
Testing Migration
import { describe, it, expect } from 'vitest';
describe('API Version Migration', () => {
const adapters = [
{ name: 'v2', adapter: new ClickUpV2Adapter() },
];
adapters.forEach(({ name, adapter }) => {
it(`${name}: returns workspaces with id and name`, async () => {
const workspaces = await adapter.getWorkspaces();
expect(workspaces[0]).toHaveProperty('id');
expect(workspaces[0]).toHaveProperty('name');
});
});
});
Rollback Procedure
export CLICKUP_API_V3=false
curl -sf https://api.clickup.com/api/v2/user \
-H "Authorization: $CLICKUP_API_TOKEN" | jq '.user.username'
Error Handling
| Issue | Cause | Solution |
|---|
| Endpoint 404 | v3 endpoint not yet available | Fall back to v2 equivalent |
| Field name mismatch | v3 changed response shape | Update type definitions |
team_id not recognized | v3 expects workspace_id | Use adapter to translate |
Resources
Next Steps
For CI integration during upgrades, see clickup-ci-integration.