Marketplace Webhook Service

Separate listener. Unlike every other page in this reference, these routes are not served under /api/v1. They live on a dedicated marketplace webhook listener rooted at /marketplace/api/v1, run by the API Server’s marketplace subcommand. Paths below are relative to that root (/marketplace/api/v1/...). This listener exists only on marketplace deployments (AWS / Azure / GCP marketplace modes).

The webhook service handles inbound subscription lifecycle events pushed by the cloud marketplaces, answers the public “is this standalone org claimable?” check used by the claim flow, and exposes a version endpoint identical in shape to the main server’s /api/v1/version.

Authentication model. None of these endpoints use a platform bearer token. The claimable check and version endpoint are public. The three notification endpoints are authenticated by the webhook itself — by verifying the payload and either the source IP range (AWS) or a per-installer secret query parameter (Azure / GCP) — not by KubeDB Platform token/session security.

Availability on this platform. The /marketplace/api/v1/* root is not served on the reference deployment (appscode, a standard non-marketplace install). Requests to it fall through to the web frontend and return HTTP 200 with Content-Type: text/html (the SPA), rather than the JSON documented here. The endpoints below are therefore documented from the OpenAPI schema and marked as not deployed; treat the JSON examples as the shapes returned by an actual marketplace deployment.


Claimable check

GET /marketplaces/standalone-organizations/{claimID}/claimable

Evaluate the claim-rules flags of a standalone (marketplace-created) organization, identified by its claim ID, and report whether it can currently be claimed. The check is proxied to the central marketplace server.

  • Auth: public (security: []). No token required.

Path parameters:

NameTypeDescription
claimIDstringThe claim ID of the standalone organization.

Response — 200 (OrgClaimableCheckResp). Returned both when the org is claimable and when the retry backoff has not yet expired but the org is already flagged claimable.

{
  "isClaimable": true,
  "claimID": "01HZK9<claim-id>"
}
FieldTypeDescription
isClaimablebooleanWhether the standalone organization can currently be claimed.
claimIDstringEcho of the claim ID that was checked.

Other statuses: 404 standalone org not found; 409 already claimed; 429 retry backoff not yet expired — try again later; 500 error while evaluating claim rules. Error bodies use the marketplace ApiError shape:

{ "message": "standalone organization already claimed" }

Example

curl https://<akp-host>/marketplace/api/v1/marketplaces/standalone-organizations/<claimID>/claimable

Verified: returned 200 with Content-Type: text/html against the reference host on 2026-07-14 — i.e. the marketplace webhook listener is not deployed here and the request was served by the web frontend SPA (catch-all), not the webhook service. Documented from schema.


Subscription notifications (webhook callbacks)

These three endpoints are the callback targets registered with each cloud marketplace. They are POST only and are called by the marketplace, not by platform clients — they are documented here for completeness. On a successful bind they return the generated installer archive download link.

POST /marketplaces/aws/notification/resource

Handle an AWS Marketplace bind-event notification.

  • Auth: enforced by the webhook. The payload is verified (marketplace must be Aws; cluster ID and options validated) and, outside dev run mode, the source IP must fall within the allowed AWS EC2 IP ranges. No platform bearer-token security.

Request body (AwsWebhookNotification):

{
  "eventType": "subscribe-success",
  "eventTime": "2026-07-14T10:00:00Z",
  "bindingInfo": {
    "marketplace": "Aws",
    "installerId": "inst-abc123",
    "clusterId": "cls-abc123",
    "AWSAccountID": "111122223333",
    "adminUsername": "admin",
    "adminPassword": "<redacted>",
    "domainWhiteList": ["example.com"],
    "options": {}
  }
}
FieldTypeRequiredDescription
eventTypestringnoMarketplace event type.
eventTimestring (date-time)noTime the event was emitted.
bindingInfoobject (BindingInfo)yesSubscription binding details (see below).

BindingInfo fields (shared by AWS/Azure/GCP; embeds InitialInput):

FieldTypeDescription
marketplacestring (Aws/Azure/Gcp)Marketplace identifier.
installerIdstringInstaller this subscription binds to.
clusterIdstringTarget cluster ID.
AWSAccountIDstringAWS account ID (AWS only).
adminUsernamestringInitial admin username for the deployment.
adminPasswordstringInitial admin password (sensitive).
domainWhiteListstring[]Allowed email/login domains.
optionsobjectFree-form installer options.

Response — 200: subscription bound; returns the installer archive link.

{ "link": "https://<akp-host>/.../installer-archive.tgz" }

Other statuses: 400 payload / binding-info / option processing failed; 403 request from an unauthorized IP; 500 provisioning error (ApiError body).

POST /marketplaces/azure/notification/resource

Handle an Azure Marketplace lifecycle notification (PUT, DELETE, BIND).

  • Auth: enforced by the webhook via a per-installer secret query parameter that must match the configured marketplace API secret. No platform bearer-token security.

Query parameters:

NameTypeRequiredDescription
secretstringnoMarketplace API secret used to authenticate the Azure webhook call.

Request body (AzureWebhookNotification). Note: managedResourceGroupId and resourceIdParts are populated server-side and are not part of the incoming JSON payload.

{
  "eventType": "BIND",
  "applicationId": "/subscriptions/<sub>/resourceGroups/<rg>/providers/...",
  "eventTime": "2026-07-14T10:00:00Z",
  "provisioningState": "Succeeded",
  "billingDetails": { "resourceUsageId": "<usage-id>" },
  "plan": {
    "publisher": "appscode",
    "product": "ace",
    "name": "standard",
    "version": "v2026.6.19"
  },
  "bindingInfo": {
    "marketplace": "Azure",
    "installerId": "inst-abc123",
    "clusterId": "cls-abc123"
  }
}
FieldTypeDescription
eventTypestringLifecycle event (PUT, DELETE, BIND).
applicationIdstringAzure application resource ID.
managedResourceGroupIdstringManaged resource group (server-populated).
resourceIdPartsobjectParsed resource-ID parts (server-populated).
eventTimestring (date-time)Event time.
provisioningStatestringAzure provisioning state.
billingDetails.resourceUsageIdstringAzure metered-billing resource usage ID.
planobjectPublisher / product / name / version of the plan.
errorobjectError code/message/details, when the event reports a failure.
bindingInfoobject (BindingInfo)Subscription binding details.

Response — 200: notification processed. For PUT/DELETE an empty body with status 200; for BIND the installer archive link is returned.

Other statuses: 400 invalid subscription ID / unknown event type / invalid binding info; 403 secret mismatch (or subscription not found while revoking contracts on delete); 500 processing error.

POST /marketplaces/gcp/notification/resource

Handle a GCP Marketplace bind-event notification.

  • Auth: enforced by the webhook via a per-installer secret query parameter that must match the configured marketplace API secret (bypassed only for the designated GCP Marketplace test installer). No platform bearer-token security.

Query parameters:

NameTypeRequiredDescription
secretstringnoMarketplace API secret used to authenticate the GCP webhook call.

Request body (GcpWebhookNotification):

{
  "eventType": "subscribe-success",
  "eventTime": "2026-07-14T10:00:00Z",
  "bindingInfo": {
    "marketplace": "Gcp",
    "installerId": "inst-abc123",
    "clusterId": "cls-abc123"
  }
}
FieldTypeRequiredDescription
eventTypestringnoMarketplace event type.
eventTimestring (date-time)noEvent time.
bindingInfoobject (BindingInfo)yesSubscription binding details.

Response — 200: subscription bound; returns the installer archive link.

{ "link": "https://<akp-host>/.../installer-archive.tgz" }

Other statuses: 400 invalid binding info / installer lookup failure; 403 secret mismatch or installer already bound; 500 provisioning error.


Version

GET /version

Return the version of the marketplace webhook service. Identical in shape to the main server’s GET /api/v1/version.

  • Auth: public (security: []).

Response — 200 (ServerVersion):

{ "version": "v2026.6.19" }
FieldTypeDescription
versionstringServer application version.

Example

curl https://<akp-host>/marketplace/api/v1/version

Verified: returned 200 with Content-Type: text/html against the reference host on 2026-07-14 — the /marketplace/api/v1 listener is not deployed here, so the request was served by the web frontend SPA, not the webhook service. For comparison, the main server’s GET /api/v1/version returned 200 with {"version":"v2026.6.19"} (application/json) — that is the shape this endpoint returns on an actual marketplace deployment.