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": [
{}
]
}
'Legacy API. This page documents the previous version of the API. This particular
operation has no documented equivalent in the current API yet, so this remains the
documented way to do it. Prefer the current API for everything it already covers.
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 facilityRetrieve available options from
GET /api/v1/facilitiesExample: "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?