---
title: "Utilizzo della REST API"
url: "https://www.4hse.com/it/news/2024-02-15"
description: "Una guida dettagliata per sviluppatori sull'uso della REST API di 4HSE: panoramica dell'architettura, metodi di autenticazione, regole di autorizzazione e operazioni CRUD. Il documento include un esempio per semplificare l'integrazione e l'utilizzo dell'API."
---

15 feb 2024

# Utilizzo della REST API

Una guida dettagliata per sviluppatori sull'uso della REST API di 4HSE: panoramica dell'architettura, metodi di autenticazione, regole di autorizzazione e operazioni CRUD. Il documento include un esempio per semplificare l'integrazione e l'utilizzo dell'API.

![Utilizzo della REST API](/_astro/hero.DXbIk_xA_Z21QiDE.webp)

## Introduzione

In questa guida descriveremo l’architettura di 4HSE e i servizi web che offre agli sviluppatori. Successivamente, costruiremo un esempio di codice che include l’uso dell’API e copre uno scenario di sviluppo comune.

-   [Introduzione](#introduzione)
-   [API Standard](#api-standard)
-   [Autenticazione](#autenticazione)
-   [oauth2](#oauth2)
-   [access-token](#access-token)
-   [Autorizzazione (ACL)](#autorizzazione-acl)
-   [Chiamate](#chiamate)
    -   [INDEX](#index)
    -   [VIEW](#view)
    -   [CREATE](#create)
    -   [UPDATE](#update)
    -   [DELETE](#delete)
-   [Esempio di codice](#esempio-di-codice)

## API Standard

La piattaforma 4HSE fornisce un ampio set di servizi web che consentono di gestire i dati dei propri progetti. Tutti i servizi seguono lo [Standard HTTP REST API](https://roy.gbiv.com/pubs/dissertation/rest_arch_style.htm) e offrono operazioni CRUD sulle risorse.

> Una risorsa è un elenco di attributi (ad esempio, una persona è descritta da nome, cognome, ecc.). Ogni risorsa ha un identificatore univoco, l’attributo `id`, che ne garantisce l’unicità. Le risorse sono raggruppate in collezioni in base al loro tipo (tutte le risorse di tipo “persona” sono raggruppate nella collezione “person”).

Per ogni collezione, generalmente, sono disponibili cinque endpoint di base:

```
- GET <collection>/index
- GET <collection>/view/<my_resource_id>
- POST <collection>/create {payload}
- PUT <collection>/update/<my_resource_id> {payload}
- DELETE <collection>/delete/<my_resource_id>
```

Può capitare che una collezione non segua esattamente questo standard. Tuttavia, tutte le API disponibili sono ben documentate [qui](https://docs.4hse.com/it/dev/guides/using-rest-api/) secondo lo standard [Open API](https://swagger.io/specification/).

## Autenticazione

Per accedere alle API di 4HSE è necessario autenticarsi. Esistono due modalità di autenticazione:

-   oauth2
-   auth\_code

Supponiamo di voler recuperare l’elenco delle sedi ordinate per nome. In tal caso, bisognerebbe chiamare l’API:  
`service.4hse.com/office/index?sort=-name&limit=50&offset=51`

Se si effettua questa chiamata senza autenticazione, si riceverà il codice di risposta `Unauthorized (401)`. È necessario utilizzare uno dei due metodi di autenticazione sopra indicati affinché la chiamata funzioni correttamente.

> Questo è solo un esempio. Una spiegazione più dettagliata delle API e delle modalità di chiamata è fornita nei capitoli successivi.

## oauth2

Utilizziamo lo standard oauth2 per autenticare gli utenti.

L’URI dell’API è: `service.4hse.com/oauth2/token`

Per ottenere un token, è necessario conoscere i seguenti dati:

-   `client_id` – un identificatore univoco che rappresenta il client
-   `client_secret` – la password associata al client\_id
-   `username` – il tuo nome utente
-   `password` – la tua password

oppure, se hai già ottenuto un token:

-   `client_id` – un identificatore univoco che rappresenta il client
-   `client_secret` – la password associata al client\_id
-   `refresh_token` – il token di aggiornamento che hai ricevuto in una chiamata precedente alla stessa API

> Ogni cliente che desidera utilizzare l’API deve avere il proprio `client_id` e `client_secret`. Dovresti chiedere al supporto 4hse per ottenere questi due dati.

Quando accedi al servizio per la prima volta, devi utilizzare il tuo nome utente e la tua password (ovviamente anche `client_id` e `client_secret`):

```
REQUEST
---
URI: service.4hse.com/oauth2/token
Host: service.4hse.com
Method: POST
Request Payload:
{
 "client_id": "example_client_id",
 "client_secret": "example_client_secret",
 "grant_type": "password",
 "username": "example_user",
 "password": "example_password"
}
```

Successivamente, riceverai una risposta simile alla seguente:

```
RESPONSE
---
Status Code: 200 OK
Content-Type: application/json
Body:
{
 "access_token": "433b8caa8ea9839b5a732a9455ee50bef31fe4e0",
 "expires_in": 86400,
 "token_type": "Bearer",
 "scope": null,
 "refresh_token": "84c893bdd88fb52400c5d8fc246e81bd544a3486",
 "user_id": "example_user"
}
```

L’ `access_token` è il token bearer che puoi utilizzare per accedere a tutte le API. Come indicato, scade dopo 86400 secondi (24 ore). Come puoi vedere, nella risposta c’è anche il `refresh_token`, che puoi utilizzare per ottenere un nuovo `access_token` senza dover usare `username` e `password`. Ricorda che il `refresh_token` scade dopo 14 giorni. La chiamata in questo caso sarà simile a questa:

```
REQUEST
---
URI: service.4hse.com/oauth2/token
Host: service.4hse.com
Method: POST
Request Payload:
{
 "client_id": "example_client_id",
 "client_secret": "example_client_secret",
 "grant_type": "refresh_token",
 "refresh_token": "84c893bdd88fb52400c5d8fc246e81bd544a3486"
}
```

Questa chiamata ti restituirà un nuovo `access_token` e un nuovo `refresh_token` (quello precedente verrà disabilitato).

```
RESPONSE
---
Status Code: 200 OK
Content-Type: application/json
Body:
{
 "access_token": "b483aff34847b87786bb1a6c313b9e40b2bcf749",
 "expires_in": 86400,
 "token_type": "Bearer",
 "scope": null,
 "refresh_token": "c645d84be64791ccf1ee1f148c4f2281a97ae49b",
 "user_id": "example_user"
}
```

Per effettuare una chiamata al sistema utilizzando il bearer token, devi aggiungere a tutte le tue richieste un nuovo header, come nell’esempio sopra:

```
Authorization: Bearer b483aff34847b87786bb1a6c313b9e40b2bcf749
```

Ora possiamo tornare alla precedente API che hai chiamato: `service.4hse.com/office/index?sort=-name&limit=50&offset=51`. Come ricordi, senza autenticazione hai ricevuto il codice di risposta `Unauthorized (401)`. Ma ora che hai il bearer token, puoi effettuare la stessa chiamata aggiungendo l’header di autorizzazione richiesto:

```
REQUEST
---
URI: service.4hse.com/office/index?sort=-name&limit=50&offset=51
Host: service.4hse.com
Method: GET
Content-Type: application/json
Authorization: Bearer b483aff34847b87786bb1a6c313b9e40b2bcf749
```

Effettuando la chiamata in questo modo, riceverai il codice `Success (200)` e l’elenco degli uffici richiesti.

## access-token

Questo metodo è molto semplice, poiché è necessario aggiungere solo il parametro di query `access-token` a ogni chiamata API. Devi contattare il supporto 4hse per ottenere l’`access-token`. Questo sarà generato su tua richiesta.

> Tieni presente che questo `access-token` è completamente diverso e non ha alcuna relazione con l’oauth2.

Quando hai questo token, puoi effettuare la stessa chiamata precedente aggiungendo il parametro di query `access-token`. Se il tuo access token è `sample-access-token`, puoi semplicemente chiamare:

```
service.4hse.com/office/index?sort=-name&limit=50&offset=51&access-token=sample-access-token
```

Effettuando la chiamata in questo modo, riceverai il codice `Success (200)` e l’elenco degli uffici richiesti.

## Autorizzazione (ACL)

Tutti i servizi web operano all’interno di un sistema di controllo degli accessi. Le regole di controllo degli accessi seguono le autorizzazioni definite per l’utente corrente.

Esempio

L’utente `user-1` è manager di `office-1` e non ha alcun accesso a `office-2`. Se `user-1` tenta di accedere a `office-2` chiamando il servizio `office/view/office-2`, il server risponde con il codice di stato `404 Not found` perché l’utente non è autorizzato a visualizzare la risorsa `office-2`.

Questo comportamento è comune a tutti i servizi, tranne per `index`. Quando un utente chiede l’elenco delle risorse (una collezione) utilizzando `index`, il server risponde con l’elenco delle risorse che l’utente può vedere in base alle sue regole di controllo accessi.

Esempio

L’utente `user-1` è manager di `office-1` e `office-3`, e chiama `office/index`. Il server risponde con un elenco di uffici che contiene solo `office-1` e `office-3`. L’`office-2` viene saltato perché l’utente non può accedervi.

## Chiamate

### INDEX

Questa chiamata restituisce un elenco delle risorse della collezione a cui si riferisce. Parametri opzionali:

-   `sort`(1): ordina il risultato in base a un attributo della risorsa. Per impostazione predefinita l’ordinamento è in modalità ASC. Per ordinare in modalità DESC aggiungi il prefisso `-`.
-   `limit`(2): limita il set di risultati a un numero massimo di elementi. Per impostazione predefinita il valore è `100`.
-   `offset`(3): l’indice del primo elemento del set di risultati.

Per parametri specifici della collezione (filtri, dati aggiuntivi ecc.) puoi consultare la nostra [Documentazione API](https://docs.4hse.com/it/dev/guides/using-rest-api/).

```
REQUEST
---
URI: service.4hse.com/office/index?sort=-name&limit=50&offset=51
Host: service.4hse.com
Method: GET
Content-Type: application/json
Query String Parameters:
 sort: -name // <b>(1)</b>
 limit: 50 // <b>(2)</b>
 offset: 51 // <b>(3)</b>
```

La risposta contiene:

-   `data`(4): elenco delle risorse che soddisfano i parametri della richiesta
-   `total_count`(5): il numero di elementi che corrispondono alla query corrente. Potrebbe essere diverso dal numero delle risorse presenti in `data`.
-   `pos`(6): l’offset corrente.

```
RESPONSE
---
Status Code: 200 OK
Content-Type: application/json
Body:
{
 "data": [
 {
 "id": "office-2-534443", // <b>(4)</b>
 "office_id": "office-2-534443",
 "name": "Office 2",
 ...
 },
 {
 "id": "office-1-213414",
 "office_id": "office-1-213414",
 "name": "Office 1",
 ...
 },
 ...
 ],
 "total_count": "2000" // <b>(5)</b>
 "pos": 51 // <b>(6)</b>
}
```

### VIEW

Restituisce una risorsa con i suoi dettagli. Il parametro obbligatorio è `id`(1), necessario per identificare la risorsa. Questo parametro sarà riportato due volte nella risposta come attributi `id`(2) e `<collection>_id`(3). Una sede avrà gli attributi `id` e `office_id` con lo stesso valore.

Per parametri specifici della collezione (filtri, dati aggiuntivi ecc.) puoi consultare la nostra [Documentazione API](https://docs.4hse.com/it/dev/guides/using-rest-api/).

```
REQUEST
---
URI: service.4hse.com/office/view/office-1-534443
Host: service.4hse.com
Method: GET
Query String Parameters:
 id: office-1-534443 // <b>(1)</b>
```

La risposta contiene la risorsa nel `body`.

```
RESPONSE
---
Status Code: 200 OK
Content-Type: application/json
Body:
{
 "data": {
 "id": "office-1-534443", // <b>(2)</b>
 "office_id": "office-1-534443", // <b>(3)</b>
 "name": "Office 1",
 ...
 }
}
```

### CREATE

Richiede un `payload`(1) contenente l’attributo `<collection>_id`(2) e tutti gli attributi richiesti per la risorsa.

Per parametri specifici della collezione puoi consultare la nostra [Documentazione API](https://docs.4hse.com/it/dev/guides/using-rest-api/).

```
REQUEST
---
URI: service.4hse.com/office/create
Host: service.4hse.com
Method: POST
Request Payload: // <b>(1)</b>
{
 "office_id": "office-1-534443", // <b>(2)</b>
 "name": "Office 1",
 ...
}
```

La risposta contiene la risorsa creata all’interno del `body`.

```
RESPONSE
---
Status Code: 201 Created
Content-Type: application/json
Body:
{
 "data": {
 "id": "office-1-534443",
 "office_id": "office-1-534443",
 "name": "Office 1",
 ...
 }
}
```

### UPDATE

Come per il `view`, è necessario il parametro `id`(1) per identificare la risorsa. Inoltre, è necessario fornire un `payload`(2) contenente `id`(3), `<collection>_id`(4) e gli attributi aggiornati (5).

```
REQUEST
---
URI: service.4hse.com/office/update/office-1-534443
Host: service.4hse.com
Method: PUT
Query String Parameters:
 id: office-1-534443 //<b>(1)</b>
Payload: //<b>(2)</b>
 {
 "id": "office-1-534443", //<b>(3)</b>
 "office_id": "office-1-534443", //<b>(4)</b>
 "name":"new name for office 1", //<b>(5)</b>
 ...
 }
```

La risposta contiene la risorsa aggiornata all’interno del `body`.

```
RESPONSE
---
Status Code: 200 OK
Content-Type: application/json
Body:
{
 "data": {
 "id": "office-1-534443",
 "office_id": "office-1-534443",
 "name":"new name for office 1",
 ...
 }
}
```

### DELETE

È necessario il parametro `id`(1) per identificare la risorsa da eliminare.  
Inoltre, è possibile specificare il parametro `force`(2), che per impostazione predefinita è `false`.  
Quando `force = false`, il servizio non elimina la risorsa, ma risponde con una richiesta di conferma che include eventualmente le risorse correlate a quella selezionata.

> Ogni elemento in 4HSE fa parte di una struttura gerarchica di dipendenze. Se si elimina una persona, tutte le risorse ad essa collegate (certificati, formazioni, ecc.) verranno eliminate insieme ad essa. Questa pratica garantisce la coerenza dei dati ed evita elementi orfani.

```
REQUEST
---
URI: service.4hse.com/office/delete/office-1-534443
Host: service.4hse.com
Method: DELETE
Query String Parameters:
 id: office-1-534443 // <b>(1)</b>
 force: false // <b>(2)</b>
```

Quando `force = false`, il servizio risponde con `400 Bad Request` e include nel `body` le risorse correlate.  
Ogni risorsa collegata è identificata da:

-   `id`(3): identificativo univoco della risorsa
-   `label`(4): etichetta descrittiva della risorsa
-   `type`(5): tipologia della risorsa

```
RESPONSE
---
Status Code: 400 Bad Request
Content-Type: application/json
Body:
{
 "message": "Addictions are present",
 "code": 1001,
 "data": [
 {
 "id": "office-1-534443", // <b>(3)</b>
 "label": "Office 1", // <b>(4)</b>
 "type": "OFFICE" // <b>(5)</b>
 }
 ]
}
```

Se `force = true`(2), il servizio elimina la risorsa identificata da `id`(1) e tutte le risorse correlate.

```
REQUEST
---
URI: service.4hse.com/office/delete/office-1-534443
Host: service.4hse.com
Method: DELETE
Query String Parameters:
 id: office-1-534443 //<b>(1)</b>
 force: true //<b>(2)</b>
```

```
RESPONSE
---
Status Code: 204 No Content
Content-Type: application/json
```

## Esempio di codice

In questo esempio di codice realizzeremo una semplice applicazione CRUD che utilizza le API REST di 4HSE.

### Requisiti:

-   Ambiente di lavoro con Python 3
-   Libreria `python-requests`
-   Libreria `python-uuid`

Iniziamo scrivendo il codice per recuperare una lista di uffici chiamando il servizio `office/index`.

```
import requests <b>(1)</b>

params = {'limit': 10, 'sort': '-name'} <b>(2)</b>
r = requests.get('https://service.4hse.com/office/index', params=params) <b>(3)</b>
print(r.text) #{data: [{'office_id':'sad14024000hdg002252','name':'My first office', 'project_id':'prj1234567'}], total_count: 1, pos: 0}
print(r) #<Response [200]>
```

1.  Importa la libreria per effettuare richieste HTTP.
2.  Definisci un insieme di parametri per la richiesta. In questo caso, vogliamo limitare il set di risultati a `10` risorse, ordinate in ordine decrescente per nome della sede.
3.  Effettua la richiesta e stampa i risultati.

Il prossimo passo è la creazione di una nuova sede utilizzando il servizio `office/create`.

```
import uuid

project_id = r.json().get('data')[0].get('project_id') # es. prj1234567 <b>(1)</b>
office_id = uuid.uuid1() # es. 00a5d37c-4fe2-46ee-b820-77ce0ac22725 <b>(2)</b>

payload = {'office_id': office_id, 'name': 'My new office', 'project_id': project_id} <b>(3)</b>
r = requests.post('https://service.4hse.com/office/create', data=payload, params=authentication) <b>(4)</b>
print(r.text) #{'data': {'office_id': '00a5d37c-4fe2-46ee-b820-77ce0ac22725', 'name': 'My new office', 'project_id': 'prj1234567'} }
print(r) #<Response [201]>
```

1.  Un attributo obbligatorio per la sede è `project_id`, che identifica il progetto all’interno del quale vogliamo creare la sede. In questo esempio, lo recuperiamo dalla prima sede restituito dalla chiamata `index`.
2.  Utilizza la libreria `uuid` di Python per generare un identificativo univoco per la sede.
3.  Definisci un payload che includa `office_id`, `project_id` e l’attributo obbligatorio `name`.
4.  Effettua la richiesta e stampa i risultati.

Ora andremo a recuperare la sede appena creata utilizzando il servizio `office/view`.

```
params = {'id': office_id} <b>(1)</b>
r = requests.get('https://service.4hse.com/office/view', params=params) <b>(2)</b>
print(r.text) #{'data': {'office_id': '00a5d37c-4fe2-46ee-b820-77ce0ac22725', 'name': 'My new office', 'project_id': 'prj1234567'} }

print(r) #<Response [200]>
new_office = r.json().get('data') <b>(3)</b>
```

1.  Definisci i parametri includendo `office_id`.
2.  Effettua la richiesta e stampa il risultato.
3.  Infine, memorizziamo la sede appena creata all’interno di `new_office`.

Ora vogliamo modificare il nome della nostra sede utilizzando il servizio `office/update`.

```
params = {'id': office_id}
payload = new_office
payload.update({'name': 'new name for my office'}) <b>(1)</b>
r = requests.put('https://service.4hse.com/office/update', data=payload, params=params) <b>(2)</b>
print(r.text) #{'data': {'office_id': '00a5d37c-4fe2-46ee-b820-77ce0ac22725', 'name': 'new name for my office', 'project_id': 'prj1234567'} }
print(r) #<Response [200]>
```

1.  Usa `new_office` come payload della richiesta e cambia il suo attributo `name`.
2.  Effettua la richiesta e stampa il risultato.

Infine, eliminiamo la sede utilizzando il servizio `office/delete`.

```
params = {'id': office_id, 'force': 'true'} <b>(1)</b>
r = requests.delete('https://service.4hse.com/office/delete', params=params) <b>(2)</b>
print(r) #<Response [204]>
```

1.  Definisci i parametri includendo l’`office_id` che vogliamo eliminare e `force = true` per confermare che vogliamo eliminare l’elemento.
2.  Effettua la richiesta e stampa il risultato.

Fonti: [https://github.com/4hse/example-rest-api-client](https://github.com/4hse/example-rest-api-client)