curl --request PUT \
--url https://api.doers.sh/v2/rounds/{day}/{index}/plan \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"taskIds": [
"3c90c3cc-0d44-4b50-8888-8dd25736052a"
],
"movedTaskIds": [
"3c90c3cc-0d44-4b50-8888-8dd25736052a"
],
"roundEndMin": 720,
"roundStartMin": 719
}
'import requests
url = "https://api.doers.sh/v2/rounds/{day}/{index}/plan"
payload = {
"taskIds": ["3c90c3cc-0d44-4b50-8888-8dd25736052a"],
"movedTaskIds": ["3c90c3cc-0d44-4b50-8888-8dd25736052a"],
"roundEndMin": 720,
"roundStartMin": 719
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
taskIds: ['3c90c3cc-0d44-4b50-8888-8dd25736052a'],
movedTaskIds: ['3c90c3cc-0d44-4b50-8888-8dd25736052a'],
roundEndMin: 720,
roundStartMin: 719
})
};
fetch('https://api.doers.sh/v2/rounds/{day}/{index}/plan', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.doers.sh/v2/rounds/{day}/{index}/plan",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'taskIds' => [
'3c90c3cc-0d44-4b50-8888-8dd25736052a'
],
'movedTaskIds' => [
'3c90c3cc-0d44-4b50-8888-8dd25736052a'
],
'roundEndMin' => 720,
'roundStartMin' => 719
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.doers.sh/v2/rounds/{day}/{index}/plan"
payload := strings.NewReader("{\n \"taskIds\": [\n \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n ],\n \"movedTaskIds\": [\n \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n ],\n \"roundEndMin\": 720,\n \"roundStartMin\": 719\n}")
req, _ := http.NewRequest("PUT", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.put("https://api.doers.sh/v2/rounds/{day}/{index}/plan")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"taskIds\": [\n \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n ],\n \"movedTaskIds\": [\n \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n ],\n \"roundEndMin\": 720,\n \"roundStartMin\": 719\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.doers.sh/v2/rounds/{day}/{index}/plan")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"taskIds\": [\n \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n ],\n \"movedTaskIds\": [\n \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n ],\n \"roundEndMin\": 720,\n \"roundStartMin\": 719\n}"
response = http.request(request)
puts response.read_body{
"round": {
"day": "2023-12-25",
"index": 0,
"taskIds": [
"<string>"
],
"engaged": true,
"closedAt": 123
},
"removedFromOtherRounds": 0
}{
"error": {
"code": "<string>",
"message": "<string>",
"details": [
{
"field": "<string>",
"message": "<string>"
}
]
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"details": [
{
"field": "<string>",
"message": "<string>"
}
]
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"details": [
{
"field": "<string>",
"message": "<string>"
}
]
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"details": [
{
"field": "<string>",
"message": "<string>"
}
]
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"details": [
{
"field": "<string>",
"message": "<string>"
}
]
}
}Plan a round
Replaces the round’s mini-plan. At most 3 tasks — one substantial and two small is the shape it was built for; a longer list is not a plan.
A task belongs to one round of the day. Planning it here removes it from any other round of the same day, so it cannot appear twice.
An empty list clears the plan. The round itself is created if it does not exist yet. When movedTaskIds and both interval bounds are supplied, those tasks are also softly scheduled onto the target day without changing deadlines or completion state.
curl --request PUT \
--url https://api.doers.sh/v2/rounds/{day}/{index}/plan \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"taskIds": [
"3c90c3cc-0d44-4b50-8888-8dd25736052a"
],
"movedTaskIds": [
"3c90c3cc-0d44-4b50-8888-8dd25736052a"
],
"roundEndMin": 720,
"roundStartMin": 719
}
'import requests
url = "https://api.doers.sh/v2/rounds/{day}/{index}/plan"
payload = {
"taskIds": ["3c90c3cc-0d44-4b50-8888-8dd25736052a"],
"movedTaskIds": ["3c90c3cc-0d44-4b50-8888-8dd25736052a"],
"roundEndMin": 720,
"roundStartMin": 719
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
taskIds: ['3c90c3cc-0d44-4b50-8888-8dd25736052a'],
movedTaskIds: ['3c90c3cc-0d44-4b50-8888-8dd25736052a'],
roundEndMin: 720,
roundStartMin: 719
})
};
fetch('https://api.doers.sh/v2/rounds/{day}/{index}/plan', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.doers.sh/v2/rounds/{day}/{index}/plan",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'taskIds' => [
'3c90c3cc-0d44-4b50-8888-8dd25736052a'
],
'movedTaskIds' => [
'3c90c3cc-0d44-4b50-8888-8dd25736052a'
],
'roundEndMin' => 720,
'roundStartMin' => 719
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.doers.sh/v2/rounds/{day}/{index}/plan"
payload := strings.NewReader("{\n \"taskIds\": [\n \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n ],\n \"movedTaskIds\": [\n \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n ],\n \"roundEndMin\": 720,\n \"roundStartMin\": 719\n}")
req, _ := http.NewRequest("PUT", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.put("https://api.doers.sh/v2/rounds/{day}/{index}/plan")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"taskIds\": [\n \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n ],\n \"movedTaskIds\": [\n \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n ],\n \"roundEndMin\": 720,\n \"roundStartMin\": 719\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.doers.sh/v2/rounds/{day}/{index}/plan")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"taskIds\": [\n \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n ],\n \"movedTaskIds\": [\n \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n ],\n \"roundEndMin\": 720,\n \"roundStartMin\": 719\n}"
response = http.request(request)
puts response.read_body{
"round": {
"day": "2023-12-25",
"index": 0,
"taskIds": [
"<string>"
],
"engaged": true,
"closedAt": 123
},
"removedFromOtherRounds": 0
}{
"error": {
"code": "<string>",
"message": "<string>",
"details": [
{
"field": "<string>",
"message": "<string>"
}
]
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"details": [
{
"field": "<string>",
"message": "<string>"
}
]
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"details": [
{
"field": "<string>",
"message": "<string>"
}
]
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"details": [
{
"field": "<string>",
"message": "<string>"
}
]
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"details": [
{
"field": "<string>",
"message": "<string>"
}
]
}
}Authorizations
A pc_… token generated from Settings > API & MCP.
Path Parameters
Local day key, YYYY-MM-DD.
^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))$Which round of the day, counting from zero.
0 <= x <= 5Body
In display order. Pass an empty array to clear the plan.
3Identifier of a row.
^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$The subset moved by this request and softly scheduled into the interval.
1 - 3 elementsIdentifier of a row.
^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$Exclusive target interval end, in minutes after midnight.
1 <= x <= 1440Inclusive target interval start, in minutes after midnight.
0 <= x <= 1439