Skip to main content

Python SDK and CLI for the Monopigi Greek Government Data API

Project description

monopigi

Python SDK and CLI for the Monopigi Greek Government Data API.

One API. 31M+ government decisions. 200K+ EU procurement notices. 10K+ energy permits. Millions of open data records. Normalized JSON. One bearer token.

Documentation | API Reference | Interactive API Docs | Get API Key

Installation

# Base package
pip install monopigi

# With Polars DataFrame support
pip install monopigi[df]

# With interactive TUI browser
pip install monopigi[fuzzy]

# Everything
pip install monopigi[all]

Requires Python 3.12+.


Quick Start

Python SDK

from monopigi import MonopigiClient

with MonopigiClient("mp_live_your_token_here") as client:
    # Search across all 8 data sources
    results = client.search("hospital procurement", limit=10)
    for doc in results.results:
        print(f"{doc.source}: {doc.title}")

CLI

# Save your token (once)
monopigi auth login mp_live_your_token_here

# Search
monopigi search "hospital procurement"

# Get your API key at https://monopigi.com

Data Sources

Source What it contains Volume
Diavgeia Government spending decisions, contracts, financial data 31M+ decisions
KIMDIS Greek public procurement — contracts, auctions, payments 1M+ records/year
TED (EU) EU public procurement notices for Greece (EL/EN) 200K+ notices
RAE Energy Energy permits — wind, solar, hydro with GeoJSON 15K+ permits
data.gov.gr National open data — health, economy, crime, energy 84 datasets, millions of records
ELSTAT Statistical time series — GDP, unemployment, trade 28 indicators, decades of data
Mitos Government orgs + services registry — names, addresses, VAT 2,886 orgs + 4,264 services
Geodata Greek geospatial data — environmental, urban, cadastral (OGC WFS) 193 layers, 500K+ features

SDK Reference

Client

from monopigi import MonopigiClient, AsyncMonopigiClient

# Sync client
client = MonopigiClient(token="mp_live_...", base_url="https://api.monopigi.com")

# With caching (5 min TTL)
client = MonopigiClient(token="mp_live_...", cache_ttl=300)

# With custom retry (default: 3)
client = MonopigiClient(token="mp_live_...", max_retries=5)

# Context manager (auto-closes connection)
with MonopigiClient("mp_live_...") as client:
    ...

# Async client
async with AsyncMonopigiClient("mp_live_...") as client:
    results = await client.search("hospital")

Core Methods

# Search across all sources
results = client.search("hospital procurement", limit=100, offset=0)

# Query a specific source
docs = client.documents("ted", limit=50, since="2026-01-01")

# List available sources
sources = client.sources()

# Platform statistics
stats = client.stats()

# Your API usage today
usage = client.usage()

Source-Specific Clients

Typed convenience wrappers for each data source:

# TED EU procurement
tenders = client.ted.notices(limit=100, since="2026-01-01")

# Diavgeia government decisions
decisions = client.diavgeia.decisions(limit=50)

# ELSTAT statistics
datasets = client.elstat.datasets()

# RAE energy permits
permits = client.rae.permits()

# data.gov.gr national data
data = client.data_gov_gr.datasets()

# Mitos government organizations + services
orgs = client.mitos.organizations()
services = client.mitos.services()

# KIMDIS Greek public procurement
contracts = client.kimdis.contracts(limit=100, since="2026-01-01")

# Geodata — Greek geospatial layers
layers = client.geodata.layers()

Auto-Pagination

Iterate through all results without manual offset management:

# Yields every document, auto-fetches next pages
for doc in client.search_iter("procurement"):
    print(doc.title)

# Same for source-specific queries
for doc in client.documents_iter("ted", since="2026-01-01"):
    process(doc)

DataFrame Conversion

Convert any response to a Polars DataFrame (requires [df] extra):

df = client.search("hospital").to_df()
df = client.documents("ted", limit=500).to_df()

Bulk Export

Export entire sources to files with progress bars:

# JSON
count = client.export("ted", "tenders.json", format="json")

# CSV
count = client.export("diavgeia", "decisions.csv", format="csv", since="2026-01-01")

# Parquet (requires polars)
count = client.export("ted", "tenders.parquet", format="parquet")

Caching

Disk-based cache with TTL to avoid repeated API calls:

# Cache responses for 1 hour
client = MonopigiClient("mp_live_...", cache_ttl=3600)

# First call hits the API
results1 = client.search("hospital")

# Second identical call served from disk cache
results2 = client.search("hospital")  # instant, no API call

Cache is stored in ~/.monopigi/cache/ as SHA-256 keyed JSON files.

Rate-Limit Handling

The client automatically handles HTTP 429 (rate limit exceeded):

# Auto-waits when rate-limited, retries up to max_retries times
client = MonopigiClient("mp_live_...", max_retries=3)

# If rate limit is hit, the client:
# 1. Reads X-RateLimit-Reset header
# 2. Waits until reset time (capped at 5 min)
# 3. Retries the request
# 4. Raises RateLimitError only after exhausting retries

Error Handling

from monopigi import MonopigiClient, AuthError, RateLimitError, NotFoundError, MonopigiError

try:
    client = MonopigiClient("invalid_token")
    client.sources()
except AuthError:
    print("Invalid API token")
except RateLimitError as e:
    print(f"Rate limited. Resets at: {e.reset_at}")
except NotFoundError:
    print("Source not found")
except MonopigiError:
    print("Something went wrong")

Response Models

All responses are typed Pydantic models with full autocomplete:

from monopigi.models import (
    Source,          # name, label, status, description
    Document,        # source_id, source, title, doc_type, published_at, quality_score, ...
    SearchResponse,  # query, results, total, limit, offset
    DocumentsResponse,
    StatsResponse,
    UsageResponse,
    SourceStatus,    # Enum: ACTIVE, UNAVAILABLE, PLANNED
    Tier,            # Enum: FREE, PRO, ENTERPRISE
)

CLI Reference

Authentication

# Save your API token
monopigi auth login mp_live_your_token_here

# Check auth status
monopigi auth status

# Remove saved token
monopigi auth logout

Token is stored in ~/.monopigi/config.toml:

token = "mp_live_..."
base_url = "https://api.monopigi.com"

Configuration

CLI settings are stored separately in ~/.monopigi/settings.json:

# Set API base URL (for self-hosted or development)
monopigi config set base_url http://localhost:8000

# Set default output format (table, json, jsonl, csv)
monopigi config set default_format json

# Set default source for documents/diff/export commands
monopigi config set default_source ted

# Set cache TTL in seconds (default: 300)
monopigi config set cache_ttl 600

# Get a config value
monopigi config get cache_ttl

# List all config (auth + settings)
monopigi config list
Key Default Description
base_url https://api.monopigi.com API base URL
default_format table Output format: table, json, jsonl, csv
default_source Default source for documents, diff, export
cache_ttl 300 Local cache TTL in seconds

Searching

Basic search:

# Simple keyword search
monopigi search "hospital"

# Multi-word queries
monopigi search "public procurement Athens"

# Greek language queries
monopigi search "δημόσιο νοσοκομείο"

Filtering by source:

# Search only in EU procurement tenders
monopigi search "IT services" --source ted

# Search Greek government decisions
monopigi search "hospital" --source diavgeia

# Search public contracts registry
monopigi search "construction" --source kimdis

# Search energy permits
monopigi search "solar" --source rae

Output formats:

# Rich table (default in terminal)
monopigi search "procurement" --limit 20

# JSON (syntax highlighted)
monopigi search "hospital" --format json

# JSONL (one JSON object per line — pipe to jq)
monopigi search "tender" --format jsonl | jq '.title'

# CSV (for spreadsheets)
monopigi search "Athens" --format csv > results.csv

# Select specific fields
monopigi search "hospital" --fields source,title,published_at --format csv

Counting and caching:

# Just count results
monopigi search "procurement" --count

# Cache results for repeated queries (5 min TTL)
monopigi search "hospital" --cache

Piping and composing:

# Filter with grep
monopigi search "hospital" --format jsonl | grep diavgeia

# Count results per source
monopigi search "procurement" --format jsonl | jq -r '.source' | sort | uniq -c | sort -rn

# Extract just titles
monopigi search "tender" --format jsonl | jq -r '.title'

# Save to file
monopigi search "Athens hospital" --format jsonl > hospitals.jsonl

# Watch for new results in real-time
monopigi watch "hospital procurement" --interval 60

Python SDK search examples:

from monopigi import MonopigiClient

with MonopigiClient("mp_live_...") as client:
    # Basic search
    results = client.search("hospital procurement")
    print(f"Found {results.total} results")
    for doc in results.results:
        print(f"  [{doc.source}] {doc.title}")

    # Search specific source
    results = client.search("solar energy", source="rae")

    # Search with limits
    results = client.search("tender", limit=50)

    # Check tier access
    if client.has_feature("full_text"):
        results = client.search("hospital", limit=100)
    else:
        print(f"Search requires Pro tier. Current: {client.tier}")

Async Python:

from monopigi import AsyncMonopigiClient

async with AsyncMonopigiClient("mp_live_...") as client:
    results = await client.search("hospital", source="ted")
    async for doc in client.search_iter("procurement"):
        print(doc.title)

Querying Sources

# Query a specific source
monopigi documents ted --limit 20

# Filter by date
monopigi documents diavgeia --since 2026-01-01

# Output as JSONL (one object per line)
monopigi documents ted --format jsonl

Watching for Changes

# Poll every 60 seconds for new results
monopigi watch "hospital procurement"

# Custom interval
monopigi watch "tender" --interval 30

# Stream to file
monopigi watch "procurement" --format jsonl | tee new_results.jsonl

Diffing

# What's new since last check?
monopigi diff ted

# Since a specific date
monopigi diff diavgeia --since 2026-03-15

Exporting

# Export to JSON
monopigi export ted tenders.json

# Export to CSV
monopigi export diavgeia decisions.csv --format csv --since 2026-01-01

# Export to Parquet
monopigi export ted tenders.parquet --format parquet

# Limit export size
monopigi export ted sample.json --limit 100

Interactive Browser

Requires monopigi[fuzzy]:

# Browse documents from a source
monopigi browse ted

# Browse with a pre-filter
monopigi browse --query "hospital" --limit 200

Piping (stdin enrichment)

# Search for each line from stdin
echo "hospital" | monopigi pipe

# Enrich a list of queries
cat search_terms.txt | monopigi pipe --limit 5

# Chain with other monopigi commands
monopigi documents ted --format jsonl | jq -r '.title' | monopigi pipe

Configuration

# Set a config value
monopigi config set cache_ttl 600
monopigi config set default_format json

# Get a config value
monopigi config get cache_ttl

# List all config
monopigi config list

Valid keys: base_url, default_format, default_source, cache_ttl.

Shell Completions

# Show installation instructions
monopigi completions

# Or use Typer's built-in
monopigi --install-completion

Platform Info

# Platform statistics
monopigi stats

# Your API usage
monopigi usage

# Available data sources
monopigi sources

Unix Pipe Recipes

The CLI is pipe-friendly — it auto-switches to JSONL output when piped.

# Filter with jq
monopigi search "hospital" | jq 'select(.quality_score > 0.9)'

# Count results
monopigi search "Athens" --count

# Extract titles
monopigi documents ted --format jsonl | jq -r '.title'

# Find procurement over EUR 1M
monopigi documents ted --format jsonl | jq 'select(.title | test("1.000.000|1,000,000"))'

# Deduplicate across sources
monopigi search "procurement" --format jsonl | jq -s 'unique_by(.source_id)'

# Top sources by document count
monopigi stats | jq '.sources | to_entries | sort_by(-.value.documents) | .[].key'

Enterprise Features

Enterprise tier unlocks AI-powered analysis and cross-source intelligence:

Ask (RAG) — AI-generated answers from government data

monopigi ask "What are the largest public contracts in Thessaloniki?"
monopigi ask "How much did the government spend on IT consulting?" --limit 10
answer = client.ask("What energy permits were issued in Crete?")
print(answer["answer"])
print(answer["sources"])

Entity Resolution — find all records for a company or person

monopigi entity 099369820 --type afm
monopigi entity "ΔΗΜΟΣ ΑΘΗΝΑΙΩΝ" --type name
entity = client.entity("099369820", identifier_type="afm")
for match in entity["matches"]:
    print(f"  {match['source']}: {match['title']}")

Similar Documents

monopigi similar "contract:26SYMV018689966"

Content Download — original PDFs, XML, JSON

monopigi content "diavgeia:ABC123" --output decision.pdf
pdf = client.content("diavgeia:ABC123")
Path("decision.pdf").write_bytes(pdf)

Due Diligence Reports — automated entity reports with PDF export

# Request a report
report = client.create_report("123456789", identifier_type="afm")
print(report["id"], report["status"])  # pending

# Check status
report = client.get_report(report["id"])
if report["status"] == "completed":
    print(report["report_json"]["sections"]["executive_summary"])

# Download PDF
pdf_bytes = client.get_report_pdf(report["id"])
with open("report.pdf", "wb") as f:
    f.write(pdf_bytes)

# List past reports
reports = client.list_reports()
monopigi report create 123456789 --type afm
monopigi report list
monopigi report get <id> --pdf --output report.pdf

Procurement Alerts — automated notifications for new tenders

# Create alert profile
profile = client.create_alert_profile(
    name="IT Contracts",
    filters={"keywords": ["πληροφορική", "software"], "min_value": 50000},
    channels=["email"],
)

# List profiles and deliveries
profiles = client.list_alert_profiles()
deliveries = client.list_alert_deliveries()
monopigi alerts create "IT Contracts" --keywords "software,πληροφορική" --min-value 50000
monopigi alerts list
monopigi alerts deliveries

Compliance Monitoring — continuous entity surveillance

# Monitor an entity
entity = client.add_monitored_entity("123456789", identifier_type="afm", label="Acme Corp")

# Check events
events = client.list_entity_events()

# Get health report
report = client.entity_health_report(entity["id"])
monopigi monitor add 123456789 --type afm --label "Acme Corp"
monopigi monitor list
monopigi monitor events
monopigi monitor report <entity-id>

Models — list available LLM models for the Ask endpoint

models = client.models()
print(models["default"])  # mistralai/mistral-large-2512
monopigi models

Pricing

Tier Price Daily Queries Reports Alert Profiles Monitored Entities MCP Server Other Features
Free EUR 0 5 Sources, stats, metadata
Pro EUR 299/mo 100 20/mo 3 + Search, full text, export
Enterprise EUR 999+/mo 1,000 Unlimited Unlimited EUR 2/entity/mo Yes + RAG, entity resolution, MCP, content download

Get your API key at monopigi.com.


Links


License

Apache License 2.0 — see LICENSE for details.

The SDK is open source. The Monopigi API and data platform are proprietary.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

monopigi-0.1.20.tar.gz (25.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

monopigi-0.1.20-py3-none-any.whl (29.5 kB view details)

Uploaded Python 3

File details

Details for the file monopigi-0.1.20.tar.gz.

File metadata

  • Download URL: monopigi-0.1.20.tar.gz
  • Upload date:
  • Size: 25.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.3 {"installer":{"name":"uv","version":"0.11.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for monopigi-0.1.20.tar.gz
Algorithm Hash digest
SHA256 99bd891add0fafdfb7a4f7eb9734e8ed100e529c14eae37e90e9d79b2175b429
MD5 c809a4fd30cf0ce75335ad8eac426a13
BLAKE2b-256 c6e8a1d16d64d2793c369259e4bd1826308ef2fbfbe95c0c2a402213c16df4c0

See more details on using hashes here.

File details

Details for the file monopigi-0.1.20-py3-none-any.whl.

File metadata

  • Download URL: monopigi-0.1.20-py3-none-any.whl
  • Upload date:
  • Size: 29.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.3 {"installer":{"name":"uv","version":"0.11.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for monopigi-0.1.20-py3-none-any.whl
Algorithm Hash digest
SHA256 be0872ca283f9d3f016428bc7829563ecbcfb4c948226852aecb071ffa0766cf
MD5 e549514b1d3b2ac4168c6c4689fcf63d
BLAKE2b-256 47355e111bac415b123a3269bd321cf4b286f240497f9d13fe51559a6a2bf50c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page