curl --request PUT \
--url https://api.cadanapay.com/v1/persons/{personId}/milestones/{milestoneId} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"title": "Design phase",
"amount": {
"amount": 10000,
"currency": "USD"
},
"description": "<string>",
"dueDate": "2026-09-30",
"contractId": "d6e7f8a9-0123-4567-def0-678901234567",
"documentIds": [
"8ef9a712-cdae-4110-b1ea-9ba95abbee6e"
]
}
'import requests
url = "https://api.cadanapay.com/v1/persons/{personId}/milestones/{milestoneId}"
payload = {
"title": "Design phase",
"amount": {
"amount": 10000,
"currency": "USD"
},
"description": "<string>",
"dueDate": "2026-09-30",
"contractId": "d6e7f8a9-0123-4567-def0-678901234567",
"documentIds": ["8ef9a712-cdae-4110-b1ea-9ba95abbee6e"]
}
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({
title: 'Design phase',
amount: {amount: 10000, currency: 'USD'},
description: '<string>',
dueDate: '2026-09-30',
contractId: 'd6e7f8a9-0123-4567-def0-678901234567',
documentIds: ['8ef9a712-cdae-4110-b1ea-9ba95abbee6e']
})
};
fetch('https://api.cadanapay.com/v1/persons/{personId}/milestones/{milestoneId}', 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.cadanapay.com/v1/persons/{personId}/milestones/{milestoneId}",
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([
'title' => 'Design phase',
'amount' => [
'amount' => 10000,
'currency' => 'USD'
],
'description' => '<string>',
'dueDate' => '2026-09-30',
'contractId' => 'd6e7f8a9-0123-4567-def0-678901234567',
'documentIds' => [
'8ef9a712-cdae-4110-b1ea-9ba95abbee6e'
]
]),
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.cadanapay.com/v1/persons/{personId}/milestones/{milestoneId}"
payload := strings.NewReader("{\n \"title\": \"Design phase\",\n \"amount\": {\n \"amount\": 10000,\n \"currency\": \"USD\"\n },\n \"description\": \"<string>\",\n \"dueDate\": \"2026-09-30\",\n \"contractId\": \"d6e7f8a9-0123-4567-def0-678901234567\",\n \"documentIds\": [\n \"8ef9a712-cdae-4110-b1ea-9ba95abbee6e\"\n ]\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.cadanapay.com/v1/persons/{personId}/milestones/{milestoneId}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"title\": \"Design phase\",\n \"amount\": {\n \"amount\": 10000,\n \"currency\": \"USD\"\n },\n \"description\": \"<string>\",\n \"dueDate\": \"2026-09-30\",\n \"contractId\": \"d6e7f8a9-0123-4567-def0-678901234567\",\n \"documentIds\": [\n \"8ef9a712-cdae-4110-b1ea-9ba95abbee6e\"\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.cadanapay.com/v1/persons/{personId}/milestones/{milestoneId}")
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 \"title\": \"Design phase\",\n \"amount\": {\n \"amount\": 10000,\n \"currency\": \"USD\"\n },\n \"description\": \"<string>\",\n \"dueDate\": \"2026-09-30\",\n \"contractId\": \"d6e7f8a9-0123-4567-def0-678901234567\",\n \"documentIds\": [\n \"8ef9a712-cdae-4110-b1ea-9ba95abbee6e\"\n ]\n}"
response = http.request(request)
puts response.read_body{
"code": "invalid_request_body",
"message": "The request body provided is not valid",
"params": {
"field": "Value is invalid."
}
}{
"code": "resource_not_found",
"message": "Requested resource could not be found."
}{
"code": "internal_error",
"message": "An unexpected error occurred. Please try again later."
}Update milestone
Update a planned milestone. documentIds are file ids from the upload-url flow and replace the milestone’s documents.
curl --request PUT \
--url https://api.cadanapay.com/v1/persons/{personId}/milestones/{milestoneId} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"title": "Design phase",
"amount": {
"amount": 10000,
"currency": "USD"
},
"description": "<string>",
"dueDate": "2026-09-30",
"contractId": "d6e7f8a9-0123-4567-def0-678901234567",
"documentIds": [
"8ef9a712-cdae-4110-b1ea-9ba95abbee6e"
]
}
'import requests
url = "https://api.cadanapay.com/v1/persons/{personId}/milestones/{milestoneId}"
payload = {
"title": "Design phase",
"amount": {
"amount": 10000,
"currency": "USD"
},
"description": "<string>",
"dueDate": "2026-09-30",
"contractId": "d6e7f8a9-0123-4567-def0-678901234567",
"documentIds": ["8ef9a712-cdae-4110-b1ea-9ba95abbee6e"]
}
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({
title: 'Design phase',
amount: {amount: 10000, currency: 'USD'},
description: '<string>',
dueDate: '2026-09-30',
contractId: 'd6e7f8a9-0123-4567-def0-678901234567',
documentIds: ['8ef9a712-cdae-4110-b1ea-9ba95abbee6e']
})
};
fetch('https://api.cadanapay.com/v1/persons/{personId}/milestones/{milestoneId}', 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.cadanapay.com/v1/persons/{personId}/milestones/{milestoneId}",
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([
'title' => 'Design phase',
'amount' => [
'amount' => 10000,
'currency' => 'USD'
],
'description' => '<string>',
'dueDate' => '2026-09-30',
'contractId' => 'd6e7f8a9-0123-4567-def0-678901234567',
'documentIds' => [
'8ef9a712-cdae-4110-b1ea-9ba95abbee6e'
]
]),
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.cadanapay.com/v1/persons/{personId}/milestones/{milestoneId}"
payload := strings.NewReader("{\n \"title\": \"Design phase\",\n \"amount\": {\n \"amount\": 10000,\n \"currency\": \"USD\"\n },\n \"description\": \"<string>\",\n \"dueDate\": \"2026-09-30\",\n \"contractId\": \"d6e7f8a9-0123-4567-def0-678901234567\",\n \"documentIds\": [\n \"8ef9a712-cdae-4110-b1ea-9ba95abbee6e\"\n ]\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.cadanapay.com/v1/persons/{personId}/milestones/{milestoneId}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"title\": \"Design phase\",\n \"amount\": {\n \"amount\": 10000,\n \"currency\": \"USD\"\n },\n \"description\": \"<string>\",\n \"dueDate\": \"2026-09-30\",\n \"contractId\": \"d6e7f8a9-0123-4567-def0-678901234567\",\n \"documentIds\": [\n \"8ef9a712-cdae-4110-b1ea-9ba95abbee6e\"\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.cadanapay.com/v1/persons/{personId}/milestones/{milestoneId}")
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 \"title\": \"Design phase\",\n \"amount\": {\n \"amount\": 10000,\n \"currency\": \"USD\"\n },\n \"description\": \"<string>\",\n \"dueDate\": \"2026-09-30\",\n \"contractId\": \"d6e7f8a9-0123-4567-def0-678901234567\",\n \"documentIds\": [\n \"8ef9a712-cdae-4110-b1ea-9ba95abbee6e\"\n ]\n}"
response = http.request(request)
puts response.read_body{
"code": "invalid_request_body",
"message": "The request body provided is not valid",
"params": {
"field": "Value is invalid."
}
}{
"code": "resource_not_found",
"message": "Requested resource could not be found."
}{
"code": "internal_error",
"message": "An unexpected error occurred. Please try again later."
}Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Headers
Required when using a Platform API token. The tenant key identifying which business to operate on.
Path Parameters
The unique identifier for the person
The unique identifier for the milestone
Body
"Design phase"
Show child attributes
Show child attributes
"2026-09-30"
Optional contract this milestone falls under; must belong to the same person and be fully signed. The invoice generated on completion carries the same contractId.
"d6e7f8a9-0123-4567-def0-678901234567"
File ids from POST /v1/files/upload-url (purpose milestone-document); replace the milestone's documents
Response
Milestone updated successfully