Bulk Upload Waste Water Treatments
const options = {
method: 'POST',
headers: {
'x-api-key': '<x-api-key>',
'x-organization-id': '<x-organization-id>',
'x-user-id': '<x-user-id>',
'Content-Type': 'application/json'
},
body: JSON.stringify({facility_id: '<string>', daily_waste_water_treatment_data: [{}]})
};
fetch('https://api.dcycle.io/api/v1/bulk/waste_water_treatments', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.dcycle.io/api/v1/bulk/waste_water_treatments"
payload = {
"facility_id": "<string>",
"daily_waste_water_treatment_data": [{}]
}
headers = {
"x-api-key": "<x-api-key>",
"x-organization-id": "<x-organization-id>",
"x-user-id": "<x-user-id>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)curl --request POST \
--url https://api.dcycle.io/api/v1/bulk/waste_water_treatments \
--header 'Content-Type: application/json' \
--header 'x-api-key: <x-api-key>' \
--header 'x-organization-id: <x-organization-id>' \
--header 'x-user-id: <x-user-id>' \
--data '
{
"facility_id": "<string>",
"daily_waste_water_treatment_data": [
{}
]
}
'Bulk Upload Waste Water Treatments
Create waste water treatment records in bulk with automatic data imputation
POST
/
api
/
v1
/
bulk
/
waste_water_treatments
Bulk Upload Waste Water Treatments
const options = {
method: 'POST',
headers: {
'x-api-key': '<x-api-key>',
'x-organization-id': '<x-organization-id>',
'x-user-id': '<x-user-id>',
'Content-Type': 'application/json'
},
body: JSON.stringify({facility_id: '<string>', daily_waste_water_treatment_data: [{}]})
};
fetch('https://api.dcycle.io/api/v1/bulk/waste_water_treatments', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.dcycle.io/api/v1/bulk/waste_water_treatments"
payload = {
"facility_id": "<string>",
"daily_waste_water_treatment_data": [{}]
}
headers = {
"x-api-key": "<x-api-key>",
"x-organization-id": "<x-organization-id>",
"x-user-id": "<x-user-id>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)curl --request POST \
--url https://api.dcycle.io/api/v1/bulk/waste_water_treatments \
--header 'Content-Type: application/json' \
--header 'x-api-key: <x-api-key>' \
--header 'x-organization-id: <x-organization-id>' \
--header 'x-user-id: <x-user-id>' \
--data '
{
"facility_id": "<string>",
"daily_waste_water_treatment_data": [
{}
]
}
'Bulk Upload Waste Water Treatments
Upload daily waste water treatment measurements in bulk for a waste water facility. This endpoint automatically imputes missing values using interpolation and moving averages.Important Constraints:
- Maximum 31 days of data per request
- The last entry must have complete data for all totalized fields
- Missing values are automatically imputed
- CH4 emissions cannot be negative
Request
Headers
string
required
Your API key for authenticationExample:
sk_live_1234567890abcdefstring
required
Your organization UUIDExample:
ff4adcc7-8172-45fe-9cf1-e90a6de53aa9string
required
Your user UUIDExample:
a1b2c3d4-e5f6-7890-abcd-ef1234567890Body Parameters
string
required
UUID of the waste water facilityExample:
"facility-uuid-here"array
required
Array of daily measurement records (max 31 days)Each daily record contains:
name(string, required): Description of the datameasurement_date(date, required): Date of measurement (YYYY-MM-DD)m3_water_in(float, optional): Input flow in m³m3_water_out(float, optional): Output flow in m³kg_bod_per_m3_wwt_line(float, optional): Input BOD in kg/m³kg_n_per_m3_wwt_line(float, optional): Nitrogen in kg/m³ (treatment line)kg_sludge(float, optional): Total evacuated sludge in kgst(float, optional): Proportion of solids (0-1)m3_biogas_engine(float, optional): Engine biogas in m³m3_biogas_flare(float, optional): Flare biogas in m³m3_biogas_boiler(float, optional): Boiler biogas in m³methane(float, optional): Methane proportion (0-1)kg_bod_per_kg_sludge_line(float, optional): BOD in sludge kg/kgkg_bod_per_m3_wwd_line(float, optional): BOD in discharge kg/m³kg_n_per_m3_wwd_line(float, optional): Nitrogen in discharge kg/m³
Last Entry Requirement: The last entry in your data array must have non-null values for:
m3_water_inm3_water_outkg_sludgem3_biogas_enginem3_biogas_flarem3_biogas_boiler
Response
Returns an array of created waste water treatment records with calculated emissions.[
{
"id": "treatment-uuid",
"name": "Waste Water Treatment Data Line 1",
"m3_water_in": 39245.33,
"m3_water_out": 31859.12,
"kg_sludge": 27140.0,
"kg_bod_per_m3_wwt_line": 0.185,
"kg_bod_per_kg_sludge_line": 0.012,
"kg_n_per_m3_wwt_line": 0.0912,
"kg_r_wwt_line": 2896.5,
"file_url": null,
"start_date": "2024-03-31",
"end_date": "2024-03-31",
"status": "uploaded",
"uploaded_by": "user-uuid",
"facility_id": "facility-uuid"
}
]
Example
curl -X POST "https://api.dcycle.io/api/v1/bulk/waste_water_treatments" \
-H "Authorization: Bearer ${DCYCLE_API_KEY}" \
-H "x-organization-id: ${DCYCLE_ORG_ID}" \
-H "x-user-id: ${DCYCLE_USER_ID}" \
-H "Content-Type: application/json" \
-d '{
"facility_id": "facility-uuid",
"daily_waste_water_treatment_data": [
{
"name": "Daily Treatment 2024-03-01",
"measurement_date": "2024-03-01",
"m3_water_in": 38000,
"m3_water_out": 30000,
"kg_bod_per_m3_wwt_line": 0.180,
"kg_n_per_m3_wwt_line": 0.090,
"kg_sludge": 25000,
"st": 0.24,
"m3_biogas_engine": 6000,
"m3_biogas_flare": 1200,
"m3_biogas_boiler": 60,
"methane": 0.6,
"kg_bod_per_kg_sludge_line": 0.012,
"kg_bod_per_m3_wwd_line": 0.007,
"kg_n_per_m3_wwd_line": 0.009
},
{
"name": "Daily Treatment 2024-03-02",
"measurement_date": "2024-03-02",
"m3_water_in": 39000,
"m3_water_out": 31000,
"kg_bod_per_m3_wwt_line": 0.185,
"kg_n_per_m3_wwt_line": 0.091,
"kg_sludge": 26000,
"st": 0.24,
"m3_biogas_engine": 6100,
"m3_biogas_flare": 1220,
"m3_biogas_boiler": 65,
"methane": 0.6,
"kg_bod_per_kg_sludge_line": 0.012,
"kg_bod_per_m3_wwd_line": 0.007,
"kg_n_per_m3_wwd_line": 0.0091
}
]
}'
import requests
import os
from datetime import date, timedelta
headers = {
"Authorization": f"Bearer {os.getenv('DCYCLE_API_KEY')}",
"x-organization-id": os.getenv("DCYCLE_ORG_ID"),
"x-user-id": os.getenv("DCYCLE_USER_ID"),
"Content-Type": "application/json"
}
facility_id = "facility-uuid"
# Generate 7 days of data
daily_data = []
start_date = date(2024, 3, 1)
for day in range(7):
current_date = start_date + timedelta(days=day)
daily_data.append({
"name": f"Daily Treatment {current_date}",
"measurement_date": current_date.isoformat(),
"m3_water_in": 38000 + (day * 100),
"m3_water_out": 30000 + (day * 80),
"kg_bod_per_m3_wwt_line": 0.180,
"kg_n_per_m3_wwt_line": 0.090,
"kg_sludge": 25000 + (day * 200),
"st": 0.24,
"m3_biogas_engine": 6000,
"m3_biogas_flare": 1200,
"m3_biogas_boiler": 60,
"methane": 0.6,
"kg_bod_per_kg_sludge_line": 0.012,
"kg_bod_per_m3_wwd_line": 0.007,
"kg_n_per_m3_wwd_line": 0.009
})
request_data = {
"facility_id": facility_id,
"daily_waste_water_treatment_data": daily_data
}
response = requests.post(
"https://api.dcycle.io/api/v1/bulk/waste_water_treatments",
headers=headers,
json=request_data
)
treatments = response.json()
print(f"✅ Created {len(treatments)} waste water treatment records")
for treatment in treatments:
print(f"- {treatment['start_date']}: {treatment['m3_water_in']} m³ in, {treatment['m3_water_out']} m³ out")
const axios = require('axios');
const headers = {
'Authorization': `Bearer ${process.env.DCYCLE_API_KEY}`,
'x-organization-id': process.env.DCYCLE_ORG_ID,
'x-user-id': process.env.DCYCLE_USER_ID,
'Content-Type': 'application/json'
};
const facilityId = 'facility-uuid';
// Generate 7 days of data
const dailyData = [];
const startDate = new Date('2024-03-01');
for (let day = 0; day < 7; day++) {
const currentDate = new Date(startDate);
currentDate.setDate(startDate.getDate() + day);
dailyData.push({
name: `Daily Treatment ${currentDate.toISOString().split('T')[0]}`,
measurement_date: currentDate.toISOString().split('T')[0],
m3_water_in: 38000 + (day * 100),
m3_water_out: 30000 + (day * 80),
kg_bod_per_m3_wwt_line: 0.180,
kg_n_per_m3_wwt_line: 0.090,
kg_sludge: 25000 + (day * 200),
st: 0.24,
m3_biogas_engine: 6000,
m3_biogas_flare: 1200,
m3_biogas_boiler: 60,
methane: 0.6,
kg_bod_per_kg_sludge_line: 0.012,
kg_bod_per_m3_wwd_line: 0.007,
kg_n_per_m3_wwd_line: 0.009
});
}
const requestData = {
facility_id: facilityId,
daily_waste_water_treatment_data: dailyData
};
axios.post(
'https://api.dcycle.io/api/v1/bulk/waste_water_treatments',
requestData,
{ headers }
)
.then(response => {
const treatments = response.data;
console.log(`✅ Created ${treatments.length} waste water treatment records`);
treatments.forEach(treatment => {
console.log(`- ${treatment.start_date}: ${treatment.m3_water_in} m³ in, ${treatment.m3_water_out} m³ out`);
});
})
.catch(error => console.error(error));
Data Imputation
The endpoint automatically fills missing values using these methods:Interpolation
Missing values are interpolated linearly between known values for:m3_water_inm3_water_outkg_sludgem3_biogas_enginem3_biogas_flarem3_biogas_boiler
Moving Average
Missing values are filled with 6-period moving average (forward/backward fill) for:kg_n_per_m3_wwt_linekg_bod_per_m3_wwt_linekg_bod_per_m3_wwd_linest(solid proportion)methanekg_bod_per_kg_sludge_linekg_n_per_m3_wwd_line
You can submit partial data for intermediate days. The endpoint will automatically fill gaps, but the last entry must have complete totalized values.
Common Errors
400 Bad Request - Facility Not Found
Cause: FACILITY_NOT_FOUND{
"detail": "FACILITY_NOT_FOUND",
"code": "BAD_REQUEST"
}
400 Bad Request - Maximum Rows Exceeded
Cause: MAXIMUM_ROWS_EXCEEDED{
"detail": "MAXIMUM_ROWS_EXCEEDED",
"code": "BAD_REQUEST"
}
400 Bad Request - Null Values in Last Row
Cause: NULL_VALUES_IN_LAST_ROW{
"detail": "NULL_VALUES_IN_LAST_ROW",
"code": "BAD_REQUEST"
}
m3_water_in, m3_water_out, kg_sludge, m3_biogas_engine, m3_biogas_flare, m3_biogas_boiler.
400 Bad Request - Negative Value
Cause: NEGATIVE_m3_water_in{
"detail": "NEGATIVE_m3_water_in",
"code": "BAD_REQUEST"
}
Best Practices
1. Submit Complete Final Entry
Always ensure the last entry has all required fields:# ✅ Good: Last entry is complete
daily_data = [
{
"measurement_date": "2024-03-01",
"m3_water_in": None, # Will be imputed
"m3_water_out": None, # Will be imputed
# ... other fields
},
{
"measurement_date": "2024-03-02",
"m3_water_in": 39000, # Complete
"m3_water_out": 31000, # Complete
"kg_sludge": 26000, # Complete
"m3_biogas_engine": 6100, # Complete
"m3_biogas_flare": 1220, # Complete
"m3_biogas_boiler": 65, # Complete
# ... all required fields present
}
]
2. Handle Date Ranges
Split large date ranges into multiple requests:def upload_monthly_data(facility_id, monthly_data):
# Split into chunks of max 31 days
chunk_size = 30
for i in range(0, len(monthly_data), chunk_size):
chunk = monthly_data[i:i + chunk_size]
response = requests.post(
"https://api.dcycle.io/api/v1/bulk/waste_water_treatments",
headers=headers,
json={
"facility_id": facility_id,
"daily_waste_water_treatment_data": chunk
}
)
print(f"Uploaded chunk {i//chunk_size + 1}: {len(chunk)} days")
3. Validate Before Upload
Check data quality before submitting:def validate_wwt_data(data):
# Check last entry completeness
last_entry = data[-1]
required_fields = ['m3_water_in', 'm3_water_out', 'kg_sludge',
'm3_biogas_engine', 'm3_biogas_flare', 'm3_biogas_boiler']
for field in required_fields:
if last_entry.get(field) is None:
raise ValueError(f"Last entry missing required field: {field}")
# Check date range
dates = [entry['measurement_date'] for entry in data]
date_range = (max(dates) - min(dates)).days + 1
if date_range > 31:
raise ValueError(f"Date range ({date_range} days) exceeds maximum of 31 days")
return True
# Use before upload
if validate_wwt_data(daily_data):
response = requests.post(url, headers=headers, json=request_data)
Related Endpoints
Delete Treatment
Remove a treatment record
Facilities
List waste water facilities
Was this page helpful?