Skip to main content

Endpoint

POST /api/quotations
Creates a new quotation with nested sections and items. This endpoint is implemented in src/controllers/quotationController.js:14.

Request Body

All fields are required. The request must include a complete quotation object with at least one section containing at least one item.

Required Fields

FieldTypeDescription
factoryStringFactory or project identifier
fixStringFix reference number
description_quotationStringOverall description of the quotation
subtotalNumberSubtotal before additional costs
unexpectedNumberUnexpected costs or contingency
ivaNumberVAT/IVA tax amount
administratitiveNumberAdministrative costs
utilityNumberUtility or profit margin
total_priceNumberFinal total price
sectionsArrayArray of section objects (must have at least one)
Each object in the sections array must contain:
FieldTypeDescription
description_sectionsStringDescription of the section
section_priceNumberTotal price for this section
itemsArrayArray of item objects (must have at least one)
Each object in the items array must contain:
FieldTypeDescription
item_nameStringName of the item
item_descriptionStringDetailed item description
item_totalNumberTotal cost for this item (quantity × item_value)
quantityNumberQuantity of items
unityStringUnit of measurement
item_valueNumberUnit price per item

Creating a Quotation

1

Prepare quotation data

Organize your quotation with factory info, fix reference, and description.
2

Structure sections

Group related items into logical sections (e.g., “Foundation Work”, “Electrical”, “Plumbing”).
3

Add items to sections

Define individual items with quantities, units, and pricing for each section.
4

Calculate totals

Compute subtotal, taxes, administrative costs, and final total_price.
5

Send POST request

Submit the complete JSON payload to the API endpoint.

Request Example

Basic Quotation with Single Section

{
  "factory": "Construction Co. Factory A",
  "fix": "FIX-2026-001",
  "description_quotation": "Residential building foundation work",
  "subtotal": 25000.00,
  "unexpected": 1250.00,
  "iva": 4987.50,
  "administratitive": 1500.00,
  "utility": 2500.00,
  "total_price": 35237.50,
  "sections": [
    {
      "description_sections": "Foundation and Structural Work",
      "section_price": 25000.00,
      "items": [
        {
          "item_name": "Concrete Foundation",
          "item_description": "High-strength concrete mix for foundation base",
          "item_total": 15000.00,
          "quantity": 30,
          "unity": "m3",
          "item_value": 500.00
        },
        {
          "item_name": "Steel Rebar",
          "item_description": "Grade 60 steel reinforcement bars",
          "item_total": 10000.00,
          "quantity": 2000,
          "unity": "kg",
          "item_value": 5.00
        }
      ]
    }
  ]
}

Complete Quotation with Multiple Sections

Response

Success Response (201 Created)

{
  "message": "Cotización almacenada correctamente",
  "quotation": {
    "_id": "65abc123def456789",
    "factory": "Construction Co. Factory A",
    "fix": "FIX-2026-001",
    "description_quotation": "Residential building foundation work",
    "subtotal": 25000.00,
    "unexpected": 1250.00,
    "iva": 4987.50,
    "administratitive": 1500.00,
    "utility": 2500.00,
    "total_price": 35237.50,
    "sections": [
      {
        "description_sections": "Foundation and Structural Work",
        "section_price": 25000.00,
        "items": [
          {
            "item_name": "Concrete Foundation",
            "item_description": "High-strength concrete mix for foundation base",
            "item_total": 15000.00,
            "quantity": 30,
            "unity": "m3",
            "item_value": 500.00,
            "_id": "65abc123def456790"
          },
          {
            "item_name": "Steel Rebar",
            "item_description": "Grade 60 steel reinforcement bars",
            "item_total": 10000.00,
            "quantity": 2000,
            "unity": "kg",
            "item_value": 5.00,
            "_id": "65abc123def456791"
          }
        ],
        "_id": "65abc123def456792"
      }
    ],
    "__v": 0
  }
}

Error Responses

{
  "error": "Formato de JSON inválido"
}
This error occurs when:
  • Any required root-level field is missing
  • sections is not an array
  • Any numeric field is undefined (note: 0 is valid)
  • Required nested fields in sections or items are missing
{
  "message": "Error al almacenar la cotización",
  "error": "[Error details]"
}
This error occurs when there’s a database or server-side issue.

Validation Logic

The controller implements validation at src/controllers/quotationController.js:18-24:
if (!data || !data.factory || !data.fix || !data.description_quotation || 
    data.subtotal === undefined || data.unexpected === undefined || 
    data.iva === undefined || data.administratitive === undefined || 
    data.utility === undefined || data.total_price === undefined || 
    !Array.isArray(data.sections)) {
  return res.status(400).json({ error: "Formato de JSON inválido" });
}
Notice that numeric fields check for undefined rather than falsy values. This means you can send 0 as a valid value for any numeric field.

Best Practices

Always ensure that:
  • item_total equals quantity × item_value for each item
  • section_price represents the sum of all item_total values in that section
  • Financial calculations are accurate before submission
Consider these tips:
  • Use descriptive section names that group related work
  • Include detailed item descriptions for clarity
  • Use standard units of measurement (m2, m3, kg, units, meters)
  • Double-check all calculations before submitting

Code Example

Using JavaScript Fetch API

const createQuotation = async () => {
  const quotationData = {
    factory: "Construction Co. Factory A",
    fix: "FIX-2026-001",
    description_quotation: "Residential building foundation work",
    subtotal: 25000.00,
    unexpected: 1250.00,
    iva: 4987.50,
    administratitive: 1500.00,
    utility: 2500.00,
    total_price: 35237.50,
    sections: [
      {
        description_sections: "Foundation and Structural Work",
        section_price: 25000.00,
        items: [
          {
            item_name: "Concrete Foundation",
            item_description: "High-strength concrete mix for foundation base",
            item_total: 15000.00,
            quantity: 30,
            unity: "m3",
            item_value: 500.00
          },
          {
            item_name: "Steel Rebar",
            item_description: "Grade 60 steel reinforcement bars",
            item_total: 10000.00,
            quantity: 2000,
            unity: "kg",
            item_value: 5.00
          }
        ]
      }
    ]
  };

  try {
    const response = await fetch('http://localhost:3000/api/quotations', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(quotationData)
    });

    const result = await response.json();
    
    if (response.ok) {
      console.log('Quotation created:', result.quotation._id);
      return result.quotation;
    } else {
      console.error('Error:', result.error || result.message);
      throw new Error(result.error || result.message);
    }
  } catch (error) {
    console.error('Request failed:', error);
    throw error;
  }
};

Using cURL

curl -X POST http://localhost:3000/api/quotations \
  -H "Content-Type: application/json" \
  -d '{
    "factory": "Construction Co. Factory A",
    "fix": "FIX-2026-001",
    "description_quotation": "Residential building foundation work",
    "subtotal": 25000.00,
    "unexpected": 1250.00,
    "iva": 4987.50,
    "administratitive": 1500.00,
    "utility": 2500.00,
    "total_price": 35237.50,
    "sections": [
      {
        "description_sections": "Foundation and Structural Work",
        "section_price": 25000.00,
        "items": [
          {
            "item_name": "Concrete Foundation",
            "item_description": "High-strength concrete mix for foundation base",
            "item_total": 15000.00,
            "quantity": 30,
            "unity": "m3",
            "item_value": 500.00
          },
          {
            "item_name": "Steel Rebar",
            "item_description": "Grade 60 steel reinforcement bars",
            "item_total": 10000.00,
            "quantity": 2000,
            "unity": "kg",
            "item_value": 5.00
          }
        ]
      }
    ]
  }'

Build docs developers (and LLMs) love