Create Interim Report
curl --request POST \
--url https://api.n-3.co.uk/reports/drawdown \
--header 'Content-Type: application/json' \
--data '
{
"project_id": {},
"month": 123,
"year": 123,
"edition": 123,
"comments": "<string>",
"aggregate": {
"amount": 123,
"surplus_shortfall": 123
},
"facility": [
{
"facility_id": {},
"amount": 123,
"surplus_shortfall": 123
}
],
"riskStatus": [
{
"input_setting_id": {},
"risk_status_legend_id": {},
"notes": "<string>"
}
],
"visit": {
"date": "<string>",
"notes": "<string>",
"files": [
{
"filename": "<string>",
"s3_location": "<string>",
"file_size": 123,
"mime_type": "<string>"
}
]
}
}
'import requests
url = "https://api.n-3.co.uk/reports/drawdown"
payload = {
"project_id": {},
"month": 123,
"year": 123,
"edition": 123,
"comments": "<string>",
"aggregate": {
"amount": 123,
"surplus_shortfall": 123
},
"facility": [
{
"facility_id": {},
"amount": 123,
"surplus_shortfall": 123
}
],
"riskStatus": [
{
"input_setting_id": {},
"risk_status_legend_id": {},
"notes": "<string>"
}
],
"visit": {
"date": "<string>",
"notes": "<string>",
"files": [
{
"filename": "<string>",
"s3_location": "<string>",
"file_size": 123,
"mime_type": "<string>"
}
]
}
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
project_id: {},
month: 123,
year: 123,
edition: 123,
comments: '<string>',
aggregate: {amount: 123, surplus_shortfall: 123},
facility: [{facility_id: {}, amount: 123, surplus_shortfall: 123}],
riskStatus: [{input_setting_id: {}, risk_status_legend_id: {}, notes: '<string>'}],
visit: {
date: '<string>',
notes: '<string>',
files: [
{
filename: '<string>',
s3_location: '<string>',
file_size: 123,
mime_type: '<string>'
}
]
}
})
};
fetch('https://api.n-3.co.uk/reports/drawdown', 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.n-3.co.uk/reports/drawdown",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'project_id' => [
],
'month' => 123,
'year' => 123,
'edition' => 123,
'comments' => '<string>',
'aggregate' => [
'amount' => 123,
'surplus_shortfall' => 123
],
'facility' => [
[
'facility_id' => [
],
'amount' => 123,
'surplus_shortfall' => 123
]
],
'riskStatus' => [
[
'input_setting_id' => [
],
'risk_status_legend_id' => [
],
'notes' => '<string>'
]
],
'visit' => [
'date' => '<string>',
'notes' => '<string>',
'files' => [
[
'filename' => '<string>',
's3_location' => '<string>',
'file_size' => 123,
'mime_type' => '<string>'
]
]
]
]),
CURLOPT_HTTPHEADER => [
"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.n-3.co.uk/reports/drawdown"
payload := strings.NewReader("{\n \"project_id\": {},\n \"month\": 123,\n \"year\": 123,\n \"edition\": 123,\n \"comments\": \"<string>\",\n \"aggregate\": {\n \"amount\": 123,\n \"surplus_shortfall\": 123\n },\n \"facility\": [\n {\n \"facility_id\": {},\n \"amount\": 123,\n \"surplus_shortfall\": 123\n }\n ],\n \"riskStatus\": [\n {\n \"input_setting_id\": {},\n \"risk_status_legend_id\": {},\n \"notes\": \"<string>\"\n }\n ],\n \"visit\": {\n \"date\": \"<string>\",\n \"notes\": \"<string>\",\n \"files\": [\n {\n \"filename\": \"<string>\",\n \"s3_location\": \"<string>\",\n \"file_size\": 123,\n \"mime_type\": \"<string>\"\n }\n ]\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
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.post("https://api.n-3.co.uk/reports/drawdown")
.header("Content-Type", "application/json")
.body("{\n \"project_id\": {},\n \"month\": 123,\n \"year\": 123,\n \"edition\": 123,\n \"comments\": \"<string>\",\n \"aggregate\": {\n \"amount\": 123,\n \"surplus_shortfall\": 123\n },\n \"facility\": [\n {\n \"facility_id\": {},\n \"amount\": 123,\n \"surplus_shortfall\": 123\n }\n ],\n \"riskStatus\": [\n {\n \"input_setting_id\": {},\n \"risk_status_legend_id\": {},\n \"notes\": \"<string>\"\n }\n ],\n \"visit\": {\n \"date\": \"<string>\",\n \"notes\": \"<string>\",\n \"files\": [\n {\n \"filename\": \"<string>\",\n \"s3_location\": \"<string>\",\n \"file_size\": 123,\n \"mime_type\": \"<string>\"\n }\n ]\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.n-3.co.uk/reports/drawdown")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"project_id\": {},\n \"month\": 123,\n \"year\": 123,\n \"edition\": 123,\n \"comments\": \"<string>\",\n \"aggregate\": {\n \"amount\": 123,\n \"surplus_shortfall\": 123\n },\n \"facility\": [\n {\n \"facility_id\": {},\n \"amount\": 123,\n \"surplus_shortfall\": 123\n }\n ],\n \"riskStatus\": [\n {\n \"input_setting_id\": {},\n \"risk_status_legend_id\": {},\n \"notes\": \"<string>\"\n }\n ],\n \"visit\": {\n \"date\": \"<string>\",\n \"notes\": \"<string>\",\n \"files\": [\n {\n \"filename\": \"<string>\",\n \"s3_location\": \"<string>\",\n \"file_size\": 123,\n \"mime_type\": \"<string>\"\n }\n ]\n }\n}"
response = http.request(request)
puts response.read_body{
"400": {},
"403": {},
"404": {},
"id": {},
"created_date": "<string>",
"project_id": {},
"month": 123,
"year": 123,
"edition": 123,
"template_id": {},
"type": "<string>"
}Reports
Create Interim Report
Create a new interim report with comprehensive drawdown tracking, risk assessments, and site visit documentation
POST
/
reports
/
drawdown
Create Interim Report
curl --request POST \
--url https://api.n-3.co.uk/reports/drawdown \
--header 'Content-Type: application/json' \
--data '
{
"project_id": {},
"month": 123,
"year": 123,
"edition": 123,
"comments": "<string>",
"aggregate": {
"amount": 123,
"surplus_shortfall": 123
},
"facility": [
{
"facility_id": {},
"amount": 123,
"surplus_shortfall": 123
}
],
"riskStatus": [
{
"input_setting_id": {},
"risk_status_legend_id": {},
"notes": "<string>"
}
],
"visit": {
"date": "<string>",
"notes": "<string>",
"files": [
{
"filename": "<string>",
"s3_location": "<string>",
"file_size": 123,
"mime_type": "<string>"
}
]
}
}
'import requests
url = "https://api.n-3.co.uk/reports/drawdown"
payload = {
"project_id": {},
"month": 123,
"year": 123,
"edition": 123,
"comments": "<string>",
"aggregate": {
"amount": 123,
"surplus_shortfall": 123
},
"facility": [
{
"facility_id": {},
"amount": 123,
"surplus_shortfall": 123
}
],
"riskStatus": [
{
"input_setting_id": {},
"risk_status_legend_id": {},
"notes": "<string>"
}
],
"visit": {
"date": "<string>",
"notes": "<string>",
"files": [
{
"filename": "<string>",
"s3_location": "<string>",
"file_size": 123,
"mime_type": "<string>"
}
]
}
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
project_id: {},
month: 123,
year: 123,
edition: 123,
comments: '<string>',
aggregate: {amount: 123, surplus_shortfall: 123},
facility: [{facility_id: {}, amount: 123, surplus_shortfall: 123}],
riskStatus: [{input_setting_id: {}, risk_status_legend_id: {}, notes: '<string>'}],
visit: {
date: '<string>',
notes: '<string>',
files: [
{
filename: '<string>',
s3_location: '<string>',
file_size: 123,
mime_type: '<string>'
}
]
}
})
};
fetch('https://api.n-3.co.uk/reports/drawdown', 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.n-3.co.uk/reports/drawdown",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'project_id' => [
],
'month' => 123,
'year' => 123,
'edition' => 123,
'comments' => '<string>',
'aggregate' => [
'amount' => 123,
'surplus_shortfall' => 123
],
'facility' => [
[
'facility_id' => [
],
'amount' => 123,
'surplus_shortfall' => 123
]
],
'riskStatus' => [
[
'input_setting_id' => [
],
'risk_status_legend_id' => [
],
'notes' => '<string>'
]
],
'visit' => [
'date' => '<string>',
'notes' => '<string>',
'files' => [
[
'filename' => '<string>',
's3_location' => '<string>',
'file_size' => 123,
'mime_type' => '<string>'
]
]
]
]),
CURLOPT_HTTPHEADER => [
"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.n-3.co.uk/reports/drawdown"
payload := strings.NewReader("{\n \"project_id\": {},\n \"month\": 123,\n \"year\": 123,\n \"edition\": 123,\n \"comments\": \"<string>\",\n \"aggregate\": {\n \"amount\": 123,\n \"surplus_shortfall\": 123\n },\n \"facility\": [\n {\n \"facility_id\": {},\n \"amount\": 123,\n \"surplus_shortfall\": 123\n }\n ],\n \"riskStatus\": [\n {\n \"input_setting_id\": {},\n \"risk_status_legend_id\": {},\n \"notes\": \"<string>\"\n }\n ],\n \"visit\": {\n \"date\": \"<string>\",\n \"notes\": \"<string>\",\n \"files\": [\n {\n \"filename\": \"<string>\",\n \"s3_location\": \"<string>\",\n \"file_size\": 123,\n \"mime_type\": \"<string>\"\n }\n ]\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
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.post("https://api.n-3.co.uk/reports/drawdown")
.header("Content-Type", "application/json")
.body("{\n \"project_id\": {},\n \"month\": 123,\n \"year\": 123,\n \"edition\": 123,\n \"comments\": \"<string>\",\n \"aggregate\": {\n \"amount\": 123,\n \"surplus_shortfall\": 123\n },\n \"facility\": [\n {\n \"facility_id\": {},\n \"amount\": 123,\n \"surplus_shortfall\": 123\n }\n ],\n \"riskStatus\": [\n {\n \"input_setting_id\": {},\n \"risk_status_legend_id\": {},\n \"notes\": \"<string>\"\n }\n ],\n \"visit\": {\n \"date\": \"<string>\",\n \"notes\": \"<string>\",\n \"files\": [\n {\n \"filename\": \"<string>\",\n \"s3_location\": \"<string>\",\n \"file_size\": 123,\n \"mime_type\": \"<string>\"\n }\n ]\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.n-3.co.uk/reports/drawdown")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"project_id\": {},\n \"month\": 123,\n \"year\": 123,\n \"edition\": 123,\n \"comments\": \"<string>\",\n \"aggregate\": {\n \"amount\": 123,\n \"surplus_shortfall\": 123\n },\n \"facility\": [\n {\n \"facility_id\": {},\n \"amount\": 123,\n \"surplus_shortfall\": 123\n }\n ],\n \"riskStatus\": [\n {\n \"input_setting_id\": {},\n \"risk_status_legend_id\": {},\n \"notes\": \"<string>\"\n }\n ],\n \"visit\": {\n \"date\": \"<string>\",\n \"notes\": \"<string>\",\n \"files\": [\n {\n \"filename\": \"<string>\",\n \"s3_location\": \"<string>\",\n \"file_size\": 123,\n \"mime_type\": \"<string>\"\n }\n ]\n }\n}"
response = http.request(request)
puts response.read_body{
"400": {},
"403": {},
"404": {},
"id": {},
"created_date": "<string>",
"project_id": {},
"month": 123,
"year": 123,
"edition": 123,
"template_id": {},
"type": "<string>"
}Create a detailed interim report for tracking project progress during active project phases. This endpoint combines financial drawdown data, risk status assessments, and site visit documentation into a single comprehensive report.
Request Body
The unique identifier of the project for which the interim report is being created
The month of the reporting period (1-12)
The year of the reporting period
The edition number of the report (defaults to 1 for new reports)
General comments or notes about the project status for this reporting period
Array of risk assessment entries for the reporting period
Site visit information (optional, only include if a site visit occurred)
Show visit
Show visit
Date of the site visit in YYYY-MM-DD format
Detailed notes from the site visit
Array of files (photos, documents) from the site visit
Example Request
{
"project_id": "123456789",
"month": 6,
"year": 2024,
"edition": 1,
"comments": "Q2 progress showing strong advancement on main structure",
"aggregate": {
"amount": 150000,
"surplus_shortfall": 5000
},
"facility": [
{
"facility_id": "987654321",
"amount": 75000,
"surplus_shortfall": 2500
},
{
"facility_id": "987654322",
"amount": 75000,
"surplus_shortfall": 2500
}
],
"riskStatus": [
{
"input_setting_id": "111",
"risk_status_legend_id": "222",
"notes": "Risk level maintained at low due to good weather conditions"
},
{
"input_setting_id": "333",
"risk_status_legend_id": "444",
"notes": "Material delivery risk increased due to supply chain delays"
}
],
"visit": {
"date": "2024-06-15",
"notes": "Foundation work completed ahead of schedule. Steel frame installation proceeding well. No safety issues observed.",
"files": [
{
"filename": "foundation_complete.jpg",
"s3_location": "projects/123456789/site-visits/2024-06/foundation_complete.jpg",
"file_size": 2048576,
"mime_type": "image/jpeg"
},
{
"filename": "steel_frame_progress.jpg",
"s3_location": "projects/123456789/site-visits/2024-06/steel_frame_progress.jpg",
"file_size": 1536789,
"mime_type": "image/jpeg"
}
]
}
}
Response
Returns the created report with its unique identifier:Unique identifier of the created interim report
ISO timestamp when the report was created
ID of the associated project
Month of the reporting period
Year of the reporting period
Edition number of the report
ID of the template used for report generation
Report type (will be “INTERIM_REPORT”)
Example Response
{
"id": "789012345",
"created_date": "2024-06-20T10:30:00.000Z",
"project_id": "123456789",
"month": 6,
"year": 2024,
"edition": 1,
"template_id": "555666777",
"type": "INTERIM_REPORT"
}
Automatic Actions
When an interim report is successfully created, the system automatically:- Creates Project Event: Logs a
REPORT_UPLOADEDevent for audit tracking - Updates Project Comments: Saves the comments field to the project record
- Applies Template: Uses the first available interim report template for the environment
- Validates Data: Ensures all required data relationships exist and are valid
Error Responses
Bad Request - Missing required fields or invalid data format
{
"statusCode": 400,
"message": "Project ID is required",
"error": "Bad Request"
}
Forbidden - User does not have access to the specified project
{
"statusCode": 403,
"message": "User does not have access to this project",
"error": "Forbidden"
}
Not Found - Project or referenced entities not found
{
"statusCode": 404,
"message": "Project not found",
"error": "Not Found"
}
Notes
- All monetary amounts should be provided as numbers (not strings)
- Site visit information is optional - omit the entire
visitobject if no visit occurred - Risk status assessments are required for all interim reports
- The system automatically determines the appropriate template based on the project’s environment
- File uploads must be completed separately before creating the report - provide S3 locations in the request
⌘I

