curl -X POST "https://us.api.konghq.com/v3/portals" \
--no-progress-meter --fail-with-body \
-H "Authorization: Bearer $KONNECT_TOKEN" \
--json '{
"name": "MyDevPortal",
"authentication_enabled": true,
"auto_approve_applications": true,
"auto_approve_developers": true,
"default_api_visibility": "public",
"default_page_visibility": "public"
}'Review partner API access requests with Dev Portal custom forms
Create a custom developer registration form and API registration form with the Konnect API (/v3/portals/{portalId}/forms). Link the API form to your published API, then turn off auto-approve so new sign-ups and registrations are marked as pending until you review the submitted additional_data.
Prerequisites
Kong Konnect
This is a Konnect tutorial and requires a Konnect personal access token.
-
Create a new personal access token by opening the Konnect PAT page and selecting Generate Token.
-
Export your token to an environment variable:
export KONNECT_TOKEN='YOUR_KONNECT_PAT' -
Run the quickstart script to automatically provision a Control Plane and Data Plane, and configure your environment:
curl -Ls https://get.konghq.com/quickstart | bash -s -- -k $KONNECT_TOKEN \ --deck-outputThis sets up a Konnect Control Plane named
quickstart, provisions a local Data Plane, and prints out the following environment variable exports:export DECK_KONNECT_TOKEN=$KONNECT_TOKEN export DECK_KONNECT_CONTROL_PLANE_NAME=quickstart export KONNECT_CONTROL_PLANE_URL=https://us.api.konghq.com export KONNECT_PROXY_URL='http://localhost:8000'Copy and paste these into your terminal to configure your session.
decK v1.65.3+
To complete this tutorial, install decK. We recommend keeping decK up to date with the latest version (1.65.3).
decK is a CLI tool for managing Kong Gateway declaratively with state files.
This guide uses deck gateway apply, which directly applies entity configuration to your Gateway instance.
You can check your current decK version with deck version.
Required entities
For this tutorial, you’ll need Kong Gateway entities, like Gateway Services and Routes, pre-configured. These entities are essential for Kong Gateway to function but installing them isn’t the focus of this guide. Follow these steps to pre-configure them:
-
Run the following command:
echo ' _format_version: "3.0" services: - name: example-service url: http://httpbin.konghq.com/anything routes: - name: example-route paths: - "/anything" service: name: example-service protocols: - http - https ' | deck gateway apply -
To learn more about entities, you can read our entities documentation.
Kong Konnect roles
To run this tutorial, you need the following Konnect teams and roles:
- Portal Admin: Manage Dev Portal settings and custom forms.
- API Registration Approver and Portal Viewer: Review and approve developer and application registrations.
Dev Portal
For this tutorial, you’ll need a Dev Portal and some Dev Portal settings pre-configured. These settings are essential for Dev Portal to function but configuring them isn’t the focus of this guide. If you don’t have these settings already configured, follow these steps to pre-configure them:
-
-
Export your Dev Portal ID and URL from the output:
export PORTAL_ID='YOUR-DEV-PORTAL-ID' export PORTAL_URL='YOUR-DEV-PORTAL-DOMAIN' -
Create a page in your Dev Portal so published APIs will display:
curl -X POST "https://us.api.konghq.com/v3/portals/$PORTAL_ID/pages" \ --no-progress-meter --fail-with-body \ -H "Authorization: Bearer $KONNECT_TOKEN" \ --json '{ "title": "My Page", "slug": "/", "description": "A custom page about developer portals", "visibility": "public", "status": "published", "content": "# Welcome to My Dev Portal\nExplore the available APIs below:\n::apis-list\n---\npersist-page-number: true\ncta-text: \"View APIs\"\n---\n" }'
Published API
-
Create an API using the
/v3/apisendpoint:curl -X POST "https://us.api.konghq.com/v3/apis" \ --no-progress-meter --fail-with-body \ -H "Authorization: Bearer $KONNECT_TOKEN" \ --json '{ "name": "MyAPI", "attributes": { "env": [ "development" ], "domains": [ "web", "mobile" ] } }'Export the ID of your API from the response:
export API_ID='YOUR-API-ID' -
First, send a request to the
/v2/control-planesendpoint to get the ID of thequickstartControl Plane:curl -X GET "https://us.api.konghq.com/v2/control-planes?filter%5Bname%5D%5Bcontains%5D=quickstart" \ --no-progress-meter --fail-with-body \ -H "Authorization: Bearer $KONNECT_TOKEN"Export your Control Plane ID:
export CONTROL_PLANE_ID='YOUR-CONTROL-PLANE-ID' -
Next, list Services by using the
/v2/control-planes/{controlPlaneId}/core-entities/servicesendpoint:curl -X GET "https://us.api.konghq.com/v2/control-planes/$CONTROL_PLANE_ID/core-entities/services" \ --no-progress-meter --fail-with-body \ -H "Authorization: Bearer $KONNECT_TOKEN"Export the ID of the
example-service:export SERVICE_ID='YOUR-GATEWAY-SERVICE-ID' -
Associate the API with a Service using the
/v3/apis/{apiId}/implementationsendpoint:curl -X POST "https://us.api.konghq.com/v3/apis/$API_ID/implementations" \ --no-progress-meter --fail-with-body \ -H "Authorization: Bearer $KONNECT_TOKEN" \ --json '{ "service": { "control_plane_id": "'$CONTROL_PLANE_ID'", "id": "'$SERVICE_ID'" } }' -
Now you can publish the API to your Dev Portal using the
/v3/apis/{apiId}/publications/{portalId}endpoint:curl -X PUT "https://us.api.konghq.com/v3/apis/$API_ID/publications/$PORTAL_ID" \ --no-progress-meter --fail-with-body \ -H "Authorization: Bearer $KONNECT_TOKEN"
In this tutorial, you’ll build both a developer and API registration custom form, turn off auto-approve so new registrations wait for review, and see how the submitted answers show up when you go to approve them. This can be useful if your company publishes a partner-facing API and you want to only allow users and applications that are from valid partners. Before a partner’s developers get access, you may want to know their company name and job title at sign-up, and a business justification when they register for the API.
Turn off auto-approve for developers and applications
To review submitted answers before granting access, turn off auto-approve for new developers and application registrations by sending a PATCH request to the /portals/{portalId} endpoint:
curl -X PATCH "https://us.api.konghq.com/v3/portals/$PORTAL_ID" \
--no-progress-meter --fail-with-body \
-H "Authorization: Bearer $KONNECT_TOKEN" \
--json '{
"auto_approve_developers": false,
"auto_approve_applications": false
}'New developers and application registrations now will have a pending status until you approve them.
Create a developer registration form
Create a custom form that collects a partner developer’s company name and job title, in addition to the required name and email fields, by sending a POST request to the /portals/{portalId}/forms endpoint:
curl -X POST "https://us.api.konghq.com/v3/portals/$PORTAL_ID/forms" \
--no-progress-meter --fail-with-body \
-H "Authorization: Bearer $KONNECT_TOKEN" \
--json '{
"type": "developer_registration",
"status": "published",
"fields": [
{
"type": "text",
"name": "full_name",
"label": "Full name",
"placeholder": "Enter your full name",
"required": true
},
{
"type": "email",
"name": "email",
"label": "Email address",
"placeholder": "you@example.com",
"required": true
},
{
"type": "text",
"name": "company_name",
"label": "Company name",
"placeholder": "Enter your company name",
"required": true
},
{
"type": "text",
"name": "job_title",
"label": "Job title",
"placeholder": "Enter your job title",
"required": true
},
{
"type": "submit",
"name": "submit",
"value": "Create account"
}
]
}'The full_name, email, and submit fields are required for every developer registration form.
Once published, this form replaces the default sign-up form.
Create an API registration form
Create a second form that collects a business justification when a partner registers an application for the API, and capture its ID as $FORM_ID, by sending a POST request to the /portals/{portalId}/forms endpoint:
FORM_ID=$(curl -X POST "https://us.api.konghq.com/v3/portals/$PORTAL_ID/forms" \
--no-progress-meter --fail-with-body \
-H "Authorization: Bearer $KONNECT_TOKEN" \
--json '{
"type": "api_registration",
"name": "api-registration",
"status": "published",
"fields": [
{
"type": "text",
"name": "api_id",
"label": "API"
},
{
"type": "textarea",
"name": "business_justification",
"label": "Why do you need access to this API?",
"placeholder": "Describe how you plan to use the API",
"required": true
},
{
"type": "submit",
"name": "submit",
"value": "Request access"
}
]
}' | jq -r ".id"
)Every API registration form must include a text field named api_id. Its value is populated from the API you’re registering for, not from something the developer fills in, so don’t make it required.
Create an application auth strategy
Applications need credentials to call the API.
Configure a key auth application authentication strategy, and capture its ID as $AUTH_STRATEGY_ID, by sending a POST request to the /application-auth-strategies endpoint:
AUTH_STRATEGY_ID=$(curl -X POST "https://us.api.konghq.com/v2/application-auth-strategies" \
--no-progress-meter --fail-with-body \
-H "Authorization: Bearer $KONNECT_TOKEN" \
--json '{
"name": "API Key Auth",
"display_name": "API Key Auth",
"strategy_type": "key_auth",
"configs": {
"key-auth": {
"key_names": [
"apikey"
]
}
}
}' | jq -r ".id"
)Link the form and auth strategy to your API
Update your API’s publication, setting form_id to the form’s ID and auth_strategy_ids to the auth strategy’s ID, by sending a PUT request to the /apis/{apiId}/publications/{portalId} endpoint:
curl -X PUT "https://us.api.konghq.com/v3/apis/$API_ID/publications/$PORTAL_ID" \
--no-progress-meter --fail-with-body \
-H "Authorization: Bearer $KONNECT_TOKEN" \
--json '{
"form_id": "'$FORM_ID'",
"auth_strategy_ids": [
"'$AUTH_STRATEGY_ID'"
]
}'Register a partner developer
Simulate a partner developer signing up with additional_data matching your custom fields, and capture their ID as $DEVELOPER_ID, by sending a POST request to the /portals/{portalId}/developers endpoint:
DEVELOPER_ID=$(curl -X POST "https://us.api.konghq.com/v3/portals/$PORTAL_ID/developers" \
--no-progress-meter --fail-with-body \
-H "Authorization: Bearer $KONNECT_TOKEN" \
--json '{
"full_name": "Raina Sovani",
"email": "raina.sovani@example.com",
"additional_data": {
"company_name": "Example Air",
"job_title": "Partnerships Manager"
}
}' | jq -r ".id"
)Since auto-approve is off, this developer’s status is pending.
Create an application and register it for the API
-
Create an application for the developer, and capture its ID as
$APPLICATION_ID, by sending aPOSTrequest to the/portals/{portalId}/applicationsendpoint:APPLICATION_ID=$(curl -X POST "https://us.api.konghq.com/v3/portals/$PORTAL_ID/applications" \ --no-progress-meter --fail-with-body \ -H "Authorization: Bearer $KONNECT_TOKEN" \ --json '{ "name": "Example Air Integration", "description": "A partner application requesting access to the API.", "auth_strategy_id": "'$AUTH_STRATEGY_ID'", "owner": { "id": "'$DEVELOPER_ID'", "type": "developer" } }' | jq -r ".id" ) -
Register the application for the API with
additional_data.business_justification, and capture the registration ID as$REGISTRATION_ID, by sending aPOSTrequest to the/portals/{portalId}/applications/{applicationId}/registrationsendpoint:REGISTRATION_ID=$(curl -X POST "https://us.api.konghq.com/v3/portals/$PORTAL_ID/applications/$APPLICATION_ID/registrations" \ --no-progress-meter --fail-with-body \ -H "Authorization: Bearer $KONNECT_TOKEN" \ --json '{ "api_id": "'$API_ID'", "additional_data": { "business_justification": "We are integrating our booking platform with your API to display real-time availability to our customers." } }' | jq -r ".id" )This registration also displays as
pending.
Approve API applications based on developer data
-
Review the submitted answers before approving. View the developer’s
additional_databy sending aGETrequest to the/portals/{portalId}/developers/{developerId}endpoint:curl -X GET "https://us.api.konghq.com/v3/portals/$PORTAL_ID/developers/$DEVELOPER_ID" \ --no-progress-meter --fail-with-body \ -H "Authorization: Bearer $KONNECT_TOKEN"The response includes
additional_data.company_nameandadditional_data.job_title. -
List application registrations, filtered to pending ones, to see the business justification, by sending a
GETrequest to the/portals/{portalId}/application-registrationsendpoint:curl -X GET "https://us.api.konghq.com/v3/portals/$PORTAL_ID/application-registrations?filter%5Bstatus%5D=pending" \ --no-progress-meter --fail-with-body \ -H "Authorization: Bearer $KONNECT_TOKEN"The matching registration includes
additional_data.business_justification. -
Once you’re satisfied with the answers, approve the developer, by sending a
PATCHrequest to the/portals/{portalId}/developers/{developerId}endpoint:curl -X PATCH "https://us.api.konghq.com/v3/portals/$PORTAL_ID/developers/$DEVELOPER_ID" \ --no-progress-meter --fail-with-body \ -H "Authorization: Bearer $KONNECT_TOKEN" \ --json '{ "status": "approved" }' -
Approve the registration, by sending a
PATCHrequest to the/portals/{portalId}/applications/{applicationId}/registrations/{registrationId}endpoint:curl -X PATCH "https://us.api.konghq.com/v3/portals/$PORTAL_ID/applications/$APPLICATION_ID/registrations/$REGISTRATION_ID" \ --no-progress-meter --fail-with-body \ -H "Authorization: Bearer $KONNECT_TOKEN" \ --json '{ "status": "approved" }'
Automation ideas
Once you can see submitted company names, job titles, and business justifications, you can do the following:
- Assign the developer to a Dev Portal team based on their job title or company, so they are assigned the correct access as soon as they’re approved.
- Send a Slack notification to your partnerships channel whenever a registration references a new company.
- Forward
additional_datato an in-house approvals dashboard or CRM so your team can track and act on requests outside Konnect.
Dev Portal doesn’t have a webhook for new registrations or form submissions, so any of these integrations need to poll the Konnect API on an interval.
For example, you can filter on status=pending and sort by created_at, and then track the last ID or timestamp you’ve already processed.
Cleanup
Clean up Konnect environment
If you created a new control plane and want to conserve your free trial credits or avoid unnecessary charges, delete the new control plane used in this tutorial.