# Move a task when a pull request merges

> Close the loop between code and plan: find the Dailybot task key in a pull request, move the task to its board's done column and leave a comment, from any CI.

Language: en
Canonical: https://www.dailybot.com/developers/plan/recipes/move-on-pr-merge
Markdown: send header `Accept: text/markdown` on any URL to receive Markdown instead of HTML.
Last Updated: 2026-09-25

---

> **Beta** — Plan is in beta. Everything under `/plan` in the web app, the CLI and agent skill commands for projects, goals, boards and tasks, and the `/v1/plan/` public API may change before general availability. Want to try it with your team? Write to **support@dailybot.com**.

When a pull request titled `ENG-142: Ship the delta feed` merges, the task `ENG-142` should move to done without anyone touching the board. Task keys make this easy: a key is enough to address a task, and every board has a column in the `done` category.

This recipe is a shell script you can run as the last step of any CI job after a merge.

<h2 id="credential">Pick a credential</h2>

- A **personal API key** (`X-API-KEY`) suits CI that should act as one person: it reaches everything that person can see, with no scope to request. An **agent or organization key** acts as a system actor instead: it only reaches tasks on **organization-visible** boards and needs the `tasks:write` scope granted to it (during the Beta, write to **support@dailybot.com**).
- A **CLI user token** also works if the move should be recorded as a specific person.

See [Authentication for Plan](/developers/plan/authentication).

<h2 id="script">The script</h2>

```bash
#!/usr/bin/env bash
set -euo pipefail
API="https://api.dailybot.com/v1/plan"
AUTH=(-H "X-API-KEY: $DAILYBOT_API_KEY")

# 1. Find the task key in the pull request title (or the branch name).
KEY=$(echo "$PR_TITLE" | grep -oE '[A-Z][A-Z0-9]+-[0-9]+' | head -1 || true)
if [ -z "$KEY" ]; then echo "No task key in the title; nothing to move."; exit 0; fi

# 2. Read the task by its key to learn its board and version.
TASK_JSON=$(curl -sS --fail-with-body "$API/tasks/$KEY/" "${AUTH[@]}")
BOARD=$(echo "$TASK_JSON" | jq -r .board)
VERSION=$(echo "$TASK_JSON" | jq -r .version)

# 3. Pick the board's first column in the "done" category.
DONE=$(curl -sS --fail-with-body "$API/boards/$BOARD/states/" "${AUTH[@]}" \
  | jq -r '[.[] | select(.category == "done")][0].uuid')

# 4. Move the task there, refusing if someone changed it meanwhile.
curl -sS --fail-with-body -X POST "$API/tasks/$KEY/move/" "${AUTH[@]}" \
  -H "Content-Type: application/json" \
  -H "If-Match: \"$VERSION\"" \
  -d "{\"state\": \"$DONE\"}" | jq '{key, state: .state.name, version}'

# 5. Say why it moved.
curl -sS --fail-with-body -X POST "$API/tasks/$KEY/comments/" "${AUTH[@]}" \
  -H "Content-Type: application/json" \
  -d "{\"body\": \"Merged: $PR_URL\"}" > /dev/null
```

Set `PR_TITLE` and `PR_URL` from your CI's pull request variables.

<h2 id="details">Details that matter</h2>

- **Keys survive renames.** If the board's key changed from `ENG` to `PLAT` after the branch was opened, `ENG-142` still resolves.
- **Categories, not names.** Columns can be called anything; the `done` category is what makes this script work on every board.
- **Concurrent edits.** If someone edited the task between the read and the move, the move answers `409 version_conflict`. Re-run the step, or drop `If-Match` if the merge should always win.
- **Moving is the only way to change a state**; the task goes to the end of the done column.
- A key from another organization, or on a board the credential cannot see, answers `404`.

From the CLI, the equivalent commands are:

```bash
dailybot plan task move "$KEY" --state done
dailybot plan task comment "$KEY" "Merged: $PR_URL"
```

<h2 id="reference">Reference</h2>

- [`GET /v1/plan/tasks/{task_id}/`](/developers/api/plan-tasks#plan-task-detail)
- [`GET /v1/plan/boards/{board_id}/states/`](/developers/api/plan-boards#plan-board-states-list)
- [`POST /v1/plan/tasks/{task_id}/move/`](/developers/api/plan-tasks#plan-task-move)
- [`POST /v1/plan/tasks/{task_id}/comments/`](/developers/api/plan-collaboration#plan-task-comment-create)

---

## Developer portal navigation

**Getting Started**

- [Overview](/developers)
- [Quick start](/developers/getting-started)
- [Authentication](/developers/authentication)

**API Reference**

- [API Overview](/developers/api)
- [Users](/developers/api/users)
- [Organization](/developers/api/organization)
- [Teams](/developers/api/teams)
- [Invitations](/developers/api/invitations)
- [Check-ins](/developers/api/check-ins)
- [Forms](/developers/api/forms)
- [Labels](/developers/api/labels)
- [Report channels](/developers/api/report-channels)
- [Templates](/developers/api/templates)
- [Kudos](/developers/api/kudos)
- [Mood tracking](/developers/api/mood)
- [Important dates](/developers/api/important-dates)
- [Messaging](/developers/api/messaging)
- [Automations](/developers/api/workflows)
- [Webhooks](/developers/api/webhooks)
- [Commands platform](/developers/api/commands-platform)
- [Agents](/developers/api/agents)
- [OAuth2](/developers/api/oauth2)
- [Integrations](/developers/api/integrations)
- [CLI](/developers/api/cli)
- [Plan · Projects](/developers/api/plan-projects)
- [Plan · Goals](/developers/api/plan-goals)
- [Plan · Boards](/developers/api/plan-boards)
- [Plan · Tasks](/developers/api/plan-tasks)
- [Plan · Comments & files](/developers/api/plan-collaboration)
- [Plan · Home & search](/developers/api/plan-home)
- [Plan · Notifications & reports](/developers/api/plan-notifications)

**Dailybot Plan**

- [Overview](/developers/plan)
- [Concepts](/developers/plan/concepts)
- [Quickstart](/developers/plan/quickstart)
- [Authentication & scopes](/developers/plan/authentication)
- [Agents on Plan](/developers/plan/agents)
- [Conventions](/developers/plan/conventions)
- [Errors](/developers/plan/errors)
- [CLI for Plan](/developers/plan/cli)
- [Agent skill](/developers/plan/agent-skill)
- [Recipe: live board](/developers/plan/recipes/board-live-updates)
- [Recipe: home in one request](/developers/plan/recipes/home-in-one-request)
- [Recipe: bulk create](/developers/plan/recipes/bulk-create)
- [Recipe: move on PR merge](/developers/plan/recipes/move-on-pr-merge) (this page)
- [Recipe: goal progress](/developers/plan/recipes/goal-progress)
- [Recipe: webhooks](/developers/plan/recipes/webhooks)

**API guides**

- [Errors & Status Codes](/developers/errors)
- [Rate Limits](/developers/rate-limits)
- [Conventions](/developers/conventions)
- [API Changelog](/developers/api-changelog)
- [Recipes](/developers/recipes)

**Developer Features**

- [Custom commands](/developers/custom-commands)
- [Serverless commands](/developers/serverless)
- [Webhooks & events](/developers/webhooks)
- [Automation API trigger](/developers/workflow-trigger)
- [Activity API](/developers/activity-api)

**CLI**

- [Overview](/developers/cli)
- [Authentication](/developers/cli-authentication)
- [Command reference](/developers/cli-reference)
- [CI/CD recipes](/developers/cli-ci-cd)
- [Configuration](/developers/cli-configuration)
- [Troubleshooting](/developers/cli-troubleshooting)

**Agent Skill**

- [Overview](/developers/agent-skill)
- [Skills catalog](/skills)

---

## Site navigation

**Product:**
- [Home](/)
- [Product](/product)
- [Pricing](/pricing)
- [Enterprise](/enterprise)
- [Integrations](/integrations)
- [Templates](/templates)

**Resources:**
- [Blog](/blog)
- [Academy](/academy)
- [Changelog](/changelog)
- [Help Center](/help)
- [Developers](/developers)
- [Agents](/agents)

**Company:**
- [About](/about)
- [Careers](/careers)
- [Security](/security)
- [Contact Sales](/demo)

**Connect:**
- [LinkedIn](https://www.linkedin.com/company/dailybot/)
- [X/Twitter](https://twitter.com/dailybot)
- [GitHub](https://github.com/Dailybot-Inc)
- [YouTube](https://www.youtube.com/channel/UC3uM9V52vwX7e3vQpCc4qvA)

