Autenticazione OAuth 2.0

UniMsg utilizza OAuth 2.0 con il flusso Client Credentials per l'autenticazione API. Questo flusso è ideale per comunicazioni server-to-server dove non è richiesta l'interazione utente.

Credenziali

Per autenticarti, hai bisogno di:

Credenziale Descrizione Esempio
client_id Identificativo pubblico del client demo_xxxxxxxxxxxx
client_secret Chiave segreta (mai condividere!) sk_test_xxxxxxxxxxxx

Trovi le credenziali in: Dashboard → Impostazioni → API

Sicurezza: Non includere mai client_secret nel codice client-side (browser, app mobile). Usa sempre chiamate server-side.

Ottenere un Access Token

POST /oauth/token

Richiesta

POST /oauth/token HTTP/1.1
Host: api.unimsg.app
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&client_id=demo_xxxxxxxxxxxx&client_secret=sk_test_xxxxxxxxxxxx

Parametri

Parametro Tipo Obbligatorio Descrizione
grant_type string Deve essere client_credentials
client_id string Il tuo Client ID
client_secret string Il tuo Client Secret
scope string No Scopes separati da spazio

Risposta Successo

{
    "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2FwaS51bmltc2cuYXBwIiwic3ViIjoiY2xpZW50XzEyMzQ1Iiwic2NvcGVzIjpbInNtczpzZW5kIiwiZW1haWw6c2VuZCJdLCJleHAiOjE3MDUzMjU2MDB9.signature",
    "token_type": "Bearer",
    "expires_in": 3600,
    "scope": "sms:send email:send whatsapp:send telegram:send"
}

Risposta Errore

{
    "error": "invalid_client",
    "error_description": "Client authentication failed"
}

Usare l'Access Token

Includi l'access token nell'header Authorization di ogni richiesta API:

GET /v1/account/balance HTTP/1.1
Host: api.unimsg.app
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...

Scopes Disponibili

Gli scopes limitano le operazioni che un token può eseguire:

Scope Descrizione
sms:send Invio SMS
sms:read Lettura stato SMS
whatsapp:send Invio WhatsApp
whatsapp:read Lettura stato WhatsApp
email:send Invio Email
email:read Lettura stato Email
telegram:send Invio Telegram
telegram:read Lettura stato Telegram
account:read Lettura info account e crediti

Se non specifichi scope, il token avrà tutti gli scope disponibili per il tuo account.

Durata Token

Gli access token hanno una durata di 1 ora (3600 secondi). Quando scade:

  1. Le richieste API restituiranno errore 401 Unauthorized
  2. Richiedi un nuovo token con le stesse credenziali
  3. Non è necessario "invalidare" il vecchio token
Best Practice: Salva il token e expires_in. Rinnova il token qualche minuto prima della scadenza per evitare interruzioni.

Esempi di Codice

cURL

curl -X POST https://api.unimsg.app/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -d "client_id=demo_xxxxxxxxxxxx" \
  -d "client_secret=sk_test_xxxxxxxxxxxx"

PHP

<?php
class UniMsgClient
{
    private string $clientId;
    private string $clientSecret;
    private ?string $accessToken = null;
    private ?int $tokenExpiry = null;

    public function __construct(string $clientId, string $clientSecret)
    {
        $this->clientId = $clientId;
        $this->clientSecret = $clientSecret;
    }

    public function getAccessToken(): string
    {
        // Check if token is still valid
        if ($this->accessToken && $this->tokenExpiry > time() + 60) {
            return $this->accessToken;
        }

        // Request new token
        $ch = curl_init();
        curl_setopt_array($ch, [
            CURLOPT_URL => 'https://api.unimsg.app/oauth/token',
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => http_build_query([
                'grant_type' => 'client_credentials',
                'client_id' => $this->clientId,
                'client_secret' => $this->clientSecret
            ])
        ]);

        $response = curl_exec($ch);
        $data = json_decode($response, true);
        curl_close($ch);

        if (isset($data['access_token'])) {
            $this->accessToken = $data['access_token'];
            $this->tokenExpiry = time() + $data['expires_in'];
            return $this->accessToken;
        }

        throw new Exception('Failed to obtain access token');
    }
}

Python

import requests
import time

class UniMsgClient:
    def __init__(self, client_id: str, client_secret: str):
        self.client_id = client_id
        self.client_secret = client_secret
        self.access_token = None
        self.token_expiry = 0

    def get_access_token(self) -> str:
        # Check if token is still valid
        if self.access_token and self.token_expiry > time.time() + 60:
            return self.access_token

        # Request new token
        response = requests.post(
            'https://api.unimsg.app/oauth/token',
            data={
                'grant_type': 'client_credentials',
                'client_id': self.client_id,
                'client_secret': self.client_secret
            }
        )

        data = response.json()
        if 'access_token' in data:
            self.access_token = data['access_token']
            self.token_expiry = time.time() + data['expires_in']
            return self.access_token

        raise Exception('Failed to obtain access token')

Node.js

const axios = require('axios');

class UniMsgClient {
    constructor(clientId, clientSecret) {
        this.clientId = clientId;
        this.clientSecret = clientSecret;
        this.accessToken = null;
        this.tokenExpiry = 0;
    }

    async getAccessToken() {
        // Check if token is still valid
        if (this.accessToken && this.tokenExpiry > Date.now() + 60000) {
            return this.accessToken;
        }

        // Request new token
        const response = await axios.post(
            'https://api.unimsg.app/oauth/token',
            new URLSearchParams({
                grant_type: 'client_credentials',
                client_id: this.clientId,
                client_secret: this.clientSecret
            })
        );

        if (response.data.access_token) {
            this.accessToken = response.data.access_token;
            this.tokenExpiry = Date.now() + (response.data.expires_in * 1000);
            return this.accessToken;
        }

        throw new Error('Failed to obtain access token');
    }
}

Errori di Autenticazione

Codice HTTP Error Descrizione
400 invalid_request Parametri mancanti o non validi
401 invalid_client Credenziali non valide
401 invalid_token Token scaduto o revocato
403 insufficient_scope Token non ha lo scope richiesto

Security Best Practices