--- title: Go | FLORA API description: Install the FLORA Go SDK and run your first Technique. --- The `flora-go` SDK is a context-aware, type-safe Go client for the [FLORA REST API](/api/index.md). It requires Go 1.21+. ## Install Terminal window ``` go get -u github.com/florafauna-ai/flora-go ``` ## Configure Set your API key in the environment: Terminal window ``` export FLORA_API_KEY="sk_live_XXXX" ``` Instantiate the client: ``` package main import ( "os" "github.com/florafauna-ai/flora-go" "github.com/florafauna-ai/flora-go/option" ) func main() { client := flora.NewClient( option.WithAPIKey(os.Getenv("FLORA_API_KEY")), ) _ = client } ``` ## First run, end to end ``` package main import ( "context" "fmt" "log" "os" "time" "github.com/florafauna-ai/flora-go" "github.com/florafauna-ai/flora-go/option" "github.com/florafauna-ai/flora-go/param" ) func main() { ctx := context.Background() client := flora.NewClient(option.WithAPIKey(os.Getenv("FLORA_API_KEY"))) // 1. List Techniques page, err := client.Techniques.List(ctx, flora.TechniqueListParams{}) if err != nil { log.Fatal(err) } for _, t := range page.Techniques { fmt.Printf("%s — %s\n", t.Slug, t.Name) } // 2. Retrieve a Technique technique, err := client.Techniques.Get(ctx, "thumbnail-v3") if err != nil { log.Fatal(err) } fmt.Printf("inputs: %+v\n", technique.Inputs) // 3. Create a run run, err := client.Techniques.Runs.New(ctx, "thumbnail-v3", flora.TechniqueRunNewParams{ Inputs: []flora.TechniqueRunNewParamsInput{ {ID: "prompt", Type: "text", Value: "Smart living, simple — warm minimalism"}, }, Mode: flora.TechniqueRunNewParamsModeAsync, }) if err != nil { log.Fatal(err) } // 4. Poll runID := run.RunID for { result, err := client.Techniques.Runs.Get(ctx, runID, flora.TechniqueRunGetParams{ TechniqueID: "thumbnail-v3", }) if err != nil { log.Fatal(err) } if result.Status == "completed" { for _, output := range result.Outputs { fmt.Println(output.URL) } return } if result.Status == "failed" { log.Fatalf("run failed: %s", result.ErrorMessage) } time.Sleep(2 * time.Second) } } ``` ## Idempotency Pass `IdempotencyKey` on any mutation that you might retry: ``` run, err := client.Techniques.Runs.New(ctx, "thumbnail-v3", flora.TechniqueRunNewParams{ Inputs: []flora.TechniqueRunNewParamsInput{...}, Mode: flora.TechniqueRunNewParamsModeAsync, IdempotencyKey: param.Field("q3-thumb-" + marketCode), }) ``` Same key + same body = same run. See [Idempotency](/platform/idempotency/index.md). ## Errors Errors are returned as `*flora.Error` with structured fields: ``` import "errors" run, err := client.Techniques.Runs.New(ctx, "thumbnail-v3", params) if err != nil { var apiErr *flora.Error if errors.As(err, &apiErr) { log.Printf("status=%d code=%s message=%s request_id=%s", apiErr.StatusCode, apiErr.Code, apiErr.Message, apiErr.RequestID) } return err } ``` See [Errors](/platform/errors/index.md) for every code and recovery guidance. ## Concurrency The client is safe for concurrent use. For batch jobs, share one client across goroutines and bound parallelism with a semaphore. ## What’s next - **[Authentication](/platform/authentication/index.md)** — keys, rotation, security. - **[Recipes](/recipes/generate-a-grid/index.md)** — common end-to-end patterns in code. - **[API Reference](/api/go/index.md)** — every method, struct, and response type.