Contratto tecnico provider Cercaviaggio
Endpoint / documentazione integrazione
Documentazione minima per integrare un provider via API (modello reference implementation). Versione contratto: v1.
Panoramica contratto
Ultimo aggiornamento: 05/06/2026.
Set minimo per vendere su Cercaviaggio: catalogo (sync_*), ricerca (search), conferma live (quote),
riserva (reserve) e finalizzazione (book).
Routing endpoint:
il provider espone un’unica base URL e seleziona l’endpoint con
rquest.
Esempio: https://provider.example.com/rest/cercaviaggio/api2.php?rquest=quote.
Consiglio:
implementa prima
health, poi sync_*, poi search/quote, infine reserve/book.
Formato risposta standard
Tutti gli endpoint devono rispondere in JSON con envelope uniforme. In caso di errore success vale false e il dettaglio va in error.
{
"success": true,
"contract_version": "v1",
"provider": "provider_code",
"request_id": "cv_65f6f3e0f1d2e4.12345678",
"data": {
"status": "ok"
},
"error": null
}
Endpoint minimi
| Endpoint | Metodo | Parametri | Uso |
|---|---|---|---|
health |
GET | nessuno | Ping + versione contratto. |
sync_stops |
GET | page, page_size, updated_since(opz.) | Catalogo fermate. |
sync_lines |
GET | page, page_size, updated_since(opz.) | Catalogo linee. |
sync_trips |
GET | page, page_size, updated_since(opz.) | Catalogo corse + fermate ordinate. |
sync_fares |
GET | page, page_size, updated_since(opz.) | Catalogo tariffe base fermata-fermata. |
search |
GET | part, arr, ad, bam, dt1 | Soluzioni disponibili. |
quote |
GET o POST | part, arr, id_corsa, ad, bam, dt1, fare_id(opz.) | Conferma live + quote_token. |
reserve |
POST | header X-Idempotency-Key, body quote_token | Riserva posti (prima del pagamento). |
cancel |
POST | body shop_id | Annulla la riserva (rollback multi-leg). |
book |
POST | header X-Idempotency-Key, body quote_token (+ shop_id opz.) | Finalizza ed emette i biglietti. |
change_check |
GET o POST | ticket_code / codice / codice_camb | Verifica se un biglietto può essere cambiato e ritorna i riferimenti. |
Esempi minimi
Esempio sync_stops
{
"items": [
{
"stop_id": 118,
"name": "SALERNO - P.za Montpellier",
"lat": 40.6773,
"lon": 14.7676,
"is_active": true,
"updated_at": null
}
],
"page": 1,
"page_size": 500,
"has_more": false,
"next_page": null,
"synced_at": "2026-05-19T10:00:00Z"
}
Esempio sync_trips
{
"items": [
{
"trip_id": 4123,
"line_id": 3,
"name": "SALERNO → ROMA",
"tempo_acquisto": 30,
"is_active": true,
"is_visible": true,
"stops": [
{
"stop_id": 118,
"sequence": 1,
"time": "04:35",
"day_offset": 0,
"is_active": true
},
{
"stop_id": 149,
"sequence": 5,
"time": "07:40",
"day_offset": 0,
"is_active": true
}
],
"updated_at": null
}
],
"page": 1,
"page_size": 500,
"has_more": false,
"next_page": null,
"synced_at": "2026-05-19T10:00:00Z"
}
Esempio search (risposta)
{
"solutions": [
{
"solution_id": "abc123",
"departure_datetime": "2026-06-10T04:35:00+02:00",
"arrival_datetime": "2026-06-10T07:40:00+02:00",
"duration_minutes": 185,
"segments": [
{
"provider": "provider_code",
"corsa_id": 4123,
"from_id": 118,
"to_id": 149,
"departure_time": "04:35",
"arrival_time": "07:40"
}
],
"fares": [
{
"fare_id": "STD",
"label": "Standard",
"amount": 24.9,
"currency": "EUR",
"seats_available": 12
}
]
}
]
}
Esempio quote
{
"part": 118,
"arr": 149,
"id_corsa": 4123,
"ad": 1,
"bam": 0,
"dt1": "21/03/2026",
"fare_id": "STD"
}
{
"quote_id": "6fd2f9a2a1b7cc11ef3d6a88",
"quote_token": "eyJ2IjoxLCJwcm92aWRlciI6InByb3ZpZGVyX2NvZGUifQ.signed",
"status": "confirmed",
"issued_at": "2026-03-17T10:45:00+00:00",
"expires_at": "2026-03-17T10:55:00+00:00",
"ttl_seconds": 600,
"trip": {
"provider": "provider_code",
"corsa_id": 4123,
"direction": "outbound",
"from_id": 118,
"from_name": "SALERNO - P.za Montpellier - P.co Pinocchio",
"to_id": 149,
"to_name": "ROMA - Stazione Tiburtina",
"departure_datetime": "2026-03-21T04:35:00+01:00",
"arrival_datetime": "2026-03-21T07:40:00+01:00",
"duration_minutes": 185
},
"passengers": {
"ad": 1,
"bam": 0,
"total": 1
},
"pricing": {
"fare_id": "STD",
"label": "Standard",
"amount": 24.9,
"seats_available": 12,
"currency": "EUR"
}
}
Esempio reserve (richiesta)
{
"quote_token": "eyJ2IjoxLCJwcm92aWRlciI6InByb3ZpZGVyX2NvZGUifQ.signed",
"contact": {
"full_name": "Mario Rossi",
"email": "mario.rossi@email.it",
"phone": "+39 333 123 4567"
},
"passengers": [
{
"full_name": "Mario Rossi",
"birth_date": "1988-04-12"
}
],
"codice": "CV-20260519-ABCD",
"codice_camb": ""
}
Esempio reserve (risposta)
{
"reservation_id": "res_123",
"reservation_token": "res_token_signed",
"status": "reserved",
"expires_at": "2026-05-19T10:05:00Z",
"shop_id": "SHOP-XYZ",
"pending_total": 24.9,
"pending_tickets": 1,
"tickets": [
{
"code": "ABCDEF123456",
"change_code": "0",
"passenger_name": "Mario Rossi",
"bus": 1,
"seat": 12,
"price": 24.9,
"departure_at": "2026-06-10 04:35:00",
"arrival_at": "2026-06-10 07:40:00",
"pdf_url": "https://provider.example.com/pdf.php?c=ABCDEF123456",
"is_paid": false
}
]
}
Esempio book (richiesta)
{
"quote_token": "eyJ2IjoxLCJwcm92aWRlciI6InByb3ZpZGVyX2NvZGUifQ.signed",
"shop_id": "SHOP-XYZ",
"email": "mario.rossi@email.it",
"nome": "Mario Rossi",
"codice": "CV-20260519-ABCD",
"codice_camb": ""
}
Esempio book (risposta)
{
"booking_reference": "CVPRE-XXXXXXXXXXXXXX",
"status": "booked",
"ticket_issued": true,
"shop_id": "SHOP-XYZ",
"tickets": [
{
"code": "ABCDEF123456",
"change_code": "0",
"passenger_name": "Mario Rossi",
"bus": 1,
"seat": 12,
"price": 24.9,
"departure_at": "2026-06-10 04:35:00",
"arrival_at": "2026-06-10 07:40:00",
"pdf_url": "https://provider.example.com/pdf.php?c=ABCDEF123456",
"is_paid": true
}
]
}
Esempio change_check
{
"ticket_code": "ABCDEF123456"
}
{
"can_change": true,
"ticket_code": "ABCDEF123456",
"from_stop_id": 118,
"to_stop_id": 149,
"suggested_date_it": "10/06/2026",
"used_changes": 0,
"max_changes": 1,
"changes_remaining": 1
}
Note operative (minime)
quoteereserveevitano acquisti con bus pieno: se non disponibile, risponderesuccess=false.reserveebookdevono essere idempotenti (headerX-Idempotency-Key).- In caso di acquisti con più segmenti, usare
cancelper annullare le riserve già create quando un leg fallisce. - Per i cambi, Cercaviaggio passa
codice_cambasearch/quote/reserve/book. - Date input:
dd/mm/YYYY. DateTime output: ISO 8601. - Valuta:
EUR.
Campi minimi richiesti
Evitiamo volutamente campi non necessari (es. GTFS/transitoria). Se un campo non è richiesto qui, puoi ometterlo.
sync_stopsitem:stop_id,name,lat,lon,is_active,updated_at.sync_linesitem:line_id,name,is_active,is_visible,updated_at.sync_tripsitem:trip_id,line_id,name,tempo_acquisto,is_active,is_visible,stops[].sync_trips.stops[]:stop_id,sequence,time,day_offset,is_active.sync_faresitem:fare_id,from_id,to_id,amount,currency,is_active,updated_at.search: lista soluzioni consegments(corsa/fermate/orari) efares(prezzo + disponibilità).quote: restituiscequote_token+pricing.amount+pricing.seats_available.reserve: accettaquote_token+contact+passengers[](almenofull_name).book: quandoshop_idè presente deve restituiretickets[](almenocode,passenger_name,departure_at,arrival_at,price,pdf_url).change_check: dato unticket_codeindica se è cambiabile e ritorna i riferimenti minimi (from_stop_id,to_stop_id,suggested_date_it).