Data di scadenza del contratto (Contratti)
Contratti
Leggere, creare, modificare ed eliminare contratti e abbonamenti con attributi, domini, cronologia dello stato e fatture associate. Lo stato viene modificato tramite un endpoint secondario dedicato.
GET /Export/JSON/contracts
GET /Export/JSON/contract/{id}
POST /Import/JSON/contracts
PUT /Import/JSON/contracts
PUT /Import/JSON/contracts/{id}/status
DELETE /Delete/JSON/contract/{id}Endpoint
| Metodo | Endpoint | Ambito | Descrizione |
|---|---|---|---|
| GET | /Export/JSON/contracts | contracts:read | Tutti i contratti, in ordine crescente per ID (con filtri) |
| GET | /Export/JSON/contract/{id} | contracts:read | Un contratto; se non vengono trovati risultati, viene restituito un codice HTTP 200 con un data |
| GET | /Export/JSON/contracts/{von}:{bis}, /contracts/{von}: | contracts:read | intervallo di ID o intervallo aperto |
| GET | /Export/JSON/contracts/{id} | contracts:read | ⚠️ Plurale: tutti i contratti a partire da questo ID, non solo uno |
| POST | /Import/JSON/contracts | contracts:write | Crea nuovi contratti |
| PUT | /Import/JSON/contracts | contracts:write | Modifica contratti esistenti |
| PUT | /Import/JSON/contracts/{id}/status | contracts:write | Modifica solo lo stato, con registrazione nella cronologia degli stati |
| DELETE | /Delete/JSON/contract/{id} | contracts:delete | Eliminare un contratto, compresi attributi, domini e cronologia degli stati |
| DELETE | /Delete/JSON/contracts | contracts:delete | Più contratti tramite JSON-Rumpf {"data": [{"contracts_id": …}]} |
/contracts/{von}:{bis}. Fino alla v2.122.11, /contracts/10/20 restituiva comunque i contratti a partire da 10 senza limite massimo, mentre ora restituisce un errore HTTP 400 INVALID_RANGE, così come qualsiasi altro segmento che non sia un numero intero o un intervallo (/contract/10x, /contract/10.0). Gli spazi vuoti ai margini dell’ID non vengono conteggiati. Regole: API di esportazione, sezione «Segmento di percorso».Filtro di query (GET)
| Parametri | Descrizione | Esempio |
|---|---|---|
?status= | ID di uno stato del contratto; gli stati del negozio sono riportati in contracts_statuses[] in ogni risposta | ?status=1 |
?customer_id= | ID cliente | ?customer_id=42 |
?product_id= | ID del prodotto | ?product_id=100 |
?interval= | Fatturazione per anno: 1 annuale, 2 semestrale, 3 tre volte all'anno, 4 trimestrale, 6 sei volte all'anno, 12 mensile | ?interval=12 |
?date_from=, ?date_to= | Data del contratto (contracts_date) da o fino a | ?date_from=2025-01-01 |
?active=1 | solo contratti senza data di disdetta inserita (contracts_cancellation_date_effective vuoto); anche una data di disdetta futura esclude il contratto | ?active=1 |
Più filtri agiscono in combinazione. Un valore non valido genera un errore HTTP 400 INVALID_FILTER_VALUE, ad esempio ?interval=5 (a partire dalla v2.122.10). A partire dalla v2.122.12, gli spazi vuoti ai margini non vengono conteggiati; un valore vuoto significa «non impostato».
Struttura dei dati
Ogni contratto presenta questi campi. I nomi dello stato e dell’articolo sono in tedesco.
| Sezione | Campi |
|---|---|
| ID e stato | contracts_id, contracts_status_id, contracts_status_name |
| Cliente | contracts_customers_id, customer_name, customer_email, contracts_customers_address_book_id, contracts_shipping_address_book_id |
| Articolo e prezzo | contracts_products_id, product_name, product_model, contracts_products_quantity, contracts_products_tax, contracts_price, contracts_final_price, contracts_discount, contracts_use_current_price |
| Fatturazione | contracts_interval e contracts_period_interval (valori come ?interval=, ciascuno con un campo corrispondente …_text con la denominazione), contracts_months, contracts_next_order_date, contracts_payment_class |
| Periodi | contracts_date; durata contracts_current_term_date_begin/_end, periodo di fatturazione contracts_current_period_date_begin/_end, ultima fatturazione contracts_last_billed_term_date_begin/_end e contracts_last_billed_period_date_begin/_end |
| Disdetta | contracts_cancellation_date_received, contracts_cancellation_date_effective |
| Dominio e licenza | contracts_domain_id, contracts_domain_name, contracts_overwrite_domain, contracts_xolic_id |
| Varie | contracts_comment, contracts_template, contracts_error_flag, contracts_is_standalone |
Dati annidati
| Elenco | Contenuto per ogni voce |
|---|---|
attributes[] | Caratteristiche dell’articolo contrattuale: contracts_products_attributes_id, contracts_products_id, products_options, products_options_values, options_values_price, detail_id |
domains[] | contracts_domains_id, contracts_domains_domain_name, contracts_domains_date_paid, contracts_domains_date_termination, contracts_domains_provider, contracts_domains_exclusive, contracts_domains_cost |
status_history[] | più recenti per primi: status_history_id, status_id, status_name, date_added, customer_notified, comments, user_id |
orders[] | fatture collegate, con il collegamento più recente per primo: orders_id, date_created, date_purchased, orders_status |
Oltre a data, in ogni risposta è presente contracts_statuses[] con gli stati contrattuali del negozio, che hanno una denominazione in tedesco (status_id, status_name, status_label, status_active, status_is_default).
Importazione (POST/PUT)
POSTcrea un nuovo record e richiedecontracts_customers_idecontracts_products_iddi un cliente o di un articolo esistente. Se viene inviato uncontracts_idgià esistente, il record non viene creato.PUTmodifica e richiede l'contracts_iddi un contratto esistente. Vengono modificati solo i campi inviati.- Sono modificabili i campi della struttura dati ad eccezione dei nomi e dei testi (
contracts_status_name,customer_name,customer_email,product_name,product_model,contracts_domain_name,…_text). Se si invia un’esportazione, l’importazione li segnala come campi sconosciuti (UNKNOWN_FIELD), così come gli elenchistatus_history[]eorders[]nonché gli identificatoricontracts_products_attributes_idecontracts_products_idinattributes[]econtracts_domains_idindomains[]. L’importazione li ignora e compila i campi rimanenti; rimuovete questi campi prima di inviare nuovamente i dati, in modo che la risposta non contenga avvisi. I campi data comeYYYY-MM-DD, i campi relativi ai periodi di fatturazione (…_period_date_…) comeYYYY-MM-DD HH:MM:SS;nullo lasciandoli vuoti li azzerano. contracts_intervalaccetta solo1,2,3,4,6o12; in caso contrario, il record viene rifiutato.attributes[]products_options, , e , accettano la chiave senza . Nel caso di , un elenco inviato insieme alla richiesta sostituisce tutte le voci precedenti.products_options_valuesoptions_values_pricedetail_iddomains[]contracts_domains_…contracts_domains_idPUTstatusCome oggetto,{"status_id": …, "comments": "…", "customer_notified": 0}imposta lo stato e registra una voce nella cronologia degli stati. v2.122.13 Sestatus_idnon è uno stato contrattuale del negozio (sezione «Stato contrattuale» in basso), non è un numero intero o manca, l’importazione salva il record senza lo stato e segnala l’avvisoCONTRACT_STATUS_UNKNOWN; il record viene considerato creato o modificato.contracts_status_idL’impostazione diretta sullo stato del contratto imposta lo stato senza inserire alcuna voce nella cronologia degli stati. v2.122.13 Un valore che non è uno stato contrattuale non viene salvato, mentre i campi rimanenti sì, con lo stesso avviso. Per una modifica dello stato con cronologia, utilizzarestatuso il sotto-endpoint/status.- ⚠️ Un valore impostato su «
contracts_cancellation_date_effective» può avere effetto alla successiva esecuzione della risoluzione automatica del contratto.
Esempio
curl -s -X POST "https://shop.de/xpanel/xoport/Import/JSON/contracts" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"type": "contracts",
"data": [{
"contracts_customers_id": 42,
"contracts_products_id": 100,
"contracts_interval": 12,
"contracts_price": "29.90",
"contracts_date": "2026-11-01",
"attributes": [
{"products_options": "Lizenztyp", "products_options_values": "Enterprise"}
],
"domains": [
{"contracts_domains_domain_name": "kunde.de"}
],
"status": {"status_id": 1, "comments": "Angelegt per API"}
}]
}'Modifica dello stato (PUT)
PUT /Import/JSON/contracts/{id}/status con l’ambito contracts:write. È obbligatorio specificare status_id, oltre a comments e customer_notified(facoltativi). Senza status_id si ottiene un errore HTTP 400 MISSING_FIELD; per un status_id che non corrisponda a uno stato contrattuale del negozio o a un numero intero, si ottiene un errore HTTP 400 INVALID_STATUS con gli ID validi riportati in error.valid_status_ids (a partire dalla v2.122.13, sezione «Stato del contratto») e, per un contratto sconosciuto, HTTP 404 NOT_FOUND. In tutti e tre i casi il contratto rimane invariato.
curl -s -X PUT "https://shop.de/xpanel/xoport/Import/JSON/contracts/1/status" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"status_id": 3, "comments": "Kündigung per API", "customer_notified": 0}'
# Antwort
{
"success": true,
"type": "contracts_status",
"contracts_id": 1,
"previous_status_id": 1,
"new_status_id": 3,
…
}Se il contratto ha una data di risoluzione valida, la risposta riporta inoltre warning: la risoluzione automatica del contratto può sovrascrivere lo stato in un secondo momento.
Stato del contratto v2.122.13
Per status_id, status.status_id e contracts_status_id è valido qualsiasi stato del contratto del negozio: gli stati della tabella status con type = 'contracts', da cui attinge anche il backend, in ogni lingua, compresi quelli disattivati (status_active = 0); questi ultimi nascondono solo la selezione nel backend. Gli stati dell’ordine (/order_statuses) non sono stati contrattuali. Gli ID validi variano a seconda del negozio: consultateli su contracts_statuses[], su GET /Export/JSON/contracts o su error.valid_status_ids. contracts_statuses[] elenca solo gli stati con denominazione in tedesco; uno stato senza denominazione in tedesco è comunque valido.
L’ID è un numero intero, espresso come cifra singola o sequenza di cifre (54, "54"; gli spazi in margine non contano). true, [65], "54abc", "1e3", 54.9 o 54.0 non sono ID.
| Modalità di invio | Stato del contratto non valido |
|---|---|
PUT /Import/JSON/contracts/{id}/status | HTTP 400 INVALID_STATUS, error.valid_status_ids indica gli ID validi; il contratto rimane invariato |
Importazione del contratto, status.status_id (anche status senza status_id, ad esempio "status": 54 o "status": {}) | Record scritto, stato e cronologia dello stato invariati, avviso CONTRACT_STATUS_UNKNOWN con field = status.status_id o status; "status": null è considerato non inviato |
Importazione del contratto, contracts_status_id | campo non compilato (rimane vuoto al momento della creazione), altri campi compilati, avviso CONTRACT_STATUS_UNKNOWN con field = contracts_status_id |
HTTP 400
{
"success": false,
"api_version": "2.122.13",
"error": {
"code": "INVALID_STATUS",
"message": "status_id 1 is not a contract status. Valid: 7, 3, 12 (…)",
"valid_status_ids": [7, 3, 12]
}
}Nell’importazione del contratto, il record continua a essere conteggiato come inserted o updated. L’avviso è presente in warnings[] nella risposta e nella voce del record in records[]:
"warnings": [
{
"type": "CONTRACT_STATUS_UNKNOWN",
"field": "status.status_id",
"entity": "contracts",
"contracts_id": 42,
"message": "Contract 42: status.status_id ignored — status.status_id 1 is not a contract status. Valid: 7, 3, 12 (…)",
"first_occurrence": "record 1"
}
]/status e l’oggetto status effettuavano un controllo incrociato con gli stati dell’ordine (orders_status). Uno stato del contratto che non fosse presente anche come stato dell’ordine generava un errore HTTP 400 nel sotto-endpoint e veniva silenziosamente ignorato durante l’importazione; un ID presente solo come stato dell’ordine veniva scritto come stato del contratto nell’endpoint con il nome dello stato dell’ordine in new_status_name. contracts_status_id veniva scritto senza essere verificato ("abc" come 0, true come 1), mentre valori come "1e3" o 54.9 venivano considerati rispettivamente come 1000 e 54. ⚠️ Chi invia gli ID dello stato dell’ordine come stato del contratto riceverà ora un codice di errore HTTP 400 o l’avviso: utilizzare gli ID disponibili su contracts_statuses[]. new_status_name ora riporta il nome dello stato del contratto.Eliminazione (DELETE)
Vengono eliminati il contratto, i suoi attributi e domini, la cronologia dello stato e i collegamenti a fatture e progetti. Le fatture e i progetti stessi rimangono.
orders[] da GET /Export/JSON/contract/{id}, ciascuna con il proprio stato d’ordine orders_status. Per verificare se uno stato è considerato pagato, consultare is_paid in GET /Export/JSON/order_statuses (Ordini, sezione «Dati anagrafici stato d’ordine»).# Ein Vertrag
curl -s -X DELETE "https://shop.de/xpanel/xoport/Delete/JSON/contract/1" \
-H "Authorization: Bearer $TOKEN"
# Mehrere Verträge
curl -s -X DELETE "https://shop.de/xpanel/xoport/Delete/JSON/contracts" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"data": [{"contracts_id": 1}, {"contracts_id": 2}]}'- Un contratto sconosciuto genera un errore HTTP 404
NOT_FOUNDse richiamato singolarmente. In caso di elaborazione in batch, gli ID cancellati si trovano indeleted_ids, quelli non trovati inerrors[]. - Un URL troncato senza
data[].contracts_id, ad esempio{"ids": [1, 2]}, non cancella nulla e restituisce un errore HTTP 400MISSING_DATA.
Ambiti OAuth2
| Ambito | Autorizzazione |
|---|---|
contracts:read | Leggere i contratti |
contracts:write | Creare e modificare contratti, compreso lo stato |
contracts:delete | Eliminare contratti |