API Builder Application Integration

Amplify Integration: how to modify API service description on discovery

In this blog post we’ll describe the steps required to modify an API Service description on discovery, using Amplify Webhooks and platform APIs using API Builder.

When APIs are discovered by the Amplify Central discovery agents, they appear in the Catalog -> Service Registry:

API Providers can view details about the discovered API by clicking on the API Service:

What if you want to display more information about the discovered API on this page? For example, what if you want to display information from the API’s OpenAPI Specification (OAS), such as the API designer’s contact info, on this page?

Amplify Integration Webhooks and Platform APIs can be used to modify the API Service description upon discovery. We covered this idea for a different use case in a prior blog post.

Let’s look at the steps required to modify an API Service description on discovery using Amplify Webhooks and platform APIs using API Builder. We’ll extract the API designers contact name and email address and prefix it to the existing description as follows:

The steps are as follows:

  • Create an Amplify Integration to make a webhook call to your application when an API Service Revision is created
  • Respond to the webhook and parse the payload for the OAS document
  • Base64 Decode the OAS Document and check if it’s OAS3
  • If the API has an OAS3 Document then:
    • Extract the contact details
    • Make an Amplify API call to GET the API Service
    • Modify the description field
    • Make an Amplify API call to PUT the API Service with it’s revised description
    • If not, exit (since the OAS2 spec does not contain contact info)

The API Builder project can be downloaded from Github.

A Docker Container can be downloaded from Docker Hub.

It’s worth noting that you could use any application or integration framework besides API Builder to do this as long as it can expose a webhook URL and make API calls.

Let’s get started!

Amplify Integration for APIServiceRevision

We’ll trigger our webhook on APIServiceRevision creation events and not APIService creation events since the APIServiceRevision contains the OAS document in the webhook payload (and we don’t know if the API Service Revision is created when responding to the APIService event).

A sample YAML file for this is shown below. You need to edit the URL (and any required headers) for your webhook handler application.

api_service_revision_created_integration.yaml

name: api-service-revision-created-integration
kind: Integration
apiVersion: v1alpha1
title: API Service Revision Created Integration
tags:
- cloud
spec:
    description: This is an Integration for when an API Service Revision is created
---
name: api-service-revision-created-integration-wh
kind: Webhook
apiVersion: v1alpha1
title: API Service Created Webhook to invoke an API Builder API
metadata:
  scope:
    kind: Integration
    name: api-service-revision-created-integration
spec:
    enabled: true
    url: <YOUR WEBHOOK HANDLER APPLICATION URL>
    headers:
        Content-Type: application/json
---
group: management
apiVersion: v1alpha1
kind: ResourceHook
name: api-service-revision-created-integration-rh
title: Resource Hook to monitor all environments for new API Service Revision created
metadata:
  scope:
    kind: Integration
    name: api-service-revision-created-integration
spec:
  triggers:
    - group: management
      kind: APIServiceRevision
      name: '*'
      type:
        - created
      scope:
        kind: Environment
        name: '*'
  webhooks:
    - api-service-revision-created-integration-wh

You can use the YAML file to create the Integration (and associated webhook and resource hook) as follows:

axway central create -f api_service_revision_created_integration.yaml

If you modify your YAML, you can apply your changes as follows:

axway central apply -f api_service_revision_created_integration.yaml

Now whenever an API is discovered, a webhook call will be made to your application.

API Builder Webhook Handler Application

The API Builder project exposes one API:

POST /api/amplifycentralwebhookhandler

Once triggered the API parses the webhook payload and checks the Swagger/OAS doc and if it’s OAS3 modifies the description to add contact details.

The POST /api/amplifycentralwebhookhandler API flow is shown below:

In order to use the API Builder project or Docker Image, you need to set the following environment variables:

PORT=8080
CLIENT_ID=<AMPLIFY SERVICE ACCOUNT CLIENT ID>
CLIENT_SECRET=<AMPLIFY SERVICE ACCOUNT CLIENT SECRET>
API_KEY=<AN ARBITRARY API KEY FOR YOUR API BUILDER API THAT YOU CREATE AND USE IN YOUR INTEGRATION>
API_CENTRAL_URL=<YOUR AMPLIFY CENTRAL BASE URL>

A service account is required to make Amplify API calls (to GET and PUT the API Service). You can read about Amplify Service Accounts here.

Here are some details from the API Builder flow:

  • The OAS Document is Base64 encoded in the webhook payload. The extractOAS  JS flow node decodes that in JavaScript as follows:
let oasB64Decoded = JSON.parse(Buffer.from(data.request.body.payload.spec.definition.value, 'base64').toString('utf8'));
return oasB64Decoded;
  • We determine if the OAS Document is OAS3 (vs OAS2) in the calculateIsOAS3 JS flow node and the isOAS3 Condition flow node using the following code to see if the OAS Document has an openapi property as per the OAS3 specification:
    return (data.extractOASResult.hasOwnProperty('openapi'));
  • The URL to get the API Service is constructed in the prepareGetAPIService JS flow node:
    let env = data.request.body.payload.metadata.scope.name;
    let name = data.request.body.payload.metadata.references.find(c => c.kind === 'APIService').name;
    let url = `${data.env.API_CENTRAL_URL}/apis/management/v1alpha1/environments/${env}/apiservices/${name}`;
  • The URL to get the API Service and the revised API Service description are constructed in the preparePutAPIService JS flow node:
    let body = data.getAPIServiceResponse.body;
    let prefix = `OAS ${data.extractOASResult.openapi} document contact is ${data.extractOASResult.info.contact.name} ([${data.extractOASResult.info.contact.email}](mailto:${data.extractOASResult.info.contact.email}))\n\n`;
    body.spec.description = prefix+body.spec.description;
    return {body};

Summary

The Amplify platform is open and extensible thanks to its powerful webhooks and platform APIs. In this example, we saw how to add useful information from the API’s OAS3 document to the discovered API Service description.