Skip to main content

cargos-api

PyPI Python Versions License

A small Python library to build and submit rental booking records to the Italian Police Ca.R.G.O.S. API.

Table of Contents


This repository was created to interact with the Ca.R.G.O.S. APIs for a client who needed to automate the submission of rental booking details to the Italian Police.

The official documentation (see docs.pdf) is difficult to follow and sparse on examples. The goal of this project is to provide a clean, documented Python module that makes the integration straightforward and consistent.

This module handles all the location -> id conversions, data formatting and submission to the Ca.R.G.O.S. API.


Install

pip install cargos-api

Quick start

from cargos_api import CargosAPI, CargosRecordMapper, models as m

# Credentials
api = CargosAPI(username="...", password="...", api_key="...48-chars...")

# Build a booking using codes from your catalogs (examples below use placeholder codes)
booking = m.BookingData(
    contract_id="CONTR-001",
    contract_datetime="2025-01-01T10:00:00",   # ISO-like; mapper outputs dd/mm/YYYY HH:MM
    payment_type_code="1",                     # per Ca.R.G.O.S. table
    checkout_datetime="2025-01-01T11:00:00",
    checkout_place=m.Address(location_code=403015146, street="Via X 1"),  # Roma (example)
    checkin_datetime="2025-01-02T11:00:00",
    checkin_place=m.Address(location_code=402020327, street="Via Y 2"),    # Verona (example)
    operator=m.Operator(
        id="SYSTEM",
        agency_id="1",
        agency_name="ACME",
        agency_place_code=403015146,
        agency_address="Via Z 3",
        agency_phone="0000",
    ),
    car=m.Car(
        type_code="A",  # vehicle type code (per table)
        brand="Fiat",
        model="Panda",
        plate="AB123CD",
        color="Bianco",
    ),
    customer=m.Customer(
        surname="Rossi",
        name="Mario",
        birth_date="1990-01-01",
        birth_place_code=401028044,           # Genova (example)
        citizenship_code=100000001,           # Italia (example)
        id_doc_type_code="CI",
        id_doc_number="XYZ12345",
        id_doc_issuing_place_code=401028044,
        driver_licence_number="LIC123456",
        driver_licence_issuing_place_code=401028044,
        contact="0000000000",
    ),
)

# Map to Ca.R.G.O.S. fixed-width record (1505 chars)
record = CargosRecordMapper().build_record(booking)

# Validate or send
api.check_contracts([record])
# api.send_contracts([record])

Formatting the data

This library exposes typed dataclasses in cargos_api.models that you fill with your normalized data and pass to the mapper.

  • BookingData: contract_id, contract_datetime, payment_type_code, checkout_datetime, checkout_place (Address), checkin_datetime, checkin_place (Address), operator (Operator), car (Car), customer (Customer), second_driver (optional)
  • Customer: surname, name, birth_date, birth_place_code, citizenship_code, residence (Address, optional), id_doc_type_code, id_doc_number, id_doc_issuing_place_code, driver_licence_number, driver_licence_issuing_place_code, contact
  • SecondDriver: same as Customer (without residence); if present, all fields are mandatory
  • Car: type_code, brand, model, plate, color (optional), has_gps (optional), has_immobilizer (optional)
  • Address: location_code, street
  • Operator: id, agency_id, agency_name, agency_place_code, agency_address, agency_phone

Ca.R.G.O.S. Tracciato Record Parameters

Name Required Description
CONTRATTO_ID ✅ Unique contract identifier
CONTRATTO_DATA ✅ Contract date (format gg/mm/aaaa hh:mm)
CONTRATTO_TIPOP ✅ Payment type (see TABELLA TIPO PAGAMENTI)
CONTRATTO_CHECKOUT_DATA ✅ Checkout date (format gg/mm/aaaa hh:mm)
CONTRATTO_CHECKOUT_LUOGO_COD ✅ Police location code (TABELLA LUOGHI POLIZIA)
CONTRATTO_CHECKOUT_INDIRIZZO ✅ Checkout address (length > 3)
CONTRATTO_CHECKIN_DATA ✅ Check-in date (format gg/mm/aaaa hh:mm)
CONTRATTO_CHECKIN_LUOGO_COD ✅ Police location code (TABELLA LUOGHI POLIZIA)
CONTRATTO_CHECKIN_INDIRIZZO ✅ Check-in address (length > 3)
OPERATORE_ID ✅ Operator identifier
AGENZIA_ID ✅ Agency identifier (unique)
AGENZIA_NOME ✅ Agency name
AGENZIA_LUOGO_COD ✅ Police location code (TABELLA LUOGHI POLIZIA)
AGENZIA_INDIRIZZO ✅ Agency address (length > 3)
AGENZIA_RECAPITO_TEL ✅ Agency phone number (length > 3)
VEICOLO_TIPO ✅ Vehicle type (TABELLA TIPO VEICOLO)
VEICOLO_MARCA ✅ Vehicle brand
VEICOLO_MODELLO ✅ Vehicle model
VEICOLO_TARGA ✅ Vehicle plate number (length > 3)
VEICOLO_COLORE ❌ Vehicle color
VEICOLO_GPS ❌ GPS presence flag
VEICOLO_BLOCCOM ❌ Immobilizer presence flag
CONDUCENTE_CONTRAENTE_COGNOME ✅ Driver’s surname
CONDUCENTE_CONTRAENTE_NOME ✅ Driver’s name
CONDUCENTE_CONTRAENTE_NASCITA_DATA ✅ Driver’s date of birth (gg/mm/aaaa)
CONDUCENTE_CONTRAENTE_NASCITA_LUOGO_COD ✅ Birthplace (COMUNE ITALIANO or STATO ESTERO)
CONDUCENTE_CONTRAENTE_CITTADINANZA_COD ✅ Citizenship code (TABELLA LUOGHI POLIZIA)
CONDUCENTE_CONTRAENTE_RESIDENZA_LUOGO_COD ❌* Residence (COMUNE ITALIANO or STATO ESTERO)
CONDUCENTE_CONTRAENTE_RESIDENZA_INDIRIZZO ❌* Residence address (e.g., “VIA DEL CASTRO PRETORIO 10, ROMA”)
CONDUCENTE_CONTRAENTE_DOCIDE_TIPO_COD ✅ Document type (TABELLA DOCUMENTI POLIZIA)
CONDUCENTE_CONTRAENTE_DOCIDE_NUMERO ✅ Document number (length > 4)
CONDUCENTE_CONTRAENTE_DOCIDE_LUOGORIL_COD ✅ Document issuing place (COMUNE ITALIANO or STATO ESTERO)
CONDUCENTE_CONTRAENTE_PATENTE_NUMERO ✅ Driver’s license number (length > 4)
CONDUCENTE_CONTRAENTE_PATENTE_LUOGORIL_COD ✅ License issuing place (COMUNE ITALIANO or STATO ESTERO)
CONDUCENTE_CONTRAENTE_RECAPITO ❌ Driver’s contact number
CONDUCENTE2_COGNOME ❌** Second driver surname
CONDUCENTE2_NOME ❌** Second driver name
CONDUCENTE2_NASCITA_DATA ❌** Second driver date of birth (gg/mm/aaaa)
CONDUCENTE2_NASCITA_LUOGO_COD ❌** Second driver birthplace (COMUNE ITALIANO or STATO ESTERO)
CONDUCENTE2_CITTADINANZA_COD ❌** Second driver citizenship (TABELLA LUOGHI POLIZIA)
CONDUCENTE2_DOCIDE_TIPO_COD ❌** Second driver document type
CONDUCENTE2_DOCIDE_NUMERO ❌** Second driver document number
CONDUCENTE2_DOCIDE_LUOGORIL_COD ❌** Second driver document issuing place
CONDUCENTE2_PATENTE_NUMERO ❌** Second driver license number (length > 4)
CONDUCENTE2_PATENTE_LUOGORIL_COD ❌** Second driver license issuing place
CONDUCENTE2_RECAPITO ❌** Second driver contact number

Notes

  • * → Both residence fields (LUOGO_COD and INDIRIZZO) must be filled together, otherwise the data is rejected.
  • ** → If a second driver is present, all fields under CONDUCENTE2_ become mandatory.
  • Each block of records must not contain more than 100 contracts (rows).

Required fields

The mapper validates inputs and raises InvalidInput if anything is missing:

  • booking: id, creation_date, from_date, to_date
  • customer: birth_date, firstname, lastname, birth_place, citizenship, and one of (document_id, driver_licence_number) and one of (cellphone, email)
  • car: brand, model, plate, color
  • delivery_place: address_city, address
  • return_place: address_city, address
  • operator: id, agency_id, agency_name, city, address, phone

Optional fields

  • Customer.address is emitted as free-text in the record when provided
  • Address.address_country is currently not mapped to a dedicated field

Lookup tables (locations, documents, payments, vehicles)

  • Packaged CSV catalogs under cargos_api/data/ are used at runtime:
    • luoghi.csv (location/country codes)
    • tipo_documento.csv (document types)
    • tipo_pagamento.csv (payment types)
    • tipo_veicolo.csv (vehicle types)
  • Lookups are case-insensitive; expired locations (rows with DataFineVal) are ignored
  • Use CatalogLoader if you need to resolve human-readable labels to Ca.R.G.O.S. codes in your app:
    from cargos_api.locations_loader import CatalogLoader
    code = CatalogLoader().document_type_code('CI')
    
  • If a required code is not found, the mapper raises a ValueError

Inspecting the record as a mapping

Sometimes you want to verify exactly what each field contains after padding/truncation. You can ask the mapper to return both the fixed-width string and a JSON-like mapping of field names to their exact slices by passing with_map=True:

from cargos_api import CargosRecordMapper, models as m

booking = m.BookingData(
    contract_id="123", contract_datetime="2025-01-05T09:00:00", payment_type_code="1",
    checkout_datetime="2025-01-06T10:00:00", checkout_place=m.Address(location_code=403015146, street="Via A 10"),
    checkin_datetime="2025-01-07T10:00:00", checkin_place=m.Address(location_code=403015146, street="Via B 20"),
    operator=m.Operator(id="SYS", agency_id="AG1", agency_name="ACME", agency_place_code=403015146, agency_address="Via C 30", agency_phone="06..."),
    car=m.Car(type_code="A", brand="VW", model="Golf", plate="ZZ999ZZ"),
    customer=m.Customer(
        surname="Bianchi", name="Anna", birth_date="1985-05-20",
        birth_place_code=403015146, citizenship_code=100000001,
        id_doc_type_code="CI", id_doc_number="X1", id_doc_issuing_place_code=403015146,
        driver_licence_number="L1", driver_licence_issuing_place_code=403015146,
    ),
)
record, mapping = CargosRecordMapper().build_record(booking, with_map=True)
print(len(record))              # 1505
print(mapping["CONTRATTO_ID"])  # 50-char padded slice for the contract ID

API usage notes

  • CargosAPI.get_token() fetches the token using HTTP Basic auth
  • The api_key must be exactly 48 characters: first 32 chars are the AES key and the last 16 chars are the IV used to encrypt the bearer token
  • Use check_contracts(records) to validate records before submission; use send_contracts(records) to submit them

Example: minimal end-to-end flow

from cargos_api import CargosAPI, CargosRecordMapper, models as m

api = CargosAPI(username="ORG", password="PASS", api_key="...48-chars...")
booking = m.BookingData(
    contract_id="123",
    contract_datetime="2025-01-05T09:00:00",
    payment_type_code="1",
    checkout_datetime="2025-01-06T10:00:00",
    checkout_place=m.Address(location_code=403015146, street="Via A 10"),
    checkin_datetime="2025-01-07T10:00:00",
    checkin_place=m.Address(location_code=403015146, street="Via B 20"),
    operator=m.Operator(id="SYS", agency_id="AG1", agency_name="ACME", agency_place_code=403015146, agency_address="Via C 30", agency_phone="06..."),
    car=m.Car(type_code="A", brand="VW", model="Golf", plate="ZZ999ZZ", color="Nero"),
    customer=m.Customer(
        surname="Bianchi", name="Anna", birth_date="1985-05-20",
        birth_place_code=403015146, citizenship_code=100000001,
        id_doc_type_code="CI", id_doc_number="DOC1", id_doc_issuing_place_code=403015146,
        driver_licence_number="LIC1", driver_licence_issuing_place_code=403015146,
        contact="333...",
    ),
)
record = CargosRecordMapper().build_record(booking)
api.check_contracts([record])

Troubleshooting

  • ValueError: location not found → check the spelling of city/country names
  • InvalidInput: missing fields → read the error message for which fields are missing
  • InvalidResponse: HTTP errors → network issues or server response with errore field

Building something with it?

If you nee dhelp implementing this in your project, please reach out.

Author

If you found this project helpful or interesting, consider starring the repo and following me for more security research and tools, or buy me a coffee to keep me up

GitHub Twitter Medium Discord Email Buy Me a Coffee


Metadata

Release files for cargos-api 0.2.4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for cargos-api 0.2.4
File Size Uploaded Provenance Actions
cargos_api-0.2.4.tar.gz 127.4 kB With provenance Details for cargos_api-0.2.4.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for cargos-api 0.2.4
File Interpreter ABI Platform Actions
cargos_api-0.2.4-py3-none-any.whl Python 3 none any Details for cargos_api-0.2.4-py3-none-any.whl

Total release size: 252.6 kB

Release files / cargos_api-0.2.4.tar.gz

Download URL cargos_api-0.2.4.tar.gz
Size 127.4 kB
Tags Source
SHA-256 checksum
How to use checksums
8c8d24ca6869c3c8f7d5c2677e1e765e3d12aa306d89e6f86808f5b1b2a1a1d3
BLAKE2b-256 checksum
How to use checksums
e60afc2c4e732f3f746a122f5c4c7057c68443ed0521a3deec464f2dc4d7c565
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 7, 2025.

Transparency log

Release files / cargos_api-0.2.4-py3-none-any.whl

Download URL cargos_api-0.2.4-py3-none-any.whl
Size 125.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
42dc4a95c5beba001f7ffbb32e33e8bb6c5a2e504774bfdaad3461df8d67ec02
BLAKE2b-256 checksum
How to use checksums
118f304e8b53d7c1cd745f985ebb44f0a1dd453fcf6b7b194003ba950d4c7c57
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 7, 2025.

Transparency log

Security for cargos-api 0.2.4

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for cargos_api-0.2.4.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 7, 2025.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page