Create Records From File Reading
const options = {
method: 'POST',
headers: {
'x-api-key': '<x-api-key>',
'x-organization-id': '<x-organization-id>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
file_readings: [{}],
'file_readings[].id': '<string>',
'file_readings[].excluded_items': [123],
'file_readings[].supplier_id': '<string>',
'file_readings[].stationary_fuel_id': '<string>',
'file_readings[].refrigerant_fuel_id': '<string>',
'file_readings[].custom_emission_factor_id': '<string>',
'file_readings[].facilities': [{}],
facilities: [{}],
'facilities[].id': '<string>',
'facilities[].percentage': 123,
project_id: '<string>',
supplier_id: '<string>'
})
};
fetch('https://api.dcycle.io/v1/files/readings', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.dcycle.io/v1/files/readings"
payload = {
"file_readings": [{}],
"file_readings[].id": "<string>",
"file_readings[].excluded_items": [123],
"file_readings[].supplier_id": "<string>",
"file_readings[].stationary_fuel_id": "<string>",
"file_readings[].refrigerant_fuel_id": "<string>",
"file_readings[].custom_emission_factor_id": "<string>",
"file_readings[].facilities": [{}],
"facilities": [{}],
"facilities[].id": "<string>",
"facilities[].percentage": 123,
"project_id": "<string>",
"supplier_id": "<string>"
}
headers = {
"x-api-key": "<x-api-key>",
"x-organization-id": "<x-organization-id>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)curl --request POST \
--url https://api.dcycle.io/v1/files/readings \
--header 'Content-Type: application/json' \
--header 'x-api-key: <x-api-key>' \
--header 'x-organization-id: <x-organization-id>' \
--data '
{
"file_readings": [
{}
],
"file_readings[].id": "<string>",
"file_readings[].excluded_items": [
123
],
"file_readings[].supplier_id": "<string>",
"file_readings[].stationary_fuel_id": "<string>",
"file_readings[].refrigerant_fuel_id": "<string>",
"file_readings[].custom_emission_factor_id": "<string>",
"file_readings[].facilities": [
{}
],
"facilities": [
{}
],
"facilities[].id": "<string>",
"facilities[].percentage": 123,
"project_id": "<string>",
"supplier_id": "<string>"
}
'Create Records From File Reading
Create invoices or wastes from the readings of a file and link the created records to facilities
POST
/
v1
/
files
/
readings
Create Records From File Reading
const options = {
method: 'POST',
headers: {
'x-api-key': '<x-api-key>',
'x-organization-id': '<x-organization-id>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
file_readings: [{}],
'file_readings[].id': '<string>',
'file_readings[].excluded_items': [123],
'file_readings[].supplier_id': '<string>',
'file_readings[].stationary_fuel_id': '<string>',
'file_readings[].refrigerant_fuel_id': '<string>',
'file_readings[].custom_emission_factor_id': '<string>',
'file_readings[].facilities': [{}],
facilities: [{}],
'facilities[].id': '<string>',
'facilities[].percentage': 123,
project_id: '<string>',
supplier_id: '<string>'
})
};
fetch('https://api.dcycle.io/v1/files/readings', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.dcycle.io/v1/files/readings"
payload = {
"file_readings": [{}],
"file_readings[].id": "<string>",
"file_readings[].excluded_items": [123],
"file_readings[].supplier_id": "<string>",
"file_readings[].stationary_fuel_id": "<string>",
"file_readings[].refrigerant_fuel_id": "<string>",
"file_readings[].custom_emission_factor_id": "<string>",
"file_readings[].facilities": [{}],
"facilities": [{}],
"facilities[].id": "<string>",
"facilities[].percentage": 123,
"project_id": "<string>",
"supplier_id": "<string>"
}
headers = {
"x-api-key": "<x-api-key>",
"x-organization-id": "<x-organization-id>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)curl --request POST \
--url https://api.dcycle.io/v1/files/readings \
--header 'Content-Type: application/json' \
--header 'x-api-key: <x-api-key>' \
--header 'x-organization-id: <x-organization-id>' \
--data '
{
"file_readings": [
{}
],
"file_readings[].id": "<string>",
"file_readings[].excluded_items": [
123
],
"file_readings[].supplier_id": "<string>",
"file_readings[].stationary_fuel_id": "<string>",
"file_readings[].refrigerant_fuel_id": "<string>",
"file_readings[].custom_emission_factor_id": "<string>",
"file_readings[].facilities": [
{}
],
"facilities": [
{}
],
"facilities[].id": "<string>",
"facilities[].percentage": 123,
"project_id": "<string>",
"supplier_id": "<string>"
}
'← Files
This endpoint converts the parsed readings of ONE file into downstream business records:
Cause: A classification of the file is still being read, or its reading failed
Cause: Missing required fields (
- water, electricity, gas, fuel delivery, or recharge invoices
- waste records
Request
Headers
string
required
Your API key for authenticationExample:
sk_live_1234567890abcdefstring
required
Your organization UUIDExample:
a8315ef3-dd50-43f8-b7ce-d839e68d51faBody
object[]
required
The readings of one file: all of them, each once. At least one item.
string
required
File reading UUID returned in
reading.id (or classifications[].reading.id) from GET /v1/files/readings.integer[]
Positions (from
0) of the items of this reading’s content.items to leave out.string
Supplier for the records of this reading. Same meaning as the top-level
supplier_id, which it overrides.string
Fuel for the records of a stationary combustion reading.
string
Gas for the records of a recharges reading.
string
Custom emission factor for the records of this reading.
object[]
Facilities for the records of this reading, with the shape of the top-level
facilities, which it overrides.object[]
required
Facilities to link to the created records.
string
required
Facility UUID.
number
required
Allocation percentage as a decimal between
0 and 1. The total must be less than or equal to 1.0.string
Optional project UUID. When present, created invoices are also linked to that project.Retrieve available options from
GET /v1/projects/extendedstring
Optional supplier UUID. Only used for electricity readings. When provided, it overrides the
supplier_id extracted from the file reading content. Required when any target facility is
located in Spain and the reading did not resolve a supplier automatically.Retrieve available options from
GET /api/v1/suppliers — electricity retailersResponse
Returns an array of the created records (HTTP 201), in the order of the file’s classifications. The exact shape depends on the category of each reading — invoices for energy categories, waste records fordocument::wastes.
Files with several readings
Every file has one classification and one reading today, and no endpoint creates a second one yet. This section
describes the contract a file that bills several services (water and gas on one invoice) will follow, so an
integration written now keeps working.
- Send all the readings of the file in
file_readings. A request that leaves one out is refused with409 FILE_READINGS_INCOMPLETEand nothing is deleted or created. - Every reading must be read successfully:
409 FILE_READINGS_NOT_READYotherwise. - With more than one reading, the supplier, fuel and custom emission factor go on each reading. The top-level
supplier_idis refused with422 REVIEW_DECISIONS_MUST_BE_PER_READING, because it cannot say which reading it is for. The top-levelfacilitiesstill applies to every reading that sends none of its own. - The readings of two different files in one request are refused with
400 MULTIPLE_FILES_NOT_SUPPORTED. - The records of all the readings are created together or not at all.
Example
curl -X POST "https://api.dcycle.io/v1/files/readings" \
-H "x-api-key: ${DCYCLE_API_KEY}" \
-H "x-organization-id: ${DCYCLE_ORG_ID}" \
-H "Content-Type: application/json" \
-d '{
"file_readings": [
{
"id": "22222222-2222-2222-2222-222222222222"
}
],
"facilities": [
{
"id": "33333333-3333-3333-3333-333333333333",
"percentage": 1.0
}
]
}'
import os
import requests
response = requests.post(
"https://api.dcycle.io/v1/files/readings",
headers={
"x-api-key": os.environ["DCYCLE_API_KEY"],
"x-organization-id": os.environ["DCYCLE_ORG_ID"],
"Content-Type": "application/json",
},
json={
"file_readings": [
{
"id": "22222222-2222-2222-2222-222222222222",
}
],
"facilities": [
{
"id": "33333333-3333-3333-3333-333333333333",
"percentage": 1.0,
}
],
},
timeout=30,
)
print(response.json())
const axios = require('axios');
axios.post('https://api.dcycle.io/v1/files/readings', {
file_readings: [
{ id: '22222222-2222-2222-2222-222222222222' },
],
facilities: [
{ id: '33333333-3333-3333-3333-333333333333', percentage: 1.0 },
],
}, {
headers: {
'x-api-key': process.env.DCYCLE_API_KEY,
'x-organization-id': process.env.DCYCLE_ORG_ID,
'Content-Type': 'application/json',
},
}).then(response => console.log(response.data));
Behavior by Category
invoice::watercreates water invoicesinvoice::electricitycreates electricity invoicesinvoice::stationary_combustion(andinvoice::gas/invoice::fuel_delivery, its labels before the merge) creates combustion invoices, one per fuel line, with each line’s fuelinvoice::rechargescreates recharge invoicesdocument::wastescreates waste records
Common Errors
401 Unauthorized
Cause: Missing or invalid API key{"detail": "Invalid API key for organization", "code": "INVALID_API_KEY"}
403 Forbidden
Cause: The authenticated user is not a member of the organization{"detail": "Logged User is not Member of Organization", "code": "LOGGED_USER_NOT_MEMBER"}
400 Bad Request
Cause: The readings belong to more than one file{"detail": "Multiple files are not supported at the moment", "code": "MULTIPLE_FILES_NOT_SUPPORTED"}
409 Conflict
Cause: The request does not carry exactly the readings the file has now. Either one is missing, or one no longer exists: reprocessing a file deletes its readings, so a save that arrives after a reprocess is refused instead of creating records from a reading that is gone. Fetch the readings again and resend.{
"code": "FILE_READINGS_INCOMPLETE",
"detail": {
"message": "A review must include every reading of the file; reload it and submit them together",
"missing_reading_ids": ["55555555-5555-5555-5555-555555555555"],
"unexpected_reading_ids": []
}
}
{
"code": "FILE_READINGS_NOT_READY",
"detail": "The file is still being read or failed to read: invoice::stationary_combustion"
}
422 Unprocessable Entity
Cause: A top-levelsupplier_id (or fuel, or custom emission factor) with more than one reading
{
"code": "REVIEW_DECISIONS_MUST_BE_PER_READING",
"detail": "With several readings, send the supplier, fuel and custom emission factor on each reading"
}
file_readings, facilities), an empty or repeated file_readings, or invalid allocation percentages
{
"detail": [
{
"loc": ["body", "file_readings"],
"msg": "field required",
"type": "value_error.missing"
}
]
}
- This endpoint requires a successful file reading with
content.items. - For Spain electricity facilities, supplier information may still be required depending on the extracted reading.
- After records are created, the file will appear as
linked=trueinGET /v1/files/readings.
Related Endpoints
List File Readings
Retrieve readings to get file reading IDs
Update Reading
Edit extracted content before creating records
Upload Files
Upload new files via presigned S3 URLs
List Invoices
View invoices created from file readings
Was this page helpful?