> ## Documentation Index
> Fetch the complete documentation index at: https://code.dcycle.io/llms.txt
> Use this file to discover all available pages before exploring further.

# List Invoice Filter Options

> Every value available in each invoice filter dropdown for one facility and invoice type, in a single call

[← Invoices API](/api-reference/invoices/overview)

Get the contents of all seven invoice filter dropdowns for one facility and invoice type, in a single call — CUPS codes, suppliers, uploaders, sources, stationary fuels, refrigerant fuels and supply contracts.

<Note>
  **The lists do not cascade.** Each list is the full universe of values that exist for the `(facility, type)` pair, and is **not** narrowed by whatever filters the user has already selected. This is deliberate: it keeps multi-select dropdowns stable, so picking a supplier does not empty the fuel list underneath it.

  The consequence to design around: a user can combine two options that no invoice actually has, and get an empty result. The lists tell you what exists on the facility, not which combinations are valid together.
</Note>

<Warning>
  **`type` is free text, not a closed list.** An unrecognised type is not rejected — it simply matches no invoices, and every one of the seven lists comes back empty. The values the enum defines are `heat`, `electricity`, `water`, `recharge`, `process` and `waste_water_treatment`.

  So "this facility has no invoice data" and "I sent `electric` instead of `electricity`" produce the same response. Check the spelling before concluding the facility is empty.
</Warning>

## Request

### Headers

<ParamField header="x-organization-id" type="string" required>
  UUID of the organization you are working in.

  **Format:** UUID
</ParamField>

<ParamField header="x-api-key" type="string">
  Your API key.
</ParamField>

### Query Parameters

<ParamField query="facility_id" type="string" required>
  UUID of the facility whose invoices you are filtering.

  The facility is resolved across the organization family — the header organization **and its accepted descendants** — so a holding can read a subsidiary's filter options. A facility outside that perimeter returns `404`, never `403`.

  **Format:** UUID
</ParamField>

<ParamField query="type" type="string" required>
  Invoice type.

  **Accepted values:** `heat`, `electricity`, `water`, `recharge`, `process`, `waste_water_treatment`
</ParamField>

## Response

Seven lists, always present, each possibly empty.

<ResponseField name="cups" type="array[string]">
  CUPS codes found on this facility's invoices. Plain strings — relevant for Spanish electricity and gas supplies.
</ResponseField>

<ResponseField name="suppliers" type="array[object]">
  Suppliers, as `{ id, name }`.
</ResponseField>

<ResponseField name="uploaded_by" type="array[object]">
  The users who uploaded invoices.

  <Expandable title="User Option">
    <ResponseField name="id" type="string">
      User UUID.
    </ResponseField>

    <ResponseField name="first_name" type="string">
      Given name.
    </ResponseField>

    <ResponseField name="last_name" type="string">
      Family name.
    </ResponseField>

    <ResponseField name="email" type="string">
      Email address — useful as the disambiguator when two users share a name.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="sources" type="array[string]">
  Where the invoices came from, as plain strings.
</ResponseField>

<ResponseField name="stationary_fuels" type="array[object]">
  Stationary combustion fuels present on the invoices, as `{ id, name }`.
</ResponseField>

<ResponseField name="refrigerant_fuels" type="array[object]">
  Refrigerant gases present on the invoices, as `{ id, name }`.
</ResponseField>

<ResponseField name="supply_contracts" type="array[object]">
  Supply contracts, as `{ id, name }`. Note that `name` carries the contract's **CUPS**, not a contract title — so this list and `cups` above can show the same codes in two different shapes.
</ResponseField>

<Note>
  **Two shapes in one response.** `cups` and `sources` are arrays of plain strings; the other five are arrays of objects. Send `id` back as the filter value for the object lists, and the string itself for the other two.
</Note>

## Example

<CodeGroup>
  ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}}
  curl -X GET "https://api.dcycle.io/v1/invoices/filter-options?facility_id=YOUR_FACILITY_ID&type=electricity" \
    -H "x-api-key: YOUR_API_KEY" \
    -H "x-organization-id: YOUR_ORGANIZATION_ID"
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
  import requests

  HEADERS = {
      "x-api-key": "YOUR_API_KEY",
      "x-organization-id": "YOUR_ORGANIZATION_ID",
  }

  INVOICE_TYPES = {"heat", "electricity", "water", "recharge", "process", "waste_water_treatment"}


  def filter_options(facility_id, invoice_type):
      # An unknown type returns empty lists rather than an error, so check first
      if invoice_type not in INVOICE_TYPES:
          raise ValueError(f"{invoice_type!r} is not one of {sorted(INVOICE_TYPES)}")

      return requests.get(
          "https://api.dcycle.io/v1/invoices/filter-options",
          headers=HEADERS,
          params={"facility_id": facility_id, "type": invoice_type},
          timeout=30,
      ).json()


  options = filter_options("YOUR_FACILITY_ID", "electricity")
  print([s["name"] for s in options["suppliers"]])
  print(options["cups"])
  ```

  ```javascript JavaScript theme={"theme":{"light":"github-light","dark":"github-dark"}}
  const INVOICE_TYPES = [
    "heat",
    "electricity",
    "water",
    "recharge",
    "process",
    "waste_water_treatment",
  ];

  async function filterOptions(facilityId, invoiceType) {
    if (!INVOICE_TYPES.includes(invoiceType)) {
      throw new Error(`${invoiceType} is not one of ${INVOICE_TYPES.join(", ")}`);
    }

    const params = new URLSearchParams({
      facility_id: facilityId,
      type: invoiceType,
    });
    const response = await fetch(
      `https://api.dcycle.io/v1/invoices/filter-options?${params}`,
      {
        headers: {
          "x-api-key": "YOUR_API_KEY",
          "x-organization-id": "YOUR_ORGANIZATION_ID",
        },
      },
    );
    return response.json();
  }
  ```
</CodeGroup>

### Successful Response

Returns `200 OK`.

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "cups": ["ES0031408000000000AB0F"],
  "suppliers": [
    {
      "id": "3f8a1c74-5d29-4e63-b018-7c4e9a2b5f61",
      "name": "Iberdrola"
    }
  ],
  "uploaded_by": [
    {
      "id": "6b2d9e41-7a83-4c50-9f27-1e5b8d3a0c94",
      "first_name": "Ana",
      "last_name": "Ruiz",
      "email": "ana.ruiz@example.com"
    }
  ],
  "sources": ["manual"],
  "stationary_fuels": [],
  "refrigerant_fuels": [],
  "supply_contracts": []
}
```

The empty lists here are normal: an electricity facility has no stationary or refrigerant fuels.

## Common Errors

### 404 Not Found

**Cause:** The facility does not exist, or it sits outside the organization family. Both return the same `404` on purpose — the API never confirms that a facility exists elsewhere.

### 422 Unprocessable Entity

**Cause:** `facility_id` or `type` is missing. Both are required.

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "detail": [
    {
      "loc": ["query", "type"],
      "msg": "field required",
      "type": "value_error.missing"
    }
  ]
}
```

A misspelled `type` produces **no** error — see the warning above.

## Use Cases

### Render a whole filter panel in one request

Because all seven lists arrive together, you can build the complete filter bar for a facility with a single call rather than one request per dropdown.

### Decide which dropdowns to hide

An empty list means the facility has no invoices carrying that attribute. Hiding those dropdowns instead of showing them empty is usually the better interface — and this response is what tells you which ones they are.

## Related Endpoints

<CardGroup cols={2}>
  <Card title="List Invoices" icon="list" href="/api-reference/invoices/list">
    Apply the filters you just populated
  </Card>

  <Card title="Get Invoice Totals" icon="chart-simple" href="/api-reference/invoices/totals">
    Aggregate the filtered set
  </Card>

  <Card title="Create Invoice" icon="plus" href="/api-reference/invoices/create">
    Add the invoices these options describe
  </Card>

  <Card title="Invoices API" icon="file-invoice" href="/api-reference/invoices/overview">
    Everything the Invoices API covers
  </Card>
</CardGroup>
