Skip to main content

ClickUp Production Setup

This is the operator runbook for connecting a ClickUp workspace to a production Alakai deployment: discovering custom field IDs, registering list-scoped webhooks, storing secrets, and using the core/ utility Makefile to do it.

It assumes the platform/stage routing model (tasks trigger on the Alakai Ready status, routed by list/Platform field). For the config.json schema and local testing, see ClickUp Integration. For the end-user view, see ClickUp Automations.

All make commands below run from the core/ directory. Each reads CLICKUP_BOT_API_TOKEN, CLICKUP_WORKSPACE_ID, and ALAKAI_WEBHOOK_URL from arguments or from core/.env if not passed explicitly.

Prerequisites

ItemHow to get it
ClickUp bot API tokenIn ClickUp: Settings → Apps → API → generate a personal API token. Used for all webhook/field admin calls and for posting comments back on tasks. Store as CLICKUP_BOT_API_TOKEN.
Workspace (team) IDThe numeric ID in any ClickUp URL: https://app.clickup.com/<workspaceId>/.... Store as CLICKUP_WORKSPACE_ID.
Alakai public URLThe internet-reachable base URL of the deployed Alakai service (no trailing path). ClickUp posts webhooks to <url>/clickup/webhook. Store as ALAKAI_WEBHOOK_URL.

Production environment variables

In production, Alakai loads its secrets from AWS Secrets Manager (AWS_SECRETS_MANAGER_SECRET_ID + AWS_REGION). The ClickUp-related keys:

VariableRequired forDescription
CLICKUP_BOT_API_TOKENWebhooks + comment-backBot token used to register webhooks and post comments on tasks.
CLICKUP_WEBHOOK_SECRETSWebhook signature verificationJSON object mapping webhook_id → secret, e.g. {"wh_abc123":"secret_..."}. One entry per registered list webhook.
ALAKAI_WEBHOOK_URLWebhook registrationPublic base URL used as the webhook endpoint.
CLICKUP_OAUTH_CLIENT_ID/clickup-ask, /clickup-taskOAuth client registered with mcp.clickup.com (see OAuth client).
CLICKUP_OAUTH_CLIENT_SECRET/clickup-ask, /clickup-taskOAuth client secret (if issued).
CLICKUP_OAUTH_REDIRECT_URI/clickup-ask, /clickup-taskOAuth callback URL; must match the registered redirect URI.
CLICKUP_SHARED_ACCESS_TOKEN@Alakai thread → taskShared token used by the thread-mention task-creation flow.
CLICKUP_MCP_OPENAI_KEY/clickup-ask, /clickup-taskOpenAI key for the ClickUp ask/task agent.
CLICKUP_WORKSPACE_IDOptionalPassed to MCP tools that accept a workspace ID.
CLICKUP_AGENT_MODELOptionalModel for the ClickUp agent (default gpt-4o).
CLICKUP_REDIS_KEY_PREFIXOptionalNamespaces ClickUp OAuth/shared-token Redis keys.
AWS_SECRETS_MANAGER_SECRET_IDProductionSecrets Manager secret holding the above. Also required so /init can persist new webhook secrets.

CLICKUP_WEBHOOK_SECRETS is stored as a JSON object (not a plain string). When adding a new list webhook, merge its {id: secret} entry into the existing object rather than overwriting it.

Step 1 — Configure the ClickUp UI

Before wiring config, set up the workspace in ClickUp so the routing fields exist:

  1. Alakai Ready status — add a status named Alakai Ready to the workflow of each list Alakai watches. Moving a task into this status is the trigger.
  2. Alakai stage field — create a dropdown custom field named Alakai stage with two options: Prompting and Implementation. (Matched by name, case-insensitive.)
  3. Platform field (only for shared lists) — if one list feeds several repos, create a dropdown custom field (commonly named Platform) whose options correspond to each target repo, e.g. Backend, iOS, Web.

Step 2 — Discover custom field IDs and option labels

config.json references the Platform field by its field ID, and routes by its option labels. List them for a given list:

cd core
make get-clickup-list-fields list_id=901200100

Output looks like:

Platform [id=cf_8a1b...] (type=drop_down)
- "Backend" orderindex=0 id=...
- "iOS" orderindex=1 id=...
Alakai stage [id=cf_9c2d...] (type=drop_down)
- "Prompting" orderindex=0 id=...
- "Implementation" orderindex=1 id=...

Use the Platform field's id as platformField.id and the option names (Backend, iOS, …) as each application's platformFieldValue in config.json.

Finding the list ID itself: open the list in ClickUp; the numeric ID is in the URL, or list them via the API — curl -s "https://api.clickup.com/api/v2/space/<spaceId>/list?archived=false" -H "Authorization: $CLICKUP_BOT_API_TOKEN" | jq '.lists[] | {id, name}'.

Step 3 — Register a list-scoped webhook

Each connected list needs its own webhook for taskStatusUpdated events:

cd core
make register-clickup-webhook \
CLICKUP_BOT_API_TOKEN=pk_xxxxxxxxxxxxx \
CLICKUP_WORKSPACE_ID=3030784 \
ALAKAI_WEBHOOK_URL=https://alakai.example.com \
list_id=901200100

The command prints the ClickUp response and a ready-to-paste secret line:

Store this secret in the CLICKUP_WEBHOOK_SECRETS map (AWS Secrets Manager), keyed by webhook id:
"wh_abc123xyz789": "secret_xxxxxxxxxxxxxxxxxxxx"

Record the webhook ID — it goes into config.json as the list's webhookId (the routing key).

Step 4 — Store the webhook secret

Merge the printed {webhookId: secret} entry into the CLICKUP_WEBHOOK_SECRETS JSON object in the AWS Secrets Manager secret referenced by AWS_SECRETS_MANAGER_SECRET_ID:

{
"CLICKUP_WEBHOOK_SECRETS": "{\"wh_abc123xyz789\":\"secret_xxxxxxxxxxxxxxxxxxxx\",\"wh_def456\":\"secret_yyyy\"}"
}

Redeploy / restart Alakai so it picks up the updated secret. Signature verification fails (401) for any webhook whose ID is not present in this map.

Step 5 — Wire config.json

Add the list (with its webhookId, and platformField/defaultApplication if shared) under the project's clickup.lists[], and point each application at the list via taskStatusTrigger. Enable workflows.clickupTaskPromptPr: true on each application.

See ClickUp Integration → Configuring routing for the full schema and worked examples.

Optional — Register the OAuth client (for /clickup-ask & /clickup-task)

The Slack ClickUp commands authenticate each user against ClickUp's MCP OAuth server. Register a client once:

cd core
make register-clickup-mcp-client \
redirect_uri='https://alakai.example.com/oauth/clickup/callback' \
client_name='Alakai'

It prints the CLICKUP_OAUTH_CLIENT_ID to store. The redirect URI must exactly match CLICKUP_OAUTH_REDIRECT_URI.

The client must be registered with mcp.clickup.com, not the legacy app.clickup.com. A client_id from app.clickup.com will not work.

Managing webhooks

List every webhook registered for the workspace (id, endpoint, scope, events, delivery health):

cd core
make list-clickup-webhooks \
CLICKUP_BOT_API_TOKEN=pk_xxxxxxxxxxxxx \
CLICKUP_WORKSPACE_ID=3030784

Use this to audit which lists are wired and to spot webhooks whose health is failing. Remove a stale or rotated webhook by ID:

cd core
make remove-clickup-webhook webhook_id='wh_abc123xyz789'

After removing a webhook, also drop its entry from CLICKUP_WEBHOOK_SECRETS.

Rotating a webhook secret

ClickUp does not rotate a webhook secret in place — delete and re-register:

  1. make remove-clickup-webhook webhook_id='<old-id>'
  2. make register-clickup-webhook ... list_id=<listId> → capture the new id + secret
  3. Update both CLICKUP_WEBHOOK_SECRETS (new entry, remove old) and the list's webhookId in config.json
  4. Redeploy.

Utility Makefile reference

All run from core/:

TargetPurpose
make get-clickup-list-fields list_id=<id>List a list's custom fields — IDs + dropdown option labels — for platformField config.
make register-clickup-webhook ... list_id=<id>Register a list-scoped taskStatusUpdated webhook; prints the webhook id + secret.
make list-clickup-webhooksList all workspace webhooks with scope, events, and health.
make remove-clickup-webhook webhook_id=<id>Delete a webhook by ID.
make register-clickup-mcp-client redirect_uri=<uri>Register the OAuth client for /clickup-ask and /clickup-task.