spicyapiDokumentacja
SDK
Treść główna

SDK dla Go

Oficjalne SDK SpicyAPI dla Go (github.com/spicyapi-ai/spicy-go): instalacja, wycena i pierwsza generacja, wysyłanie plików z dysku, przeglądanie historii zadań i obsługa wszystkich kodów błędów.

spicy-go to oficjalne SDK SpicyAPI dla Go. Generowanie obrazów, wideo i dźwięku chowa za jednym *spicy.Client: dołącza twój klucz API, zamienia strukturę odpowiedzi na typowane struktury, czeka na zadanie z ograniczonym wydłużaniem odstępów, wysyła pliki z dysku jednym wywołaniem i nadaje każdemu niepowodzeniu jeden typ błędu, który dopasujesz przez errors.As.

Wymaga Go 1.23 lub nowszego i korzysta wyłącznie z biblioteki standardowej. To celowe: ten pakiet trafia do twojego grafu zależności, a każdy moduł, który by ze sobą przyciągnął, to kolejna rzecz do audytu po twojej stronie.

Czy to właściwe narzędzie?

Chcesz…Użyj
Wywoływać SpicyAPI z własnego kodu w GoTego SDK
Wywoływać je z Node.js albo TypeScriptuSDK dla TypeScriptu
Wywoływać je z Pythona, PHP albo JavySDK dla Pythona, SDK dla PHP albo SDK dla Javy
Generować z terminala, bez pisania koduCLI
Pozwolić, żeby asystent AI wywoływał SpicyAPI za ciebieSerwer MCP i Agent Skill
Korzystać z modelu czatu albo modelu tekstowegoUznanego klienta Go dla formatów OpenAI, Anthropic albo Gemini – zobacz Tekst i streaming

Instalacja

Go rozwiązuje moduły prosto z ich repozytorium, więc nie ma tu kroku z rejestrem ani na co czekać. To polecenie działa już dziś:

go get github.com/spicyapi-ai/spicy-go

Klucz trzymaj w zmiennej środowiskowej, żeby nigdy nie pojawił się w twoim kodzie ani w pliku historii powłoki:

export SPICY_API_KEY="sk-spicy-..."

Pierwszy wynik

Zapytaj o cenę, zdecyduj, utwórz zadanie, poczekaj, odczytaj pliki. Wycena jest bezpłatna i niczego nie blokuje.

client, err := spicy.New(spicy.Options{}) // odczytuje SPICY_API_KEY ze zmiennej środowiskowej
if err != nil {
    return err
}

request := spicy.CreateTaskInput{
    Model: "MODEL_ID_FROM_CATALOG",
    Input: map[string]any{"prompt": "a lantern in fog"},
}

quote, err := client.Quote(ctx, request)
if err != nil {
    return err
}
log.Printf("this will cost at most %s", quote.MaxCharge)

// Zapisz go obok własnego rekordu zlecenia, zanim wyślesz żądanie: cały sens
// tego klucza polega na tym, żeby przetrwał awarię, która zgubiła odpowiedź.
key, err := spicy.NewIdempotencyKey()
if err != nil {
    return err
}

request.Model = quote.Model
request.QuoteID = quote.QuoteID
request.ExpectedCost = quote.EstimatedCost

task, err := client.CreateTask(ctx, request, key, spicy.CreateTaskOptions{})
if err != nil {
    return err
}

final, err := client.WaitForTerminal(ctx, task.TaskID, spicy.WaitOptions{})
if err != nil {
    return err
}
for _, asset := range final.ReadyAssets() {
    log.Println(asset.URL)
}

MODEL_ID_FROM_CATALOG to symbol zastępczy. Prawdziwy identyfikator bierz z uwierzytelnionego katalogu na żywo — client.ListModels, czyli GET /api/v1/models — a nigdy z pamięci ani ze starej strony: modele są dodawane, wstrzymywane i wycofywane. Input buduj na podstawie inputSchema tego konkretnego modelu, które zwraca ListModels; każdy model przyjmuje inne pola.

Kwoty to dziesiętne łańcuchy znaków w dolarach amerykańskich, nigdy liczby zmiennoprzecinkowe, bo binarne liczby zmiennoprzecinkowe nie potrafią dokładnie zapisać większości kwot dziesiętnych. W tym API nigdzie nie ma kredytów ani punktów.

Stan końcowy to jeszcze nie stan udany: czekanie kończą także failed, canceled i expired. Sprawdź final.State.

Pomiń pierwsze odpytanie

WaitSeconds prosi usługę, żeby trzymała połączenie otwarte aż do końca zadania, co przy szybkim modelu oznacza, że wynik przychodzi razem z potwierdzeniem zgłoszenia.

seconds := 30
task, err := client.CreateTask(ctx, request, key, spicy.CreateTaskOptions{WaitSeconds: &seconds})
if err != nil {
    return err
}

// Task jest nil zawsze wtedy, gdy skończył się czas czekania. To zwykły wynik,
// a nie błąd — generacja nadal trwa, więc od tego miejsca odpytuj.
final := task.Task
if final == nil {
    final, err = client.WaitForTerminal(ctx, task.TaskID, spicy.WaitOptions{})
    if err != nil {
        return err
    }
}
log.Println(final.State, final.Cost)

To optymalizacja, nigdy gwarancja. Kod, który czyta task.Task bez sprawdzenia nil, działa dokładnie do pierwszej generacji wolniejszej niż przyjęty budżet czasu, a wtedy wpada w panikę na produkcji.

Zacznij od pliku z dysku

Generowanie wideo z obrazu, podmiana osoby i edycja obrazu wymagają, żeby twój materiał najpierw trafił na naszą stronę. UploadFile wykonuje wysyłkę w trzech krokach — pozwolenie na wysyłkę, PUT do magazynu, commit — w jednym wywołaniu i zwraca URI spicy://. To właśnie ten URI trafia do Input.

uploaded, err := client.UploadFile(ctx, "/path/to/reference.png", "")
// uploaded.URI -> "spicy://f/fil_..."

Publicznie dostępny adres HTTPS możesz podać w danych wejściowych wprost i wtedy nie musisz niczego wysyłać. Limit dla obrazów to 10 MiB, dla dźwięku i wideo – 90 MiB; zobacz Media.

Saldo, zużycie i historia

Wszystkie trzy dotyczą klucza API, którym wywołujesz: bratnie klucze z tego samego konta ani generacje uruchomione w konsoli się w nich nie mieszczą, a ich brak nie jest usterką.

balance, err := client.GetBalance(ctx)
if err != nil {
    return err
}
log.Printf("%s available, %s held by accepted tasks", balance.Available, balance.Held)

usage, err := client.GetUsage(ctx, spicy.UsageOptions{From: "2026-09-01", To: "2026-09-08"})
if err != nil {
    return err
}
log.Printf("%d calls, %s settled over [%s,%s)", usage.TotalCalls, usage.TotalSpend, usage.From, usage.To)

// EachTask powtarza każdy filtr na każdej stronie i przesuwa wyłącznie kursor.
if err := client.EachTask(ctx, spicy.ListTasksOptions{From: "2026-09-01", To: "2026-09-08"},
    func(task spicy.TaskListItem) bool {
        log.Println(task.TaskID, task.State, task.Cost)
        return true // zwróć false, żeby przerwać wcześniej
    }); err != nil {
    return err
}

Daty to dni kalendarzowe UTC w przedziale półotwartym [from, to), obejmującym najwyżej 92 dni. Przy każdym przeglądaniu, które może przekroczyć północ UTC, ustaw From i To na sztywno. Zostawione puste sprawiają, że serwer przy każdej stronie wylicza własne okno od nowa — to to jutro według UTC — więc przeglądanie zaczęte o 23:59 i kontynuowane o 00:01 zadaje dwa różne pytania i skleja odpowiedzi w jedno. Nic tego nie zgłasza.

GetUsage służy do uzgadniania rachunków, nie do śledzenia postępu. Stoi za nim budżet obowiązujący dla całego konta, wspólny dla wszystkich kluczy, a ten ogranicznik przy problemach domyka się zamiast otwierać — odpytywanie go potrafi odciąć każdy inny klucz od jego własnych raportów. Za pojedynczym zadaniem podążaj przez WaitForTerminal. Rozliczenie może też przyjść z opóźnieniem, więc liczba odczytana dziś nadal może się jutro zmienić.

Błędy

Niepowodzenia wracają jako *spicy.APIError, do którego dotrzesz przez errors.As:

var apiErr *spicy.APIError
if errors.As(err, &apiErr) {
    log.Println(apiErr.Status, apiErr.Code, apiErr.RequestID, apiErr.RetryAfter)
}

Rozgałęziaj logikę po Code, nigdy po komunikacie — komunikaty są tłumaczone, kody nie. Status HTTP 503 dzielą między siebie trzy różne kody aplikacyjne, więc sam status nie wystarczy, żeby zdecydować, co zrobić:

KodCo to znaczyCo zrobić
40003przesłane bajty nie zgadzają się ze swoim pozwoleniem na wysyłkęzacznij od nowa, od świeżego pozwolenia
40004żadne wdrożenie nie obsługuje tej kombinacji parametrówzmień parametr wskazany w komunikacie
40201za niskie saldodoładuj konto
40901cena zmieniła się, zanim powstało zadaniewyceń ponownie, zachowując ten sam klucz idempotentności
503składnik, od którego zależymy, jest chwilowo niedostępnyodczekaj tyle, ile mówi RetryAfter
50301nie ma teraz działającego wdrożenia ani cenyodśwież katalog, nie bombarduj usługi
50302generacja synchroniczna nie powiodła się podczas przetwarzania i została zwróconaponów z nowym kluczem idempotentności

Wszystkie kody wymienia strona Błędy. Kontaktując się ze wsparciem, podaj RequestID.

Dwie rzeczy, które oszczędzą ci pieniędzy

Miej jeden klucz idempotentności na jedno zgłoszenie. Używaj go przy każdym ponownym wysłaniu, także po przekroczeniu czasu. Utracona odpowiedź nie dowodzi, że zadanie nie powstało — nowy klucz zamienia nieznany wynik w drugie płatne zadanie. Dokładnie dlatego CreateTask wymaga klucza. Zobacz Idempotentność.

Za udane zadanie płacisz, nawet jeśli wynik cię rozczaruje. Quote niczego nie blokuje, więc gdy cena ma znaczenie, najpierw wyceń.

Czego ten pakiet nie robi

  • Modeli tekstowych. Mówią formatami OpenAI, Anthropic i Gemini — uznani klienci Go dla tych formatów działają z https://api.spicyapi.ai/v1 od ręki, z tym samym kluczem. Zobacz Tekst i streaming.
  • Aplikacji po stronie klienta. Nigdy nie umieszczaj tego klucza w pliku wykonywalnym, który rozdajesz. Wywołuj ze swojego serwera.
  • Wyboru modelu ani wypełniania jego pól. Pakiet podaje ci katalog i schemat każdego modelu; o tym, co wysłać, decydujesz ty.
  • Anulowania zadania. Przyjęte zadanie wykonuje się do końca. Anulowanie context kończy tylko twoje czekanie.

Kod źródłowy

Moduł jest na licencji MIT i powstaje otwarcie pod adresem github.com/spicyapi-ai/spicy-go. Jego README to najkrótsza kompletna wycieczka po kliencie; ta strona dokłada do tego pojęcia, które go otaczają.

Co dalej

Na tej stronie