> ## Documentation Index
> Fetch the complete documentation index at: https://docs.shappire.tools/llms.txt
> Use this file to discover all available pages before exploring further.

# Exemplos em Go

> Cliente HTTP com net/http e tratamento de erros

## Estrutura do cliente

```go theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
package shappire

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"os"
	"time"
)

const BaseURL = "https://api.shappire.tools/v1"

type Client struct {
	apiKey string
	http   *http.Client
}

func NewClient() *Client {
	return &Client{
		apiKey: os.Getenv("SHAPPIRE_API_KEY"),
		http:   &http.Client{Timeout: 30 * time.Second},
	}
}

type apiError struct {
	Error struct {
		Code    string `json:"code"`
		Message string `json:"message"`
	} `json:"error"`
}

func (c *Client) do(method, path string, payload interface{}) (map[string]interface{}, error) {
	var body io.Reader
	if payload != nil {
		b, _ := json.Marshal(payload)
		body = bytes.NewReader(b)
	}

	req, err := http.NewRequest(method, BaseURL+path, body)
	if err != nil {
		return nil, err
	}
	req.Header.Set("X-API-Key", c.apiKey)
	req.Header.Set("Content-Type", "application/json")

	resp, err := c.http.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		var apiErr apiError
		json.NewDecoder(resp.Body).Decode(&apiErr)
		return nil, fmt.Errorf("%s: %s", apiErr.Error.Code, apiErr.Error.Message)
	}

	var out struct {
		Data map[string]interface{} `json:"data"`
	}
	if err := json.NewDecoder(resp.Body).Decode(&out); err != nil {
		return nil, err
	}
	return out.Data, nil
}
```

## Métodos principais

```go theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
func (c *Client) Resolve(url string) (map[string]interface{}, error) {
	return c.do(http.MethodPost, "/media/resolve", map[string]string{"url": url})
}

func (c *Client) Enqueue(mediaID, format string) (string, error) {
	data, err := c.do(http.MethodPost, "/media/download", map[string]string{
		"media_id": mediaID,
		"format":   format,
	})
	if err != nil {
		return "", err
	}
	return data["job_id"].(string), nil
}

func (c *Client) WaitJob(jobID string) (map[string]interface{}, error) {
	for {
		data, err := c.do(http.MethodGet, "/jobs/"+jobID, nil)
		if err != nil {
			return nil, err
		}
		switch data["status"] {
		case "completed":
			return data, nil
		case "failed":
			return nil, fmt.Errorf("job failed")
		}
		time.Sleep(3 * time.Second)
	}
}
```

## Uso

```go theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
func main() {
	client := shappire.NewClient()
	media, err := client.Resolve("https://www.tiktok.com/@user/video/7123456789012345678")
	if err != nil {
		log.Fatal(err)
	}
	jobID, err := client.Enqueue(media["id"].(string), "video_best")
	job, err := client.WaitJob(jobID)
	fmt.Println(job["result"])
}
```
