npm package: @speakeasy-api/react-embeds
Description: ![180100416-b66263e6-1607-4465-b45d-0e298a67c397](https://user-images.githubusercontent.com/68016351/181640742-31ab234a-3b39-432e-b899-21037596b360.png)
Latest version: 1.3.1

# Speakeasy React Components

![180100416-b66263e6-1607-4465-b45d-0e298a67c397](https://user-images.githubusercontent.com/68016351/181640742-31ab234a-3b39-432e-b899-21037596b360.png)

Embed Speakeasy's React components in your API developer portal to augment your static API documentation with a magical developer experience. With our components, onboarding to and ongoing usage of your API becomes self-service for your users.  

All the components we offer are composable, meaning you can use them in isolation, or any combination.  Our available components are:

* [**API Overview Cards**]() - Give your users the key API metrics they want.  API Cards provide your users with the most important API stats: number of requests, number of errors, error rate, and change over time. Each top-level API is represented with a card, which summarizes usage across all the API's individual endpoints filtered for a specific customer.
* [**API Request Viewer**]() - Enable your users to troubleshoot API integration issues without engineering support.  The API Request Viewer gives user the ability to filter API traffic, make edits to headers & request objects, and replay specific requests. All without having to ever leave your dev portal.
* [**API Usage Dashboard**]() - Give your users advanced insight into their API traffic patterns filterable by api, api endpoint, and status. The Usage dashboard gives them rich visualizations to help them better understand how they use your API. Pair with the API Cards to provide both summarized and granular views of API traffic.

## Installing Speakeasy Components

```bash
npm install @speakeasy-api/react-embeds
 #or
yarn add @speakeasy-api/react-embeds
 ```

## Using Speakeasy Components

To embed Speakeasy components in your application, the first step is making sure they are properly authenticated and filtered for the logged in customer. After which you will be able to easily add the component into your react app

### Authenticating and Filtering your Components

To get Speakeasy components working correctly, you will need to generate an `accessToken` filtered to the correct subset of data. There are two ways to generate an `accessToken`:
1. **[Recommended]** Declare an embed filter in the instantiation of the Speakeasy SDK in your API handlers.
2. Make an API request from your React app, passing in the filter as an API parameter. **note:** Access tokens retrieved through the `/v1/workspace/embed-access-token` endpoint are `read-only`.

#### **Recommended Option: Create Filtered Access Token in SDK**
Creating a filtered `accessToken` in the SDK is a language-specific activity. For the full range of supported languages, see our documentation.  This instruction set will be in Go.

#### **Step one: set up the Speakeasy SDK**
​
Add the sdk to your api project according to the documentation.
​
```go
// routes.go
​
func addPublicRoutes(r *mux.Router) {
	r := mux.NewRouter()
​
	speakeasySDK := speakeasy.New(speakeasy.Config {
		APIKey:		"YOUR API KEY HERE",
		ApiID:		"main_api",
		VersionID:	"1.0.0",
	}
    r.Use(speakeasySDK.Middleware)
​
    // Your paths
}
```
​
#### **Step Two: add auth endpoint**

Embed tokens can provide access to only a subset of your data, if desired. This is useful for allowing each of your customers to use your embedded component to view only their own data or for restricting which apis, versions, or endpoints you'd like to expose in your embedded component.
​
```go
// controller.go
​
func EmbedAuthHandler(w http.ResponseWriter, r *http.Request) {
	ctrl := speakeasy.MiddlewareController(req)
​
    // Use your existing authentication provider or logic for the embed access token.
    customerID := auth.GetCustomerID(req)
​
    accessToken, err := ctrl.GetSDKInstance().GetEmbedAccessToken(ctx, &embedaccesstoken.EmbedAccessTokenRequest{
		Filters: []*embedaccesstoken.EmbedAccessTokenRequest_Filter{
			{
				Key:   "customer_id",
				Operator: "=",
				Value: customerID,
			},
		},
	})
​
    w.WriteHeader(http.StatusOK)
	if err := json.NewEncoder(w).Encode(EmbedResponse{AccessToken: accessToken}); err != nil {
		// handle error
	}
}
​
// models.go
​
type EmbedResponse struct {
	AccessToken string `json:"access_token"`
}
​
// routes.go
​
func addPublicRoutes(r *mux.Router) {
	r := mux.NewRouter()
​
	speakeasySDK := speakeasy.New(speakeasy.Config {
		APIKey:		"YOUR API KEY HERE",
		ApiID:		"main_api",
		VersionID:	"1.0.0",
	}
    r.Use(speakeasySDK.Middleware)
​
​
	r.Path("v1/auth/embed-token").Methods(http.MethodGet).HandlerFunc(EmbedAuthHandler)
​
    // Your other paths
}
```
​
#### **Step Three: Add the embed to your react application**

```typescript
export const DataView = () => {
    const [embedToken, setEmbedToken] = useState(undefined);
​
    // This function will call the handler that you defined in step two.
    const getEmbedToken = useCallback(async () => {
        const accessTokenResponse = await axios.get("https://my-api.dev/v1/auth/embed-token);
        return accessTokenResponse.data.access_token;
    }, []);
​
    // Set the initial token
    useEffect(() => {
        getEmbedToken.then(token => setEmbedToken(token));
    }, [])
​
    return (
        <div>
            <h1>View your data</h1>
            <SpeakeasyRequestsComponent
                accessToken={embedToken}
                onRefetchAccessToken={getEmbedToken}
            />
        </div>
    )
}
​
```

#### **Alternate Option: Create a Filtered Access Token in React**

#### **Step One: Create a filter object**

Set the `accessToken` in your react code by configuring a SpeakeasyFilter object: 

```typescript
type SpeakeasyFilter = {
    // Currently supported filter keys.
    key: 'customer_id' | 'created_at';
    operator: '=' | '<' | '>';
    value: string;
}
```

**`customer_id` should almost always be set in your filter to restrict data to a single customer, lest you unintentionally share another customer's data.**

The filters you configure are then serialized as json into the `filters` query parameter in the API request you will make.

```typescript
const filters = useMemo(() => {
      const customerId = "";  // your customer id.
      return {
        filters: [{
          key: "customer_id",
          operator: "=",
          value: customerId
        }]
      };
    }), [];
```
#### **Step 2: Pass the filter as a parameter into the API request**

```typescript
return (await axios.get("https://app.speakeasyapi.dev/v1/workspace/embed-access-token", {
        headers: {
          "x-api-key": "" // your api key
        }, 
        params: { 
          filters 
        }
      })).data.access_token;
    }, []);
```

#### **Step 3: Set up `accessToken` refresh**

Nest the GET request from step 2 in `onRefetchAccessToken` a callback function that triggers when the 'accessToken' expires
```typescript
const onRefetchAccessToken = useCallback(async () => {
      return (await axios.get("https://app.speakeasyapi.dev/v1/workspace/embed-access-token", {
        headers: {
          "x-api-key": "" // your api key
        }, 
        params: { 
          filters 
        }
      })).data.access_token;
    }, []);

    useEffect(() => {
        getAccessToken()
            .then(access_token => setAccessToken(access_token))
    }, []);
```

Put it all together for a full example of constructing a filters object and making an API request:

```typescript
const App () => { 
    const [accessToken, setAccessToken] = useState("");

    const filters = useMemo(() => {
      const customerId = "";  // your customer id.
      return {
        filters: [{
          key: "customer_id",
          operator: "=",
          value: customerId
        }]
      };
    }), [];

    const onRefetchAccessToken = useCallback(async () => {
      return (await axios.get("https://app.speakeasyapi.dev/v1/workspace/embed-access-token", {
        headers: {
          "x-api-key": "" // your api key
        }, 
        params: { 
          filters 
        }
      })).data.access_token;
    }, []);

    useEffect(() => {
        getAccessToken()
            .then(access_token => setAccessToken(access_token))
    }, []);

    // return
}
```

#### **Step 4: Add Components to Your App**

After a filtered `accessToken` has been created, adding the react components to your app should be easy.  Speakeasy components can be added directly into your react pages. The authentication props are passed directly into the embedded component. See the example below:

```typescript
const SomeReactComponent = (props) => {

  // logic

  return (
    <>
      <YourComponent />
        <SpeakeasyRequestsComponent 
          accessToken={myApiToken}
          onRefetchAccessToken={myApiTokenRefreshFunc} 
        />
    </>
      <YourOtherComponent />
  )

```

If you have multiple components that are using the same access token, a `SpeakeasyConfigure` component can simplify the integration

```typescript
const App = () => {

    // authentication

    return (
        <>
          <SpeakeasyConfigure
            accessToken={myApiToken}
            onRefetchAccessToken={amyApiTokenRefresh} 
          >
            <SpeakeasyApiComponent />
            <SpeakeasyRequestsComponent />
          </SpeakeasyConfigure>
        <>
    );
}
```