Tutoriale
Come usare grok-4.7 tramite l'API HiAPI: curl, Python e una richiesta che funziona
Guida pratica dalla prima richiesta alla verifica della risposta
Cosa ti serve prima della prima richiesta
Prima di inviare qualsiasi cosa all'API, assicurati di avere quattro cose pronte. Saltare una di queste è la causa più comune di fallimento alla prima chiamata, e spesso il motivo del fallimento non ha nulla a che vedere con il modello stesso.
Un account HiAPI
Ti serve un account HiAPI.ai valido. Accedi alla dashboard per gestire progetti, chiavi e utilizzo. Tutte le operazioni in questo tutorial passano attraverso la stessa interfaccia API unificata, quindi la chiave che crei qui funziona per tutti i modelli offerti dalla piattaforma.
Una chiave API
Crea una chiave API nella dashboard e conservala in un luogo sicuro: durante i test puoi usare una variabile d'ambiente della shell, per qualsiasi cosa destinata alla produzione usa un gestore di segreti. Non committare mai le chiavi nei repository di codice e non incollarle nelle applicazioni client.
Per i test locali, esportala una volta per ogni sessione della shell:
export HIAPI_API_KEY="your-api-key-here"
L'URL di base
L'URL di base è l'indirizzo radice dell'API HiAPI. Tutte le richieste di questo tutorial sono relative ad esso. Consulta la tua dashboard per confermare l'URL di base esatto da usare per il tuo account e salvalo in una variabile, così che script e codice applicativo facciano riferimento allo stesso valore:
export HIAPI_BASE_URL="https://api.hiapi.ai"
L'identificatore del modello
L'identificatore del modello usato in questo tutorial è grok-4.7. Viene passato come stringa semplice nel corpo della richiesta. Se l'identificatore è errato, di solito ricevi un errore esplicito invece di un fallback silenzioso, quindi gli errori di battitura sono facili da individuare.
Una volta che questi quattro elementi — account, chiave, URL di base, ID modello — sono pronti, hai tutto il necessario per la forma della richiesta. Il metodo curl non richiede alcun SDK, e il metodo Python richiede solo un client HTTP che probabilmente hai già.
Verifica rapida dell'ambiente
Verifica che la chiave e l'URL di base siano visibili alla shell che stai per usare:
[ -n "$HIAPI_API_KEY" ] && echo "key set"
[ -n "$HIAPI_BASE_URL" ] && echo "base url set"
Se entrambe le righe vengono stampate, puoi passare alla sezione successiva.
La forma di una richiesta a grok-4.7 su HiAPI
Ogni richiesta in questo tutorial condivide gli stessi quattro elementi: endpoint, header di autenticazione, campo model e array messages. Comprenderli separatamente renderà molto più facile capire in seguito lo streaming e il tool calling, poiché queste funzionalità modificano solo una parte di questa forma.
Endpoint
La chiamata è una richiesta POST all'endpoint di chat completion sotto l'URL di base. In questo tutorial la rappresentiamo così:
POST {HIAPI_BASE_URL}/v1/chat/completions
Se la tua dashboard mostra un percorso diverso, usa quello della dashboard; in ogni caso, il corpo della richiesta è identico.
Header di autenticazione
L'autenticazione avviene tramite un bearer token nell'header Authorization:
Authorization: Bearer $HIAPI_API_KEY
Poiché è un header e non un parametro di query, la chiave non appare mai nell'URL, nei log di accesso o nella cronologia del browser.
Content-Type
Il corpo della richiesta è JSON, quindi invia Content-Type: application/json. curl e qualsiasi client HTTP Python possono impostarlo per te, ma vale la pena scriverlo esplicitamente, così l'insieme degli header non è ambiguo.
Corpo della richiesta: model e messages
Il corpo della richiesta è un oggetto JSON contenente almeno due campi:
model— la stringa dell'identificatore del modello, quigrok-4.7.messages— un array ordinato di oggetti messaggio. Ogni oggetto haroleecontent. I ruoli comuni sono:systemper le istruzioni che inquadrano la conversazione,userper la richiesta stessa,assistantper fornire turni precedenti del modello quando continui una conversazione.
Il corpo minimo della richiesta è il seguente:
{
"model": "grok-4.7",
"messages": [
{ "role": "system", "content": "You are a concise technical assistant." },
{ "role": "user", "content": "Explain what an idempotent HTTP method is in two sentences." }
]
}
Questo è l'intero contratto di una chiamata base. Qualsiasi altra cosa — streaming, definizioni di tool — sono campi aggiuntivi sullo stesso oggetto, ed è per questo che le sezioni precedenti sono importanti: una volta che questa forma è corretta, il resto è aggiuntivo.
Come appare la risposta
La risposta è un oggetto JSON. La parte che quasi sempre ti interessa si trova sotto choices, che è un array; ogni voce ha un message contenente role e content. Ci sono inoltre metadati, come il modello che ha elaborato la richiesta e un blocco usage che descrive il numero di token. Leggendo choices[0].message.content ottieni il testo della risposta. Gli altri campi sono utili per il logging e il monitoraggio dei costi, ma non sono necessari per iniziare.
Una richiesta curl funzionante
Una volta esportata la chiave e compresa la forma della richiesta, la chiamata curl è breve. Quando vuoi isolare la domanda dal codice applicativo, questa è la versione da copiare.
curl -sS "$HIAPI_BASE_URL/v1/chat/completions" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "grok-4.7",
"messages": [
{ "role": "system", "content": "You are a concise technical assistant." },
{ "role": "user", "content": "In one sentence, what is a bearer token?" }
]
}'
Cosa fa ogni flag
-sSmantiene l'output silenzioso, ma stampa comunque gli errori. Senza di esso, una richiesta fallita potrebbe sembrare una risposta vuota.- L'URL è composto dalla variabile dell'URL di base più il percorso di chat completion, così non devi mai codificare l'host direttamente negli script.
-H "Authorization: ..."invia il bearer token. La variabile viene espansa dalla shell, ed è per questo che esportarla prima è importante.-H "Content-Type: application/json"dice al server che il corpo della richiesta è JSON.-d '...'è il corpo della richiesta. Gli apici singoli attorno al JSON impediscono alla shell di interpretare le graffe e le virgolette al suo interno.
Se preferisci mettere il corpo della richiesta in un file, scrivilo in body.json e sostituisci il parametro -d con -d @body.json. Questo è spesso più chiaro una volta che l'array messages diventa lungo.
Leggere il JSON grezzo
La risposta arriva su stdout come oggetto JSON. Quando vuoi esaminarla a occhio, passala attraverso un formattatore:
curl -sS "$HIAPI_BASE_URL/v1/chat/completions" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d @body.json | python -m json.tool
Dovresti vedere un array choices il cui primo elemento contiene un oggetto message con una stringa content — quella stringa è la risposta del modello. Accanto ad essa ci sono di solito anche l'identificatore della risposta, il nome del modello ripetuto e un oggetto usage contenente il conteggio dei token di prompt e completion. Registra ora una risposta riuscita: sarà il riferimento con cui confrontarti quando verificherai il client Python.
Errori comuni in questa fase
Un 401 significa quasi sempre che il bearer token manca, è malformato o non è stato realmente esportato nella shell corrente. Un 400 con un messaggio relativo al corpo della richiesta di solito significa JSON malformato — virgole finali o virgolette tipografiche incollate dalla documentazione sono i colpevoli più comuni. Correggi questi due aspetti prima di guardare qualsiasi altra cosa.
La stessa richiesta in Python
La versione Python fa la stessa cosa con lo stesso corpo della richiesta. Riscriverla serve a passare dal test nella shell a codice inseribile in un'applicazione, dove il corpo della richiesta è una struttura dati invece di una stringa tra virgolette.
Usare la libreria standard
Se non vuoi aggiungere dipendenze, urllib è sufficiente:
import json
import os
import urllib.request
api_key = os.environ["HIAPI_API_KEY"]
base_url = os.environ["HIAPI_BASE_URL"]
payload = {
"model": "grok-4.7",
"messages": [
{"role": "system", "content": "You are a concise technical assistant."},
{"role": "user", "content": "In one sentence, what is a bearer token?"},
],
}
request = urllib.request.Request(
f"{base_url}/v1/chat/completions",
data=json.dumps(payload).encode("utf-8"),
headers={
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json",
},
method="POST",
)
with urllib.request.urlopen(request) as response:
body = json.loads(response.read().decode("utf-8"))
print(body["choices"][0]["message"]["content"])
Usare requests
Se requests è già nel tuo ambiente, la chiamata è più breve:
import os
import requests
response = requests.post(
f"{os.environ['HIAPI_BASE_URL']}/v1/chat/completions",
headers={"Authorization": f"Bearer {os.environ['HIAPI_API_KEY']}"},
json={
"model": "grok-4.7",
"messages": [
{"role": "system", "content": "You are a concise technical assistant."},
{"role": "user", "content": "In one sentence, what is a bearer token?"},
],
},
timeout=60,
)
response.raise_for_status()
print(response.json()["choices"][0]["message"]["content"])
Perché questa versione è più sicura per un'applicazione
Nota tre scelte deliberate. La chiave e l'URL di base provengono da variabili d'ambiente, mai da letterali nel codice sorgente. Il corpo della richiesta è un dizionario Python, quindi le virgolette fuori posto producono immediatamente un SyntaxError invece di un rifiuto lato server confuso. E la chiamata imposta un timeout: senza timeout, una connessione bloccata può sospendere un processo worker a tempo indeterminato.
Esegui la versione Python con lo stesso prompt usato in curl. La formulazione della risposta può variare leggermente tra esecuzioni — il modello non è deterministico — ma la struttura della risposta dovrebbe essere identica: un array choices, un message con content e un blocco usage. Se la struttura corrisponde, il client è connesso correttamente e tutte le sezioni successive sono miglioramenti opzionali.
Attivare lo streaming
Lo streaming cambia il modo in cui i token arrivano, non ciò che richiedi. Invece di aspettare la risposta completa, la ricevi progressivamente, ed è per questo che le interfacce chat sembrano così reattive.
Le modifiche alla richiesta
Aggiungi un campo al corpo della richiesta che hai già:
{
"model": "grok-4.7",
"stream": true,
"messages": [
{ "role": "user", "content": "Count from one to five, one number per line." }
]
}
L'endpoint, gli header o il resto dei messages non cambiano. È proprio questo il senso di imparare prima la forma base: lo streaming è un flag aggiuntivo, non una seconda API.
Cosa viene restituito
Con stream abilitato, la risposta non è più un singolo oggetto JSON. È una serie di server-sent events (SSE). Ogni evento trasporta una riga data:, il cui payload è un frammento JSON con la stessa forma della risposta normale, tranne per il fatto che in choices[0] c'è un oggetto delta invece del message completo. I primi frammenti possono contenere solo il ruolo; i frammenti intermedi trasportano parti di contenuto; il flusso termina con la riga sentinella data: [DONE].
Come client, il tuo compito è concatenare in ordine le stringhe delta.content e fermarti alla sentinella. Tratta qualsiasi frammento privo di content come un'operazione nulla, non come un errore.
Consumare i chunk in Python
import json
import os
import requests
with requests.post(
f"{os.environ['HIAPI_BASE_URL']}/v1/chat/completions",
headers={"Authorization": f"Bearer {os.environ['HIAPI_API_KEY']}"},
json={
"model": "grok-4.7",
"stream": True,
"messages": [{"role": "user", "content": "Count from one to five."}],
},
stream=True,
timeout=60,
) as response:
response.raise_for_status()
for line in response.iter_lines():
if not line:
continue
line = line.decode("utf-8")
if not line.startswith("data: "):
continue
data = line[len("data: "):]
if data == "[DONE]":
break
delta = json.loads(data)["choices"][0].get("delta", {})
text = delta.get("content")
if text:
print(text, end="", flush=True)
Due dettagli determinano se lo streaming funziona o sembra bloccarsi. Passa stream=True al client HTTP, così non bufferizza l'intero corpo della risposta, e itera riga per riga invece di leggere la risposta tutta in una volta. Il flush=True su print riguarda solo ciò che vedi sullo schermo; senza di esso, l'output potrebbe sembrare esplodere tutto alla fine, anche se i chunk vengono elaborati man mano che arrivano.
Verificare lo streaming separatamente
Non verificare streaming e tool calling nello stesso test. Prima conferma che il testo concatenato dia una risposta sensata a un prompt semplice, poi aggiungi le funzionalità una alla volta. Se il flusso termina senza la sentinella, è un segnale per controllare la connessione, non il modello.
L'opzione tool calling
Il tool calling permette al modello di richiedere funzioni definite nel tuo codice, invece di limitarsi a generare testo. Il lato richiesta si estende esattamente come per lo streaming.
Dove vanno le opzioni
Le definizioni dei tool sono un array tools sul corpo della richiesta. Ogni voce descrive un elemento chiamabile: nome, descrizione di quando usarlo e una descrizione JSON schema dei suoi parametri. La descrizione è più importante di quanto sembri — è l'unica guida che il modello ha per decidere quando un tool è applicabile.
{
"model": "grok-4.7",
"messages": [
{ "role": "user", "content": "What is the weather in Lisbon right now?" }
],
"tools": [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Return the current weather for a named city.",
"parameters": {
"type": "object",
"properties": {
"city": { "type": "string", "description": "City name, e.g. Lisbon" }
},
"required": ["city"]
}
}
}
]
}
La forma da ricordare è type più function, con name, description e parameters annidati. Se hai già definizioni di JSON schema, il blocco parameters è il posto dove metterle.
Come risponde il modello
Quando il modello decide che serve un tool, il messaggio assistant in choices[0] non è testo normale. Il suo content è di solito vuoto e trasporta un array tool_calls. Ogni voce ha un identificatore, un nome di funzione che corrisponde a una delle tue definizioni e una stringa arguments contenente JSON. Fai il parsing di quella stringa di arguments — è una stringa, non un oggetto, e trattarla come un oggetto è una fonte comune di errori.
Il tuo codice esegue quindi la funzione e invia una richiesta successiva: la conversazione originale, il messaggio assistant con tool_calls e un nuovo messaggio con ruolo tool contenente l'identificatore della chiamata e il risultato. Il modello usa quel risultato per generare la risposta finale. Il tool_call_id deve corrispondere all'identificatore nel messaggio assistant; senza di esso, la richiesta successiva è ambigua.
Misure di protezione pratiche
- Valida i parametri analizzati con lo stesso schema che hai inviato. Il modello è guidato dallo schema, ma non vincolato da esso.
- Tratta il nome della funzione restituito come input non attendibile e instrada solo verso una lista esplicita di funzioni consentite.
- Non abilitare
streame i tool contemporaneamente nel primo test. Conferma prima il round-trip non in streaming end-to-end, poi combinali se il tuo caso d'uso richiede entrambi.
Verificare le risposte prima di andare in produzione
Una chiamata che funziona nel terminale non equivale a un'integrazione verificata. Segui questa checklist per intero, poi conserva lo script come smoke test.
Confermare il livello di trasporto
Prima di fare il parsing di qualsiasi cosa, controlla che lo stato HTTP sia 200. Un client che fa il parsing per primo produrrà un confuso KeyError quando il vero problema è un 401. Verifica esplicitamente lo stato e registra il corpo della risposta in caso di fallimento — il server di solito indica cosa è andato storto.
Confermare la struttura della risposta
Verifica, non presumere. In una chiamata non in streaming riuscita, controlla tre cose: choices esiste e non è vuoto, choices[0].message.content è una stringa non vuota e il modello ripetuto nella risposta corrisponde a quello che hai inviato. Quest'ultimo controllo intercetta un numero sorprendente di errori di configurazione — un modello predefinito che sovrascrive quello richiesto.
Provare deliberatamente i percorsi di errore
Non aspettare che si verifichi un guasto per scoprire come si comporta il tuo codice. Esegui tre test negativi rapidi:
- Chiama rimuovendo l'header di autenticazione e conferma che il tuo codice esponga un errore di autenticazione esplicito, invece di riprovare all'infinito.
- Invia un corpo di richiesta senza il campo
modele conferma di ottenere un errore client, invece di un blocco. - Invia un prompt deliberatamente molto lungo e conferma che il timeout e la gestione del troncamento si comportino come previsto.
Ognuno dovrebbe produrre un fallimento concreto e registrato — non un generico "qualcosa è andato storto".
Verificare le funzionalità avanzate separatamente
Se hai abilitato lo streaming, conferma che i chunk concatenati formino una risposta coerente e che la sentinella termini il ciclo. Se hai abilitato i tool, conferma che il round-trip sia completo: la chiamata al tool viene analizzata, la funzione viene eseguita, il risultato ritorna con l'identificatore corrispondente e produce una risposta testuale finale. Metti ogni verifica in un piccolo script separato, così un fallimento indica una singola funzionalità.
Rendere i controlli ripetibili
Metti l'intera sequenza in un file, esci con codice diverso da zero se qualsiasi verifica fallisce ed eseguilo contro la tua configurazione di staging prima di ogni deployment. Dovrebbe richiedere solo pochi secondi e coprire la chiamata base, una chiamata in streaming e, se usi i tool, un round-trip di tool. Quando passa, puoi fidarti del fatto che i fallimenti in produzione dipendono dalle richieste che invii, non dall'infrastruttura sottostante.
Una volta superati i controlli, esegui ancora una volta la chiamata curl. Se il JSON grezzo corrisponde all'output della tua applicazione, l'integrazione è completa.
Articoli correlati
Vedi tutti gli articoli →-
Tutoriale
Come chiamare hailuo-2.3-fast/image-to-video tramite l'API HiAPI: pratica con curl e Python
La prima richiesta funzionante per il livello image-to-video veloce ed economico — dall'ID del modello al download di un MP4
-
Tutoriale
Come chiamare hailuo-2.3/text-to-video tramite l'API HiAPI: curl, Python ed esempi di richiesta eseguibili
-
Tutoriale
Utilizzare Kandinsky 6.0 Pro su HiAPI per la generazione di video da testo: tutorial con curl e Python
Dimostrazione pratica guidata dalla richiesta: costruire la chiamata da prompt a clip video, inviare la richiesta, monitorare lo stato di completamento e scaricare il risultato