cup-cig
CUP-CIG
Use this skill to retrieve detailed information on Italian public projects and tenders from CUP and CIG codes using open data sources.
IMPORTANT: Always write
curlcommands on a single line. Multi-line\continuation breaks argument parsing in agent environments and will cause errors.
Decision Tree — Which Source for Which Question?
User has a CUP
├─ Project metadata (name, sector, entity, amounts)?
│ └─ OpenCUP API (or web page if no API key)
├─ Financial monitoring / execution status?
│ └─ OpenBDAP OData
└─ Associated tenders (CIG)?
└─ ANAC BDNCP bulk (authoritative CUP↔CIG join)
User has a CIG
├─ Starts with Z (e.g. Z063947806)?
│ └─ Below-threshold direct award → ANAC BDNCP bulk only
└─ Alphanumeric (e.g. 8874674CA7)?
└─ SCP-MIT API (published tenders)
Environment Variables
export OPENCUP_API_CLIENT_ID='...'
export OPENCUP_API_CLIENT_SECRET='...'
To verify without printing the values:
[[ -n "${OPENCUP_API_CLIENT_ID:-}" ]] && echo "ID is set" || echo "ERROR: OPENCUP_API_CLIENT_ID not set"
[[ -n "${OPENCUP_API_CLIENT_SECRET:-}" ]] && echo "SECRET is set" || echo "ERROR: OPENCUP_API_CLIENT_SECRET not set"
Source 1 — OpenCUP: Project Metadata
Base URL: https://api.sogei.it/rgs/opencup/o/extServiceApi/v1/opendataes/cup/{CUP}
Auth: IBM API headers (x-ibm-client-id, x-ibm-client-secret)
Look up a single CUP
curl -sS -X GET "https://api.sogei.it/rgs/opencup/o/extServiceApi/v1/opendataes/cup/J87G22000360002" -H "x-ibm-client-id: ${OPENCUP_API_CLIENT_ID}" -H "x-ibm-client-secret: ${OPENCUP_API_CLIENT_SECRET}" -H "Accept: application/json" | jq '.results[0]|{cup:.CUP, anno:.ANNO_DECISIONE, stato:.COD_STATO_PROGETTO, soggetto:.DESC_SOGGETTO, settore:.DESC_SETTORE_INTERVENTO, area:.DESC_AREA_INTERVENTO, importo:.IMPORTO_COSTO_PROGETTO, regione:.LOC_REGIONI}'
Look up a list of CUPs
Given a file cups.txt (one CUP per line):
while IFS= read -r cup; do echo "=== $cup ==="; curl -sS -X GET "https://api.sogei.it/rgs/opencup/o/extServiceApi/v1/opendataes/cup/$cup" -H "x-ibm-client-id: ${OPENCUP_API_CLIENT_ID}" -H "x-ibm-client-secret: ${OPENCUP_API_CLIENT_SECRET}" -H "Accept: application/json" | jq '.results[0]|{cup:.CUP, stato:.COD_STATO_PROGETTO, soggetto:.DESC_SOGGETTO, settore:.DESC_SETTORE_INTERVENTO, importo:.IMPORTO_COSTO_PROGETTO}'; done < cups.txt
Without API credentials (web page fallback)
The project page at https://opencup.gov.it/portale/progetto/-/cup/{CUP} is publicly
accessible but returns HTML. Use a browser or a headless fetch tool for scraping.
Source 2 — OpenBDAP: Financial Monitoring
Base URL: https://bdap-opendata.rgs.mef.gov.it/ODataProxy/MdData('bda1676b-62ab-44b7-8f9a-ca93b8534488@rgs')/DataRows
Auth: None
Field name for CUP: Cccodice_cup_1267962549
Query by CUP
curl -sS "https://bdap-opendata.rgs.mef.gov.it/ODataProxy/MdData('bda1676b-62ab-44b7-8f9a-ca93b8534488@rgs')/DataRows?\$filter=Cccodice_cup_1267962549%20eq%20'H87H21003670005'&\$inlinecount=allpages&\$top=10&\$format=json" | jq '[.d.results[]|{cup:.Cccodice_cup_1267962549, descrizione:.Ccdescrizione_cu902475141, stato:.Ccdescrizione_s1176782119, ente:.Ccdescrizione_ti177583083, settore:.Ccsettore_inter1475973826, costo:.Cccosto_lavori_e582037416}]'
Query by entity fiscal code (without knowing CUPs)
curl -sS "https://bdap-opendata.rgs.mef.gov.it/ODataProxy/MdData('bda1676b-62ab-44b7-8f9a-ca93b8534488@rgs')/DataRows?\$filter=Cccodice_fiscal1934873127%20eq%20'02246660985'&\$inlinecount=allpages&\$top=10&\$format=json" | jq '[.d.results[]|{cup:.Cccodice_cup_1267962549, ente:.Ccdescrizione_ti177583083, stato:.Ccdescrizione_s1176782119}]'
Common OData filters
| What | Filter |
|---|---|
| By CUP | $filter=Cccodice_cup_1267962549 eq '{CUP}' |
| By fiscal code | $filter=Cccodice_fiscal1934873127 eq '{CF}' |
| Active projects | $filter=Cccodice_stato_1426672593 eq 'A' |
| Closed projects | $filter=Cccodice_stato_1426672593 eq 'C' |
| By sector | $filter=Ccsettore_inter1475973826 eq 'STRADALI' |
Combine with and/or. Always add $inlinecount=allpages for total counts.
Source 3 — SCP-MIT: Published Tenders (CIG above threshold)
Base URL: https://www.serviziocontrattipubblici.it/WSConsultBandi/rest/
Method: POST + Content-Type: application/x-www-form-urlencoded
Note: Use -k flag to skip SSL verification (self-signed certificate).
Important: page_limit and offset go as URL query params; all other filters go in the form body.
stato values: 1=In corso, 2=Scaduti, 3=Tutti. Use 3 when searching by CIG to avoid missing results.
Search by CIG — tender list (Bandi)
curl -sSkX POST "https://www.serviziocontrattipubblici.it/WSConsultBandi/rest/Bandi/Lista?page_limit=10&offset=0" -H "Content-Type: application/x-www-form-urlencoded" -d "stato=3&cig=8874674CA7" | jq '.'
Search by CIG — award results (Esiti)
curl -sSkX POST "https://www.serviziocontrattipubblici.it/WSConsultBandi/rest/Esiti/Lista?page_limit=10&offset=0" -H "Content-Type: application/x-www-form-urlencoded" -d "stato=3&cig=8874674CA7" | jq '.'
Note: Z-prefix CIG (below-threshold direct awards) appear in Esiti, not in Bandi. Try both endpoints when a CIG returns no results in one of them.
Source 4 — ANAC BDNCP: CUP↔CIG Join & Below-Threshold CIGs
Dataset pages:
- CIG:
https://dati.anticorruzione.it/opendata/dataset/cig - CUP:
https://dati.anticorruzione.it/opendata/dataset/cup
Access: Bulk CSV/JSON download (no live API — WAF blocks programmatic queries). Live API: Not available.
Workflow
- Download the dataset CSV from the ANAC portal.
- Load into DuckDB for fast querying:
duckdb -c "DESCRIBE SELECT * FROM read_csv_auto('cup.csv', HEADER=TRUE) LIMIT 1;"
duckdb -c "SELECT * FROM read_csv_auto('cup.csv', HEADER=TRUE) WHERE cig = 'Z063947806' LIMIT 10;"
Key use cases
- Find CIG(s) associated with a CUP: filter
cupcolumn. - Find details of a Z-prefix CIG (direct award): filter
cigcolumn.
Definition of Done
A task is complete when:
- The correct source is selected based on the decision tree above.
- API call returns data (or a clear "no results" message).
- Output is readable (not a raw JSON blob) — use
jqto format. - For bulk sources: DuckDB query returns and formats results.
Common Errors
| Error | Cause | Fix |
|---|---|---|
401 Unauthorized on OpenCUP |
Wrong credentials or not set | Check OPENCUP_API_CLIENT_ID/SECRET |
| Empty results on OpenBDAP | CUP not in MOP dataset | Project may not have financial monitoring data |
| No results on SCP-MIT | Z-prefix CIG | Use ANAC BDNCP bulk instead |
| SSL error on SCP-MIT | Self-signed certificate | Add -k flag to curl |