/unkey-go

Go SDK for Unkey

Primary LanguageGoApache License 2.0Apache-2.0

unkey-go

unkey-go is a Go client for unkey - a simple, secure, and open-source API key management service.

Get started with unkey & check the official docs for more information.

Installation

To use the unkey-go SDK in your Go project, you can simply import it using Go modules:

go get github.com/WilfredAlmeida/unkey-go

Usage

The APIs are based on the offcial API Documentation. The parameters are same, their initial letter is capitalised.

Examples


Verify Key

package main

import (
	"fmt"

	unkey "github.com/WilfredAlmeida/unkey-go/features"
)

func main() {
	apiKey := "key_3ZZ7faUrkfv1YAhffAcnKW74"

	response, err := unkey.KeyVerify(apiKey)
	if err != nil {
		fmt.Println("Error:", err)
		return
	}

	if response.Valid {
		fmt.Println("Key is valid")
	} else {
		fmt.Println("Key is invalid")
	}
}

Note: See the structs reference for more information on the response body for KeyVerify

Create Key

package main

import (
	"fmt"

	unkey "github.com/WilfredAlmeida/unkey-go/features"
)

func main() {
	// Prepare the request body
	request := unkey.KeyCreateRequest{
		APIId:      "your-api-id",
		Prefix:     "your-prefix",
		ByteLength: 16,
		OwnerId:    "your-owner-id",
		Meta:       map[string]string{"key": "value"},
		Expires:    0,
		Remaining:  0,
		RateLimit: unkey.KeyCreateRateLimit{
			Type:           "fast",
			Limit:          100,
			RefillRate:     10,
			RefillInterval: 60,
		},
	}

	// Provide the authentication token
	authToken := "your-auth-token"

	// Call the KeyCreate function
	response, err := unkey.KeyCreate(request, authToken)
	if err != nil {
		fmt.Println("Error:", err)
		return
	}

	// Process the response
	fmt.Println("Key:", response.Key)
	fmt.Println("Key ID:", response.KeyId)
}

Note: Pass the optional & required parameters as per the official API docs. See the structs reference for more information on the request body for KeyCreate

Revoke Key

package main

import (
	"fmt"

	unkey "github.com/WilfredAlmeida/unkey-go/features"
)

func main() {
	// Specify the key ID to revoke
	keyID := "your-key-id"

	// Provide the authentication token
	authToken := "your-auth-token"

	// Call the RevokeKey function
	success, err := unkey.RevokeKey(keyID, authToken)
	if err != nil {
		fmt.Println("Error:", err)
		return
	}

	// Process the response
	if success {
		fmt.Println("Key revoked successfully")
	} else {
		fmt.Println("Failed to revoke key")
	}
}

Note: The API returns {} as a success response for revkoking key. For user convenience, unkey-go returns boolean

** Update Key**

package main

import (
	"fmt"

	unkey "github.com/WilfredAlmeida/unkey-go/features"
)

func main() {

	// The API for update has optional params. To determine which params to update, a custome type is made which mimics the behaviour of `undefined`/`null`.
	// To update, define a object in the following manner & set the value for the fields you want to update following on.

	keyUpdateReq := unkey.KeyUpdateRequest{
		KeyId: "someKey",
		Name: unkey.NullableField[string]{Defined: false, Value: new(string)},
		OwnerId: unkey.NullableField[string]{Defined: false, Value: nil},
		Meta: unkey.NullableField[map[string]interface{}]{Defined: false, Value: new(map[string]interface{})},
		Expires: unkey.NullableField[int64]{Defined: false, Value: new(int64)},
		Ratelimit: unkey.NullableField[unkey.RateLimitSchema]{Defined: false, Value: nil},
		Remaining: unkey.NullableField[int64]{Defined: false, Value: new(int64)},
	}

	// Set the value for Name
	keyUpdateReq.Name.Defined = true
	*keyUpdateReq.Name.Value = "John Doe"

	// Set the value for Meta
	keyUpdateReq.Meta.Defined = true
	metaData := map[string]interface{}{
		"field1": "value1",
		"field2": 42,
	}
	*keyUpdateReq.Meta.Value = metaData

	response, err := features.KeyUpdate("someKey",keyUpdateReq, os.Getenv("AUTH_TOKEN"))
	if err != nil {
		fmt.Println("Error:", err)
		return
	}

	fmt.Printf("Response: %+v\n", response)

}

Get API Information

package main

import (
	"fmt"

	unkey "github.com/WilfredAlmeida/unkey-go/features"
)

func main() {
	response, err := features.APIGet("API_ID","AUTH_TOKEN")
	if err != nil {
		fmt.Println("Error:", err)
		return
	}

	fmt.Printf("Response: %+v\n", response)
}

Get List Keys

package main

import (
	"fmt"

	unkey "github.com/WilfredAlmeida/unkey-go/features"
)

func main() {
	response, err := features.APIListKeys("API_ID","AUTH_TOKEN")
	if err != nil {
		fmt.Println("Error:", err)
		return
	}

	fmt.Printf("Response: %+v\n", response)
}

Structs Reference

The structs used in code for you to get a better idea of the request & response bodies.

KeyVerify

type ratelimitResponse struct {
	Limit     int64 `json:"limit"`
	Remaining int64 `json:"remaining"`
	Reset     int64 `json:"reset"`
}

type KeyVerifyResponse struct {
    Valid       bool                   `json:"valid"`
    OwnerId     string                 `json:"ownerId,omitempty"`
    Meta        map[string]interface{} `json:"meta,omitempty"`
    Expires     int64                  `json:"expires,omitempty"`
    Remaining   int64                  `json:"remaining,omitempty"`
    Ratelimit   *ratelimitResponse     `json:"ratelimit,omitempty"`
    Code        string                 `json:"code,omitempty"`
    Enabled     bool                   `json:"enabled"`
    Environment string                 `json:"environment"`
    KeyId       string                 `json:"keyId"`
    Name        string                 `json:"name"`
    Permissions []string               `json:"permissions"`
}

KeyCreate

type KeyCreateRequest struct {
	APIId      string             `json:"apiId"`
	Prefix     string             `json:"prefix"`
	ByteLength int                `json:"byteLength"`
	OwnerId    string             `json:"ownerId"`
	Meta       Meta               `json:"meta"`
	Expires    int64              `json:"expires"`
	Remaining  int                `json:"remaining"`
	RateLimit  KeyCreateRateLimit `json:"ratelimit"`
}

type Meta map[string]string

type KeyCreateRateLimit struct {
	Type           string `json:"type"`
	Limit          int    `json:"limit"`
	RefillRate     int    `json:"refillRate"`
	RefillInterval int    `json:"refillInterval"`
}

type KeyCreateResponse struct {
	Key   string `json:"key"`
	KeyId string `json:"keyId"`
}

KeyUpdate

type NullableField[T any] struct {
	Defined bool
	Value   *T
}

func (m *NullableField[T]) UnmarshalJSON(data []byte) error {
	m.Defined = true
	return json.Unmarshal(data, &m.Value)
}

type RateLimitSchema struct {
	Type           string `json:"type" validate:"required"`
	Limit          int64  `json:"limit" validate:"required"`
	RefillRate     int64  `json:"refillRate" validate:"required"`
	RefillInterval int64  `json:"refillInterval" validate:"required"`
}

type KeyUpdateRequest struct {
	KeyId     string                         `json:"keyId" validate:"required"`
	Name      NullableField[string]          `json:"name"`
	OwnerId   NullableField[string]          `json:"ownerId"`
	Meta      NullableField[map[string]any]  `json:"meta"`
	Expires   NullableField[int64]           `json:"expires"`
	Ratelimit NullableField[RateLimitSchema] `json:"ratelimit"`
	Remaining NullableField[int64]           `json:"remaining"`
}

APIGet

type APIGetResponse struct {
	ID          string `json:"id"`
	Name        string `json:"name"`
	WorkspaceID string `json:"workspaceId"`
}

APIListKeys

type Key struct {
	ID          string            `json:"id,omitempty"`
	APIID       string            `json:"apiId,omitempty"`
	WorkspaceID string            `json:"workspaceId,omitempty"`
	Start       string            `json:"start,omitempty"`
	CreatedAt   int64             `json:"createdAt,omitempty"`
	Expires     *int64            `json:"expires,omitempty"`
	Ratelimit   ratelimitResponse `json:"ratelimit,omitempty"`
}

type APIListKeysResponse struct {
	Keys  []Key `json:"keys,omitempty"`
	Total int   `json:"total,omitempty"`
}

Note: ratelimitResponse is defined in KeyVerify struct reference


Contributing

Refer the CONTRIBUTING.md file for more information.