Create Invoice
Create a new consumption invoice (electricity, heat, water, etc.) for your organization. This endpoint supports both single-facility invoices and distributed invoices (split across multiple facilities with percentage allocation).
This endpoint automatically calculates CO2e emissions based on the invoice type, quantity, and location. For distributed invoices, emissions are proportionally allocated across facilities.
Request
Your API key for authentication Example: sk_live_1234567890abcdef
Your organization UUID Example: ff4adcc7-8172-45fe-9cf1-e90a6de53aa9
Your user UUID Example: a1b2c3d4-e5f6-7890-abcd-ef1234567890
Body Parameters
Type of consumption invoice Valid values: electricity, heat, water, recharge, processExample: "electricity"
Consumption quantity in the specified unit Example: 15000.5
UUID of the unit of measurement Common units:
Electricity: kilowatt_hour_(kwh)
Natural gas: cubic_meter_(mΒ³)
Water: cubic_meter_(mΒ³)
Diesel/Gasoline: liter_(l)
Example: "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
Invoice period start date (ISO 8601 format) Example: "2024-11-01"
Invoice period end date (ISO 8601 format) Example: "2024-11-30"
UUID of the user creating the invoice Example: "b2c3d4e5-f6g7-8901-bcde-fg2345678901"
Array of facility allocation objects. Sum of percentages must equal 1.0 (100%) Facility Percentage Object:
organization_id (string, UUID, required) - Organization that owns the facility
facility_id (string, UUID, required) - Facility to allocate to
percentage (number, required) - Allocation percentage (0.0-1.0)
company_name (string, optional) - Company name for reference
facility_name (string, optional) - Facility name for reference
Example: [
{
"organization_id" : "c3d4e5f6-g7h8-9012-cdef-gh3456789012" ,
"facility_id" : "d4e5f6g7-h8i9-0123-defg-hi4567890123" ,
"percentage" : 1.0 ,
"company_name" : "Acme Corp" ,
"facility_name" : "Madrid Office"
}
]
For distributed invoices (multiple facilities): [
{
"organization_id" : "c3d4e5f6-g7h8-9012-cdef-gh3456789012" ,
"facility_id" : "d4e5f6g7-h8i9-0123-defg-hi4567890123" ,
"percentage" : 0.6 ,
"company_name" : "Acme Corp" ,
"facility_name" : "Madrid Office"
},
{
"organization_id" : "c3d4e5f6-g7h8-9012-cdef-gh3456789012" ,
"facility_id" : "e5f6g7h8-i9j0-1234-efgh-ij5678901234" ,
"percentage" : 0.4 ,
"company_name" : "Acme Corp" ,
"facility_name" : "Barcelona Office"
}
]
Deprecated: Use facility_percentages insteadLegacy single facility ID field. Maintained for backwards compatibility.
External invoice reference number (e.g., supplier invoice number) Example: "INV-2024-11-001"
UUID of the energy/utility supplier Example: "f6g7h8i9-j0k1-2345-fghi-jk6789012345"
UUID of the facility fuel type (for heat invoices) Required for type: "heat" invoices Example: "g7h8i9j0-k1l2-3456-ghij-kl7890123456"
CUPS code for Spanish electricity meters Format: ES + 20 digits + 2 letters (e.g., ES0031406398765432GH0F) Example: "ES0031406398765432GH0F"
URL to the invoice file (PDF, image, etc.) stored in S3 Example: "https://s3.amazonaws.com/dcycle-files/invoices/..."
custom_emission_factor_id
UUID of custom emission factor group (if using custom factors) Example: "h8i9j0k1-l2m3-4567-hijk-lm8901234567"
Transport operation category (for logistics-related invoices) Example: "van_diesel"
Response
UUID of the created invoice
Original consumption quantity
Allocated consumption quantity for this facility (base_quantity Γ percentage)
Original quantity if converted from currency
Original unit ID if converted
Invoice period start date
Allocation percentage for primary facility
Invoice status: "loading" (processing), "active" (completed), "error" (failed)
User UUID who created the invoice
Complete distribution across all facilities
Parent invoice UUID for distributed invoices
Supplier UUID if specified
Facility fuel UUID if specified
External invoice reference
Invoice file URL if specified
custom_emission_factor_id
Custom emission factor UUID if specified
Custom emission factor details if applicable
Transport operation category if specified
Example
cURL - Single Facility
cURL - Distributed Invoice
Python - Single Facility
Python - Distributed Invoice
JavaScript
curl -X POST "https://api.dcycle.io/api/v1/invoices" \
-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 '{
"type": "electricity",
"base_quantity": 15000,
"unit_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"start_date": "2024-11-01",
"end_date": "2024-11-30",
"uploaded_by": "b2c3d4e5-f6g7-8901-bcde-fg2345678901",
"invoice_id": "E-2024-11-001",
"cups": "ES0031406398765432GH0F",
"supplier_id": "c3d4e5f6-g7h8-9012-cdef-gh3456789012",
"facility_percentages": [
{
"organization_id": "d4e5f6g7-h8i9-0123-defg-hi4567890123",
"facility_id": "e5f6g7h8-i9j0-1234-efgh-ij5678901234",
"percentage": 1.0,
"company_name": "Acme Corp",
"facility_name": "Madrid Office"
}
]
}'
Successful Response
{
"id" : "a1b2c3d4-e5f6-7890-abcd-ef1234567890" ,
"type" : "electricity" ,
"base_quantity" : 15000.0 ,
"quantity" : 15000.0 ,
"unit_id" : "b2c3d4e5-f6g7-8901-bcde-fg2345678901" ,
"original_quantity" : null ,
"original_unit_id" : null ,
"start_date" : "2024-11-01" ,
"end_date" : "2024-11-30" ,
"percentage" : 1.0 ,
"status" : "loading" ,
"facility_id" : "e5f6g7h8-i9j0-1234-efgh-ij5678901234" ,
"uploaded_by" : "b2c3d4e5-f6g7-8901-bcde-fg2345678901" ,
"facility_percentages" : [
{
"organization_id" : "d4e5f6g7-h8i9-0123-defg-hi4567890123" ,
"facility_id" : "e5f6g7h8-i9j0-1234-efgh-ij5678901234" ,
"percentage" : 1.0 ,
"company_name" : "Acme Corp" ,
"facility_name" : "Madrid Office"
}
],
"source_invoice_id" : null ,
"supplier_id" : "c3d4e5f6-g7h8-9012-cdef-gh3456789012" ,
"facility_fuel_id" : null ,
"invoice_id" : "E-2024-11-001" ,
"cups" : "ES0031406398765432GH0F" ,
"file_url" : null ,
"custom_emission_factor_id" : null ,
"custom_emission_factor" : null ,
"toc" : null
}
Distributed Invoice Response
{
"id" : "g7h8i9j0-k1l2-3456-ghij-kl7890123456" ,
"type" : "heat" ,
"base_quantity" : 5000.0 ,
"quantity" : 3000.0 ,
"unit_id" : "f6g7h8i9-j0k1-2345-fghi-jk6789012345" ,
"original_quantity" : null ,
"original_unit_id" : null ,
"start_date" : "2024-11-01" ,
"end_date" : "2024-11-30" ,
"percentage" : 0.6 ,
"status" : "loading" ,
"facility_id" : "e5f6g7h8-i9j0-1234-efgh-ij5678901234" ,
"uploaded_by" : "b2c3d4e5-f6g7-8901-bcde-fg2345678901" ,
"facility_percentages" : [
{
"organization_id" : "d4e5f6g7-h8i9-0123-defg-hi4567890123" ,
"facility_id" : "e5f6g7h8-i9j0-1234-efgh-ij5678901234" ,
"percentage" : 0.6 ,
"company_name" : "Acme Corp" ,
"facility_name" : "Madrid Office"
},
{
"organization_id" : "d4e5f6g7-h8i9-0123-defg-hi4567890123" ,
"facility_id" : "h8i9j0k1-l2m3-4567-hijk-lm8901234567" ,
"percentage" : 0.4 ,
"company_name" : "Acme Corp" ,
"facility_name" : "Barcelona Office"
}
],
"source_invoice_id" : "g7h8i9j0-k1l2-3456-ghij-kl7890123456" ,
"supplier_id" : null ,
"facility_fuel_id" : "i9j0k1l2-m3n4-5678-ijkl-mn9012345678" ,
"invoice_id" : "H-2024-11-015" ,
"cups" : null ,
"file_url" : null ,
"custom_emission_factor_id" : null ,
"custom_emission_factor" : null ,
"toc" : null
}
Common Errors
400 Bad Request - Invalid Total Percentage
Cause: Sum of facility_percentages does not equal 1.0
{
"detail" : "INVALID_TOTAL_PERCENTAGE" ,
"code" : "VALIDATION_ERROR"
}
Solution: Ensure the sum of all percentage values in facility_percentages equals exactly 1.0 (100%).
400 Bad Request - Invalid Invoice Type
Cause: Unsupported invoice type
{
"detail" : "Bad invoice type: xyz. It must be one of ('heat', 'electricity', 'water', 'recharge', 'process')" ,
"code" : "VALIDATION_ERROR"
}
Solution: Use only valid invoice types: heat, electricity, water, recharge, process
400 Bad Request - Invalid Facility
Cause: Facility doesnβt belong to the specified organization or is archived
{
"detail" : "Bad facility_id: xxx. It must belong to the provided organization_id yyy" ,
"code" : "VALIDATION_ERROR"
}
Solution: Verify that:
The facility_id exists and belongs to the organization_id
The facility is not archived
You have access to the organization
403 Forbidden
Cause: User doesnβt have permission to create invoices for the specified organization
{
"detail" : "ORGANIZATION_ID_IS_NOT_UNDER_PARENT_ORGANIZATION" ,
"code" : "FORBIDDEN"
}
Solution: Verify that x-organization-id matches the organizations in facility_percentages and you have proper permissions.
404 Not Found - Organization Not Found
Cause: Organization ID in facility_percentages doesnβt exist
{
"detail" : "Bad organization_id: xxx. Organization not found" ,
"code" : "NOT_FOUND"
}
Solution: Use valid organization UUIDs that exist in the system.
Use Cases
Single Facility Electricity Invoice
Create an electricity invoice for one facility:
def create_electricity_invoice (facility_id, kwh, start_date, end_date, invoice_number):
"""Create electricity invoice for a single facility"""
invoice_data = {
"type" : "electricity" ,
"base_quantity" : kwh,
"unit_id" : "kwh-unit-id" , # Get from units endpoint
"start_date" : start_date,
"end_date" : end_date,
"uploaded_by" : user_id,
"invoice_id" : invoice_number,
"supplier_id" : "supplier-id" , # Your electricity supplier
"facility_percentages" : [
{
"organization_id" : org_id,
"facility_id" : facility_id,
"percentage" : 1.0
}
]
}
response = requests.post(
"https://api.dcycle.io/api/v1/invoices" ,
headers = headers,
json = invoice_data
)
return response.json()
# Example: Create invoice for 15,000 kWh
invoice = create_electricity_invoice(
facility_id = "facility-uuid" ,
kwh = 15000 ,
start_date = "2024-11-01" ,
end_date = "2024-11-30" ,
invoice_number = "E-2024-11-001"
)
Distributed Heat Invoice
Split a shared heating bill across multiple facilities:
def create_shared_heating_invoice (facilities, total_m3, start_date, end_date):
"""Create distributed heat invoice across facilities"""
# Calculate percentages based on facility sizes
total_size = sum (f[ 'size_m2' ] for f in facilities)
facility_percentages = []
for facility in facilities:
percentage = facility[ 'size_m2' ] / total_size
facility_percentages.append({
"organization_id" : org_id,
"facility_id" : facility[ 'id' ],
"percentage" : round (percentage, 4 ), # Round to avoid floating point errors
"facility_name" : facility[ 'name' ]
})
# Verify percentages sum to 1.0
total_percentage = sum (f[ 'percentage' ] for f in facility_percentages)
if abs (total_percentage - 1.0 ) > 0.0001 :
# Adjust last percentage to ensure exact 1.0
facility_percentages[ - 1 ][ 'percentage' ] += ( 1.0 - total_percentage)
invoice_data = {
"type" : "heat" ,
"base_quantity" : total_m3,
"unit_id" : "m3-unit-id" ,
"start_date" : start_date,
"end_date" : end_date,
"uploaded_by" : user_id,
"facility_fuel_id" : "natural-gas-id" ,
"facility_percentages" : facility_percentages
}
response = requests.post(
"https://api.dcycle.io/api/v1/invoices" ,
headers = headers,
json = invoice_data
)
return response.json()
# Example: Shared heating across 3 facilities
facilities = [
{ "id" : "facility-1-uuid" , "name" : "Building A" , "size_m2" : 1000 },
{ "id" : "facility-2-uuid" , "name" : "Building B" , "size_m2" : 1500 },
{ "id" : "facility-3-uuid" , "name" : "Building C" , "size_m2" : 500 }
]
invoice = create_shared_heating_invoice(
facilities = facilities,
total_m3 = 5000 ,
start_date = "2024-11-01" ,
end_date = "2024-11-30"
)
Corporate Distribution
Headquarters distributing utility bills to subsidiaries:
def distribute_utility_to_subsidiaries (invoice_type, quantity, subsidiaries):
"""Distribute utility invoice across subsidiary organizations"""
facility_percentages = []
for subsidiary in subsidiaries:
facility_percentages.append({
"organization_id" : subsidiary[ 'org_id' ],
"facility_id" : subsidiary[ 'facility_id' ],
"percentage" : subsidiary[ 'cost_allocation' ],
"company_name" : subsidiary[ 'company_name' ],
"facility_name" : subsidiary[ 'facility_name' ]
})
invoice_data = {
"type" : invoice_type,
"base_quantity" : quantity,
"unit_id" : get_unit_id_for_type(invoice_type),
"start_date" : "2024-11-01" ,
"end_date" : "2024-11-30" ,
"uploaded_by" : user_id,
"facility_percentages" : facility_percentages
}
response = requests.post(
"https://api.dcycle.io/api/v1/invoices" ,
headers = headers,
json = invoice_data
)
return response.json()
# Example: HQ distributing water bill to 3 subsidiaries
subsidiaries = [
{
"org_id" : "subsidiary-1-org-id" ,
"facility_id" : "subsidiary-1-facility-id" ,
"cost_allocation" : 0.5 ,
"company_name" : "Subsidiary A" ,
"facility_name" : "Main Office"
},
{
"org_id" : "subsidiary-2-org-id" ,
"facility_id" : "subsidiary-2-facility-id" ,
"cost_allocation" : 0.3 ,
"company_name" : "Subsidiary B" ,
"facility_name" : "Regional Office"
},
{
"org_id" : "subsidiary-3-org-id" ,
"facility_id" : "subsidiary-3-facility-id" ,
"cost_allocation" : 0.2 ,
"company_name" : "Subsidiary C" ,
"facility_name" : "Branch Office"
}
]
invoice = distribute_utility_to_subsidiaries(
invoice_type = "water" ,
quantity = 1000 ,
subsidiaries = subsidiaries
)
Batch Invoice Creation
Create multiple invoices efficiently:
def create_monthly_invoices (facilities, month, year):
"""Create invoices for all facilities for a given month"""
from datetime import datetime
import calendar
# Calculate month dates
start_date = f " { year } - { month :02d } -01"
last_day = calendar.monthrange(year, month)[ 1 ]
end_date = f " { year } - { month :02d } - { last_day } "
created_invoices = []
for facility in facilities:
invoice_data = {
"type" : "electricity" ,
"base_quantity" : facility[ 'monthly_kwh' ],
"unit_id" : "kwh-unit-id" ,
"start_date" : start_date,
"end_date" : end_date,
"uploaded_by" : user_id,
"supplier_id" : facility[ 'supplier_id' ],
"facility_percentages" : [
{
"organization_id" : org_id,
"facility_id" : facility[ 'id' ],
"percentage" : 1.0 ,
"facility_name" : facility[ 'name' ]
}
]
}
try :
response = requests.post(
"https://api.dcycle.io/api/v1/invoices" ,
headers = headers,
json = invoice_data
)
created_invoices.append(response.json())
print ( f "β Created invoice for { facility[ 'name' ] } " )
except Exception as e:
print ( f "β Failed for { facility[ 'name' ] } : {str (e) } " )
return created_invoices
# Example: Create November 2024 invoices for all facilities
facilities = [
{ "id" : "fac-1" , "name" : "Madrid Office" , "monthly_kwh" : 15000 , "supplier_id" : "sup-1" },
{ "id" : "fac-2" , "name" : "Barcelona Office" , "monthly_kwh" : 12000 , "supplier_id" : "sup-1" },
{ "id" : "fac-3" , "name" : "Valencia Office" , "monthly_kwh" : 8000 , "supplier_id" : "sup-2" }
]
invoices = create_monthly_invoices(facilities, month = 11 , year = 2024 )
print ( f "Created {len (invoices) } invoices" )
Special Notes
Invoice Status Workflow
Invoices go through the following status workflow:
loading : Initial state after creation. System is calculating emissions.
active : Processing complete. Emissions calculated and available.
error : Processing failed. Check error_messages field in GET response.
Typically, invoices move from loading to active within a few seconds.
Distributed Invoices
When creating distributed invoices (multiple facilities):
The system creates one parent invoice + N child invoices (one per facility)
The parent invoice ID is returned in the response
All child invoices reference the parent via source_invoice_id
Emissions are automatically calculated proportionally for each facility
Percentages must sum to exactly 1.0 (100%)
Use cases for distributed invoices:
Shared utility bills across office floors
Corporate headquarters allocating costs
Multi-tenant buildings
Franchise operations with centralized billing
Dates must be provided in ISO 8601 format: YYYY-MM-DD
Valid examples:
"2024-11-01"
"2024-12-31"
The system will handle timezone conversion based on facility location.
Invoice Types and Required Fields
Different invoice types have different requirements:
Type Required Fields Optional Fields electricitytype, base_quantity, unit_id, dates, facility_percentages supplier_id, cups, file_url heattype, base_quantity, unit_id, dates, facility_percentages, facility_fuel_id supplier_id, file_url watertype, base_quantity, unit_id, dates, facility_percentages supplier_id, file_url rechargetype, base_quantity, unit_id, dates, facility_percentages supplier_id, toc processtype, base_quantity, unit_id, dates, facility_percentages custom_emission_factor_id
Common unit UUIDs for different consumption types:
Electricity : kilowatt_hour_(kwh)
Natural Gas : cubic_meter_(mΒ³)
Diesel/Gasoline : liter_(l)
Water : cubic_meter_(mΒ³)
Use the Units endpoint to get the complete list of available units and their UUIDs.
CUPS Validation
For Spanish electricity invoices, if you provide a cups code:
Format: ES + 20 digits + 2 letters
Example: ES0031406398765432GH0F
The system validates format but doesnβt verify existence with utility companies
Emission Calculation
CO2e emissions are calculated automatically based on:
Consumption quantity and unit
Facility location (country-specific emission factors)
Time period (emission factors vary by year/month)
Supplier (if renewable energy contract)
Custom emission factors (if specified)
For electricity, the system calculates:
Scope 2 (consumption) emissions
Scope 3 (generation + T&D) emissions
File Attachments
To attach invoice files (PDF, images):
Upload file to S3 using presigned URL (separate endpoint)
Include the S3 URL in file_url field
System will retain file for audit trail