Skip to main content
POST
https://api.dcycle.io
/
api
/
v1
/
invoices
Create Invoice
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({
    type: '<string>',
    base_quantity: 123,
    unit_id: '<string>',
    start_date: '<string>',
    end_date: '<string>',
    uploaded_by: '<string>',
    facility_percentages: [{}],
    facility_id: '<string>',
    invoice_id: '<string>',
    supplier_id: '<string>',
    facility_fuel_id: '<string>',
    cups: '<string>',
    file_url: '<string>',
    custom_emission_factor_id: '<string>',
    toc: '<string>'
  })
};

fetch('https://api.dcycle.io/api/v1/invoices', options)
  .then(res => res.json())
  .then(res => console.log(res))
  .catch(err => console.error(err));
{
  "id": "<string>",
  "type": "<string>",
  "base_quantity": 123,
  "quantity": 123,
  "unit_id": "<string>",
  "original_quantity": 123,
  "original_unit_id": "<string>",
  "start_date": "<string>",
  "end_date": "<string>",
  "percentage": 123,
  "status": "<string>",
  "facility_id": "<string>",
  "uploaded_by": "<string>",
  "facility_percentages": [
    {}
  ],
  "source_invoice_id": "<string>",
  "supplier_id": "<string>",
  "facility_fuel_id": "<string>",
  "invoice_id": "<string>",
  "cups": "<string>",
  "file_url": "<string>",
  "custom_emission_factor_id": "<string>",
  "custom_emission_factor": {},
  "toc": "<string>"
}

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

Headers

x-api-key
string
required
Your API key for authenticationExample: sk_live_1234567890abcdef
x-organization-id
string
required
Your organization UUIDExample: ff4adcc7-8172-45fe-9cf1-e90a6de53aa9
x-user-id
string
required
Your user UUIDExample: a1b2c3d4-e5f6-7890-abcd-ef1234567890

Body Parameters

type
string
required
Type of consumption invoiceValid values: electricity, heat, water, recharge, processExample: "electricity"
base_quantity
number
required
Consumption quantity in the specified unitExample: 15000.5
unit_id
string
required
UUID of the unit of measurementCommon units:
  • Electricity: kilowatt_hour_(kwh)
  • Natural gas: cubic_meter_(mΒ³)
  • Water: cubic_meter_(mΒ³)
  • Diesel/Gasoline: liter_(l)
Example: "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
start_date
string
required
Invoice period start date (ISO 8601 format)Example: "2024-11-01"
end_date
string
required
Invoice period end date (ISO 8601 format)Example: "2024-11-30"
uploaded_by
string
required
UUID of the user creating the invoiceExample: "b2c3d4e5-f6g7-8901-bcde-fg2345678901"
facility_percentages
array
required
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"
  }
]
facility_id
string
deprecated
Deprecated: Use facility_percentages insteadLegacy single facility ID field. Maintained for backwards compatibility.
invoice_id
string
External invoice reference number (e.g., supplier invoice number)Example: "INV-2024-11-001"
supplier_id
string
UUID of the energy/utility supplierExample: "f6g7h8i9-j0k1-2345-fghi-jk6789012345"
facility_fuel_id
string
UUID of the facility fuel type (for heat invoices)Required for type: "heat" invoicesExample: "g7h8i9j0-k1l2-3456-ghij-kl7890123456"
cups
string
CUPS code for Spanish electricity metersFormat: ES + 20 digits + 2 letters (e.g., ES0031406398765432GH0F)Example: "ES0031406398765432GH0F"
file_url
string
URL to the invoice file (PDF, image, etc.) stored in S3Example: "https://s3.amazonaws.com/dcycle-files/invoices/..."
custom_emission_factor_id
string
UUID of custom emission factor group (if using custom factors)Example: "h8i9j0k1-l2m3-4567-hijk-lm8901234567"
toc
string
Transport operation category (for logistics-related invoices)Example: "van_diesel"

Response

id
string
UUID of the created invoice
type
string
Invoice type
base_quantity
number
Original consumption quantity
quantity
number
Allocated consumption quantity for this facility (base_quantity Γ— percentage)
unit_id
string
Unit of measurement UUID
original_quantity
number
Original quantity if converted from currency
original_unit_id
string
Original unit ID if converted
start_date
string
Invoice period start date
end_date
string
Invoice period end date
percentage
number
Allocation percentage for primary facility
status
string
Invoice status: "loading" (processing), "active" (completed), "error" (failed)
facility_id
string
Primary facility UUID
uploaded_by
string
User UUID who created the invoice
facility_percentages
array
Complete distribution across all facilities
source_invoice_id
string
Parent invoice UUID for distributed invoices
supplier_id
string
Supplier UUID if specified
facility_fuel_id
string
Facility fuel UUID if specified
invoice_id
string
External invoice reference
cups
string
CUPS code if specified
file_url
string
Invoice file URL if specified
custom_emission_factor_id
string
Custom emission factor UUID if specified
custom_emission_factor
object
Custom emission factor details if applicable
toc
string
Transport operation category if specified

Example

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:
  1. The facility_id exists and belongs to the organization_id
  2. The facility is not archived
  3. 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:
  1. loading: Initial state after creation. System is calculating emissions.
  2. active: Processing complete. Emissions calculated and available.
  3. 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

Date Format

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:
TypeRequired FieldsOptional Fields
electricitytype, base_quantity, unit_id, dates, facility_percentagessupplier_id, cups, file_url
heattype, base_quantity, unit_id, dates, facility_percentages, facility_fuel_idsupplier_id, file_url
watertype, base_quantity, unit_id, dates, facility_percentagessupplier_id, file_url
rechargetype, base_quantity, unit_id, dates, facility_percentagessupplier_id, toc
processtype, base_quantity, unit_id, dates, facility_percentagescustom_emission_factor_id

Units

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:
  1. Consumption quantity and unit
  2. Facility location (country-specific emission factors)
  3. Time period (emission factors vary by year/month)
  4. Supplier (if renewable energy contract)
  5. 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):
  1. Upload file to S3 using presigned URL (separate endpoint)
  2. Include the S3 URL in file_url field
  3. System will retain file for audit trail