Skip to main content

Server Integration

The Speakeasy SDK is the primary mechanism for passing API data to Speakeasy. With the data collected from API requests, Speakeasy is able to power a number of use cases:

  • API Key Management - With Speakeasy’s API key management, your users can create and revoke API keys in your API portal.
  • API Request Viewer - Enable your users to troubleshoot API integration issues without engineering support.
  • API Usage Dashboard - Give your users advanced insight into their API traffic patterns.

SDKs are available for a number of languages and frameworks. They are open-sourced under Apache 2.0.

When installing the SDK you will need a few values to include in the configuration:

  • APIKey: This key identifies your account within the Speakeasy platform. If you need a key, head over to the API Keys tab in the Speakeasy platform and click "New API Key".
  • ApiID: This is an arbitrary ID to help you identify you API within the platform. Use something that is meaningful to your team. Supports any string up to 128 characters, using Alphanumeric characters or the following symbols (. - _ ~). For example: test-api
  • VersionID: Use this field to demarcate the version of the API that you are tracking. Supports any string up to 128 characters, using Alphanumeric characters or the following symbols (. - _ ~). For example: v1.0.0

Initial Install

Full Documentation available on pkg.go.dev

The Speakeasy Go SDK for evaluating API requests/responses. Compatible with any API framework implemented on top of Go's native http library.

Requirements

Supported routers:

  • gorilla/mux
  • go-chi/chi
  • http.DefaultServerMux

We also support custom HTTP frameworks:

  • gin-gonic/gin
  • labstack/echo

Usage

Speakeasy uses Go Modules to manage dependencies.

go get github.com/speakeasy-api/speakeasy-go-sdk

Minimum configuration

  1. Sign up for free on our platform. Create a workspace and generate an API key

  2. Import and configure the Speakeasy SDK as below. Note:

    • APIKey: enter the key you generated above
    • ApiID and VersionID: these are labels that you can specify. Requests from your API will show up in the web application using this ApiID (name) and version label.
    import "github.com/speakeasy-api/speakeasy-go-sdk"

    func main() {
    // Configure the Global SDK
    speakeasy.Configure(speakeasy.Config {
    APIKey: "YOUR API KEY HERE", // retrieve from Speakeasy API dashboard.
    ApiID: "YOUR API ID HERE", // enter a name that you'd like to associate captured requests with.
    // This name will show up in the Speakeasy dashboard. e.g. "PetStore" might be a good ApiID for a Pet Store's API.
    // No spaces allowed.
    VersionID: "YOUR VERSION ID HERE", // enter a version that you would like to associate captured requests with.
    // The combination of ApiID (name) and VersionID will uniquely identify your requests in the Speakeasy Dashboard.
    // e.g. "v1.0.0". You can have multiple versions for the same ApiID (if running multiple versions of your API)
    })

    // Associate the SDK's middleware with your router
    r := mux.NewRouter()
    r.Use(speakeasy.Middleware)
    }
  3. Build and deploy your app.

That's it! Go to your dashboard to view and manage your API Ops.

Visit our docs site to learn more.

Supported Versions

VersionFeature
v1.2.0https://github.com/speakeasy-api/speakeasy-go-sdk/releases/tag/v1.2.0
v1.1.1

https://github.com/speakeasy-api/speakeasy-go-sdk/releases/tag/v1.1.1

https://github.com/speakeasy-api/speakeasy-go-sdk/releases/tag/v1.1.0

v1.0.3
  • Request Capture

Capture CustomerIDs

Capturing CustomerIDs is not required, but is highly recommended. By setting a CustomerID you can associate requests to your customers/users, which powers the filters needed to build a customer-facing API dashboard.

tip

If you are planning to build a developer experience portal, then it's important to pick a CustomerID that is stable, and connected to your identity system. When users login to your portal, Speakeasy will then be able to filter the data to just those relevant to the user.

For example: CustomerID is preferable to api_key because an API key can be rotated and is therefore unstable.

To associate requests with a customer ID, you need to instantiate the Speakeasy middleware in your handler functions and then set the CustomerID field. Below are per language examples of setting a CustomerID in a handler function.

func MyHandler(w http.ResponseWriter, r *http.Request) {
ctrl := speakeasy.MiddlewareController(req)
ctrl.CustomerID("a-customers-id") // This customer ID will be used to associate this instance of a request with your customers/users

// the rest of your handlers code
}

Mask Sensitive Fields

Speakeasy can mask sensitive data in the query string parameters, headers, cookies and request/response bodies captured by the SDK. This is useful for maintaining sensitive data isolation, and retaining control over the data that is captured.

Mask By Endpoint

By not assigning the middleware to their router, you will cause the SDK to not capture any requests to that router. But if you would like to be more selective, you can mask certain sensitive data using our middleware controller allowing you to mask fields as needed in different handlers:

func MyHandler(w http.ResponseWriter, r *http.Request) {
ctrl := speakeasy.MiddlewareController(req)
ctrl.Masking(speakeasy.WithRequestHeaderMask("Authorization")) // Mask the Authorization header in the request

// the rest of your handlers code
}

The Masking function takes a number of different options to mask sensitive data in the request:

  • speakeasy.WithQueryStringMask - WithQueryStringMask will mask the specified query strings with an optional mask string.
  • speakeasy.WithRequestHeaderMask - WithRequestHeaderMask will mask the specified request headers with an optional mask string.
  • speakeasy.WithResponseHeaderMask - WithResponseHeaderMask will mask the specified response headers with an optional mask string.
  • speakeasy.WithRequestCookieMask - WithRequestCookieMask will mask the specified request cookies with an optional mask string.
  • speakeasy.WithResponseCookieMask - WithResponseCookieMask will mask the specified response cookies with an optional mask string.
  • speakeasy.WithRequestFieldMaskString - WithRequestFieldMaskString will mask the specified request body fields with an optional mask. Supports string fields only. Matches using regex.
  • speakeasy.WithRequestFieldMaskNumber - WithRequestFieldMaskNumber will mask the specified request body fields with an optional mask. Supports number fields only. Matches using regex.
  • speakeasy.WithResponseFieldMaskString - WithResponseFieldMaskString will mask the specified response body fields with an optional mask. Supports string fields only. Matches using regex.
  • speakeasy.WithResponseFieldMaskNumber - WithResponseFieldMaskNumber will mask the specified response body fields with an optional mask. Supports number fields only. Matches using regex.

Mask Globally

Masking can also be done more globally on all routes or a selection of routes by taking advantage of middleware. Here is an example:

speakeasy.Configure(speakeasy.Config {
APIKey: "YOUR API KEY HERE", // retrieve from Speakeasy API dashboard.
ApiID: "YOUR API ID HERE", // this is an ID you provide that you would like to associate captured requests with.
VersionID: "YOUR VERSION ID HERE", // this is a Version you provide that you would like to associate captured requests with.
})

r := mux.NewRouter()
r.Use(speakeasy.Middleware)
r.Use(func (next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Mask the Authorization header in the request for all requests served by this middleware
ctrl := speakeasy.MiddlewareController(req)
ctrl.Masking(speakeasy.WithRequestHeaderMask("Authorization"))
})
})

Manage Versioning

The Speakeasy SDK provides both a global and per Api configuration option. If you want to use the SDK to track multiple Apis or Versions from the same service you can configure individual instances of the SDK.

import "github.com/speakeasy-api/speakeasy-go-sdk"

func main() {
r := mux.NewRouter()

// Configure a new instance of the SDK for the store API
storeSDKInstance := speakeasy.New(speakeasy.Config {
APIKey: "YOUR API KEY HERE", // retrieve from Speakeasy API dashboard.
ApiID: "store_api", // this is an ID you provide that you would like to associate captured requests with.
VersionID: "1.0.0", // this is a Version you provide that you would like to associate captured requests with.
})

// Configure a new instance of the SDK for the product API
productSDKInstance := speakeasy.New(speakeasy.Config {
APIKey: "YOUR API KEY HERE", // retrieve from Speakeasy API dashboard.
ApiID: "product_api", // this is an ID you provide that you would like to associate captured requests with.
VersionID: "1.0.0", // this is a Version you provide that you would like to associate captured requests with.
})

// The different instances of the SDK (with differnt IDs or even versions assigned) can be used to associate requests with different APIs and Versions.
s := r.PathPrefix("/store").Subrouter()
r.Use(storeSDKInstance.Middleware)

s := r.PathPrefix("/products").Subrouter()
r.Use(productSDKInstance.Middleware)
}

Provide Path Hints

The Speakeasy SDK out of the box will do its best to match requests to your provided OpenAPI Schema. It does this by extracting the path template used by the Mapping annotation for your controller handlers and attempting to match it to the paths defined in the OpenAPI Schema, for example:

r := mux.NewRouter()
r.Use(sdkInstance.Middleware)
r.HandleFunc("/v1/users/{id}", MyHandler) // The path template "/v1/users/{id}" is captured automatically by the SDK

This isn't always successful or even possible, meaning requests received by Speakeasy will be marked as unmatched, and potentially not associated with your Api, Version or ApiEndpoints in the Speakeasy Dashboard. This normally happens if your path contains regex patterns or is a catch all path and your handler parses the routes manually. To help the SDK in these situations you can provide path hints per request handler that match the paths in your OpenAPI Schema:

func MyHandler(w http.ResponseWriter, r *http.Request) {
// Provide a path hint for the request using the OpenAPI Path Templating format: https://swagger.io/specification/#path-templating-matching
ctrl := speakeasy.MiddlewareController(req)
ctrl.PathHint("/v1/users/{id}")

// the rest of your handlers code
}
note

Wildcard path matching in Echo & Chi will end up with a OpenAPI path paramater called {wildcard} which will only match single level values represented by the wildcard. This is a restriction of the OpenAPI spec (Detail Here). For example:

chi template: /user/{id}/path/* => openapi template: /user/{id}/path/{wildcard}

And in the above example a path like /user/1/path/some/sub/path won't match but /user/1/path/somesubpathstring will, as / characters are not matched in path parameters by the OpenAPI spec.

Generate Embed Tokens

The Speakeasy SDK can generate access tokens for Embedded Components.

Below are examples for how to generate access tokens:

import "github.com/speakeasy-api/speakeasy-schemas/grpc/go/registry/embedaccesstoken"

ctx := context.Background()

// If the SDK is configured as a global instance,
// an access token can be generated using the
// `GenerateAccessToken` function on the speakeasy package.
accessToken, err := speakeasy.GetEmbedAccessToken(ctx, &embedaccesstoken.EmbedAccessTokenRequest{
Filters: []*embedaccesstoken.EmbedAccessTokenRequest_Filter{
{
Key: "customer_id",
Operator: "=",
Value: "a-customer-id",
},
},
})

// If you have followed the `Advanced Configuration` section above,
// you can also generate an access token using the
// `GenerateAccessToken` function on the sdk instance.
accessToken, err := storeSDKInstance.GetEmbedAccessToken(ctx, &embedaccesstoken.EmbedAccessTokenRequest{
Filters: []*embedaccesstoken.EmbedAccessTokenRequest_Filter{
{
Key: "customer_id",
Operator: "=",
Value: "a-customer-id",
},
},
})

// Or finally if you have a handler that you would like to generate an access token from,
// you can get the SDK instance for that handler from the middleware controller
// and use the `GetEmbedAccessToken` function it.
func MyHandler(w http.ResponseWriter, r *http.Request) {
ctrl := speakeasy.MiddlewareController(req)
accessToken, err := ctrl.GetSDKInstance().GetEmbedAccessToken(ctx, &embedaccesstoken.EmbedAccessTokenRequest{
Filters: []*embedaccesstoken.EmbedAccessTokenRequest_Filter{
{
Key: "customer_id",
Operator: "=",
Value: "a-customer-id",
},
},
})

// the rest of your handlers code
}