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

# Integrar con Go

> Agrega cobros y pagos a tu aplicación de Go usando net/http.

Instala la Commet Skill para que tu agente integre el SDK actual y valide su trabajo contra el contrato vivo de la API.

```bash theme={null}
npx skills add commet-labs/skills --skill commet
```

<Steps>
  <Step title="Instalar">
    ```bash theme={null}
    go get github.com/commet-labs/commet-go/v9
    ```
  </Step>

  <Step title="Configurar">
    ```bash title=".env" theme={null}
    COMMET_API_KEY=ck_sandbox_xxx
    COMMET_WEBHOOK_SECRET=whsec_xxx
    ```

    ```go title="billing/client.go" theme={null}
    package billing

    import (
    	"log"
    	"os"

    	commet "github.com/commet-labs/commet-go/v9"
    )

    var Client *commet.Client

    func Init() {
    	var err error
    	Client, err = commet.New(os.Getenv("COMMET_API_KEY"))
    	if err != nil {
    		log.Fatal(err)
    	}
    }
    ```

    El cliente no tiene opción de environment: sandbox o live lo decide la organización a la que pertenece la API key.
  </Step>

  <Step title="Suscribir">
    ```go title="billing/handlers.go" theme={null}
    package billing

    import (
    	"encoding/json"
    	"net/http"

    	commet "github.com/commet-labs/commet-go/v9"
    )

    type subscribeRequest struct {
    	Email      string `json:"email"`
    	CustomerID string `json:"customer_id"`
    }

    func Subscribe(w http.ResponseWriter, r *http.Request) {
    	var req subscribeRequest
    	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
    		http.Error(w, err.Error(), http.StatusBadRequest)
    		return
    	}

    	_, err := Client.Customers.Create(r.Context(), &commet.CreateCustomerParams{
    		Email: req.Email,
    		ID:    &req.CustomerID,
    	})
    	if err != nil {
    		http.Error(w, err.Error(), http.StatusInternalServerError)
    		return
    	}

    	planCode := "pro"
    	subscription, err := Client.Subscriptions.Create(r.Context(), &commet.CreateSubscriptionParams{
    		CustomerID: req.CustomerID,
    		PlanCode:   &planCode,
    	})
    	if err != nil {
    		http.Error(w, err.Error(), http.StatusInternalServerError)
    		return
    	}

    	checkoutURL := ""
    	if subscription.CheckoutURL != nil {
    		checkoutURL = *subscription.CheckoutURL
    	}

    	w.Header().Set("Content-Type", "application/json")
    	json.NewEncoder(w).Encode(map[string]any{"checkout_url": checkoutURL})
    }
    ```
  </Step>

  <Step title="Verificar acceso">
    ```go title="billing/handlers.go" theme={null}
    func GetSubscription(w http.ResponseWriter, r *http.Request) {
    	customerID := r.PathValue("customerID")

    	sub, err := Client.Subscriptions.GetActive(r.Context(), &commet.GetActiveSubscriptionParams{
    		CustomerID: customerID,
    	})
    	if err != nil {
    		http.Error(w, err.Error(), http.StatusInternalServerError)
    		return
    	}

    	if sub == nil {
    		http.Error(w, "No active subscription", http.StatusNotFound)
    		return
    	}

    	w.Header().Set("Content-Type", "application/json")
    	json.NewEncoder(w).Encode(map[string]any{"status": sub.Status})
    }

    func CheckFeature(w http.ResponseWriter, r *http.Request) {
    	feature := r.PathValue("feature")
    	customerID := r.PathValue("customerID")

    	result, err := Client.FeatureAccess.Get(r.Context(), feature, &commet.GetFeatureAccessParams{
    		CustomerID: customerID,
    	})
    	if err != nil {
    		http.Error(w, err.Error(), http.StatusInternalServerError)
    		return
    	}

    	w.Header().Set("Content-Type", "application/json")
    	json.NewEncoder(w).Encode(map[string]any{"allowed": result.Allowed})
    }
    ```
  </Step>

  <Step title="Trackear uso">
    ```go title="billing/handlers.go" theme={null}
    func float64Ptr(value float64) *float64 { return &value }

    type usageRequest struct {
    	CustomerID string `json:"customer_id"`
    }

    func TrackUsage(w http.ResponseWriter, r *http.Request) {
    	var req usageRequest
    	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
    		http.Error(w, err.Error(), http.StatusBadRequest)
    		return
    	}

    	_, err := Client.Usage.Track(r.Context(), &commet.TrackUsageParams{
    		CustomerID: req.CustomerID,
    		FeatureCode: "api_calls",
    		Value:       float64Ptr(1),
    	})
    	if err != nil {
    		http.Error(w, err.Error(), http.StatusInternalServerError)
    		return
    	}

    	w.Header().Set("Content-Type", "application/json")
    	json.NewEncoder(w).Encode(map[string]any{"tracked": true})
    }
    ```

    El uso se agrega y se cobra al final del período.
  </Step>

  <Step title="Portal del Cliente">
    ```go title="billing/handlers.go" theme={null}
    func Portal(w http.ResponseWriter, r *http.Request) {
    	customerID := "user_123"
    	result, err := Client.Portal.GetURL(r.Context(), &commet.RequestPortalAccessParams{
    		CustomerID: &customerID,
    	})
    	if err != nil {
    		http.Error(w, err.Error(), http.StatusInternalServerError)
    		return
    	}

    	http.Redirect(w, r, result.PortalURL, http.StatusTemporaryRedirect)
    }
    ```
  </Step>

  <Step title="Webhooks">
    ```go title="billing/webhooks.go" theme={null}
    package billing

    import (
    	"io"
    	"net/http"
    	"os"

    	commet "github.com/commet-labs/commet-go/v9"
    )

    func HandleWebhook(w http.ResponseWriter, r *http.Request) {
    	rawBody, err := io.ReadAll(r.Body)
    	if err != nil {
    		http.Error(w, "Failed to read body", http.StatusBadRequest)
    		return
    	}

    	webhooks := &commet.WebhooksResource{}
    	payload, err := webhooks.VerifyAndParse(
    		string(rawBody),
    		r.Header.Get("x-commet-signature"),
    		os.Getenv("COMMET_WEBHOOK_SECRET"),
    	)
    	if err != nil {
    		http.Error(w, "Invalid signature", http.StatusUnauthorized)
    		return
    	}

    	switch payload["event"] {
    	case "subscription.activated":
    		// manejar activación
    	}

    	w.Header().Set("Content-Type", "application/json")
    	w.Write([]byte(`{"ok":true}`))
    }
    ```
  </Step>

  <Step title="Iniciar el servidor">
    ```go title="main.go" theme={null}
    package main

    import (

    	"log"
    	"net/http"

    	"myapp/billing"
    )

    func main() {
    	billing.Init()
    	defer billing.Client.Close()

    	mux := http.NewServeMux()

    	mux.HandleFunc("POST /billing/subscribe", billing.Subscribe)
    	mux.HandleFunc("GET /billing/subscription/{customerID}", billing.GetSubscription)
    	mux.HandleFunc("GET /billing/features/{feature}/{customerID}", billing.CheckFeature)
    	mux.HandleFunc("POST /billing/usage", billing.TrackUsage)
    	mux.HandleFunc("GET /billing/portal", billing.Portal)
    	mux.HandleFunc("POST /webhooks/commet", billing.HandleWebhook)

    	log.Println("Listening on :3000")
    	log.Fatal(http.ListenAndServe(":3000", mux))
    }
    ```
  </Step>
</Steps>

## Relacionado

* [Suscripciones](/docs/es/manage-subscriptions)
* [Trackear Uso](/docs/es/track-usage)
* [Portal del Cliente](/docs/es/customer-portal)
* [Referencia del SDK](/docs/es/sdk-reference)


## Related topics

- [Integrar con Encore](/docs/es/integrate-with-encore.md)
- [Integrar con Flask](/docs/es/integrate-with-flask.md)
- [Integrar con Java](/docs/es/integrate-with-java.md)
- [Integrar con Django](/docs/es/integrate-with-django.md)
- [Integrar con Laravel](/docs/es/integrate-with-laravel.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.