platform-api

module
v0.11.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 10, 2026 License: Apache-2.0

README

Platform API

Backend service that powers the API Platform portals, gateways, and automation flows.

Quick Start

Prerequisites

Before using the Platform API, obtain a bearer token for authentication. In local JWT mode (default) you can generate a token using the configured AUTH_JWT_SECRET_KEY. In IDP mode, obtain a token from your identity provider.

Build and Run
# Build
cd platform-api
go build ./cmd/main.go

# Run (TLS with self-signed certificates)
cd platform-api
go run ./cmd/main.go
Database Configuration

Platform API supports sqlite3 (default), postgres, and sqlserver.

# SQL Server example
export DATABASE_DRIVER=sqlserver
export DATABASE_HOST=sqlserver.example.internal
export DATABASE_PORT=1433
export DATABASE_NAME=platform_api
export DATABASE_USER=sa
export DATABASE_PASSWORD='<strong-password>'
export DATABASE_SSL_MODE=disable

cd platform-api
go run ./cmd/main.go
Step-by-Step Workflow

Across the API, resources with a handle expose it as id (an immutable, URL-safe slug), with a separate human-readable displayName. Path parameters are handle-based, not UUIDs — e.g. {projectId}, {gatewayId}, {restApiId} are all handles. See src/resources/openapi.yaml for the full contract.

1. Register an Organization

curl -k -X POST https://localhost:9243/api/v0.9/organizations \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer <your-token>' \
  -d '{"id":"acme","displayName":"ACME Corporation","region":"us-east-1"}'

2. Create a Project

curl -k -X POST https://localhost:9243/api/v0.9/projects \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer <your-token>' \
  -d '{
    "displayName": "Production APIs"
  }'

Response includes the project handle, auto-generated from displayName if id is omitted:

{
  "id": "production-apis",
  "displayName": "Production APIs",
  "organizationId": "acme",
  "createdAt": "2026-06-21T15:12:44+05:30",
  "updatedAt": "2026-06-21T15:12:44+05:30"
}

3. Create a Gateway

curl -k -X POST https://localhost:9243/api/v0.9/gateways \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer <your-token>' \
  -d '{
    "id": "prod-gateway-01",
    "displayName": "Production Gateway 01",
    "endpoints": ["https://prod-gateway-01.example.com:8443/api/v1"],
    "functionalityType": "regular"
  }'

Response includes the gateway handle (used as {gatewayId} in all subsequent calls):

{
  "id": "prod-gateway-01",
  "displayName": "Production Gateway 01",
  "organizationId": "acme",
  "endpoints": ["https://prod-gateway-01.example.com:8443/api/v1"],
  "functionalityType": "regular",
  "isCritical": false,
  "version": "1.0",
  "isActive": false,
  "createdAt": "2026-06-21T15:12:44+05:30",
  "updatedAt": "2026-06-21T15:12:44+05:30"
}

4. Generate Gateway Token

curl -k -X POST https://localhost:9243/api/v0.9/gateways/prod-gateway-01/tokens \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer <your-token>'

Response includes the gateway authentication token:

{
  "id": "7ed55286-66a4-43ae-9271-bd1ead475a55",
  "token": "QY8Rnm9bJ-incsGU0xtFz2vx16I1IVhEf0Ma_4O5F9s",
  "createdAt": "2026-06-21T15:12:57+05:30",
  "message": "New token generated successfully. Old token remains active until revoked."
}

List Gateway Tokens:

curl -k https://localhost:9243/api/v0.9/gateways/prod-gateway-01/tokens \
  -H 'Authorization: Bearer <your-token>'

Returns a bare array of token summaries ([{"id": "...", "status": "active", "createdAt": "...", "revokedAt": null}]) — token hashes are never exposed.

5. Connect Gateway to Platform (WebSocket)

Install wscat if not already installed:

npm install -g wscat

Connect using the gateway token:

wscat -n -c wss://localhost:9243/api/internal/v1/ws/gateways/connect \
  -H "api-key: <gateway-token>"

Expected output:

Connected (press CTRL+C to quit)
< {"type":"connection.ack","gatewayId":"4dac93bd-07ba-417e-aef8-353cebe3ba73","connectionId":"3150a8b6-649d-4d12-8512-7d72e8ec7f13","timestamp":"2026-06-21T14:42:13+05:30"}

Note: gatewayId on WebSocket events is the gateway's internal UUID, not the handle returned by the REST API — the gateway itself doesn't need to know its handle.

Keep this connection open to receive real-time deployment events.

6. Create an API

curl -k -X POST 'https://localhost:9243/api/v0.9/rest-apis' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer <your-token>' \
  -d '{
      "id": "weather-api",
      "displayName": "Weather API",
      "description": "Weather API with main and sandbox upstreams",
      "context": "weather",
      "version": "1.0.0",
      "projectId": "production-apis",
      "lifeCycleStatus": "CREATED",
      "transport": ["http","https"],
      "upstream": {
         "main": { "url": "http://sample-backend:5000" },
         "sandbox": { "url": "http://sample-backend:5000/sandbox" }
       }
    }'

projectId is the project's handle (from step 2), not its UUID.

7. Deploy API to Gateway

curl -k -X POST 'https://localhost:9243/api/v0.9/rest-apis/weather-api/deployments' \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer <your-token>' \
  -d '{
    "name": "weather-v1-prod",
    "base": "current",
    "gatewayId": "prod-gateway-01",
    "metadata": {
      "vhostMain": "example.wso2.com",
      "vhostSandbox": "sand-example.wso2.com"
    }
}'

gatewayId is the gateway's handle (from step 3), not its UUID.

Expected response:

{
  "deploymentId": "90d10e1c-8560-5c36-9d5a-124ecaa17485",
  "name": "weather-v1-prod",
  "gatewayId": "prod-gateway-01",
  "status": "DEPLOYED",
  "metadata": {
    "vhostMain": "example.wso2.com",
    "vhostSandbox": "sand-example.wso2.com"
  },
  "createdAt": "2026-06-21T16:15:18+05:30",
  "updatedAt": "2026-06-21T16:15:18+05:30",
  "baseDeploymentId": null
}

The connected gateway will receive a deployment event via WebSocket:

< {"type":"api.deployed","payload":{"apiId":"54588845-c860-4a56-8802-c06b03028543","deploymentId":"90d10e1c-8560-5c36-9d5a-124ecaa17485","performedAt":"2026-06-21T16:15:18+05:30"},"gatewayId":"4dac93bd-07ba-417e-aef8-353cebe3ba73","timestamp":"2026-06-21T16:15:18+05:30","correlationId":"ae7488ec-9559-4a81-bddd-b85e1391d2c0"}

apiId and gatewayId in the event payload are internal UUIDs, distinct from the handle-based id used in the REST API.

Configuration

All configuration is supplied via environment variables.

Authentication

Two authentication modes are supported. Exactly one should be active at a time.

AUTH_IDP_ENABLED=false (default)  →  Local JWT mode  (HMAC signature verification)
AUTH_IDP_ENABLED=true             →  IDP mode        (JWKS-based verification)

Demo mode (APIP_DEMO_MODE). Defaults to true; an explicit false/0 opts into production-grade startup checks. With demo mode off, the server will not fall back to an ephemeral secret encryption key (set PLATFORM_SECRET_ENCRYPTION_KEY or DATABASE_ENCRYPTION_KEY) and warns loudly if AUTH_JWT_SKIP_VALIDATION=true.


Local JWT Mode (default)

The server validates HMAC-signed tokens using AUTH_JWT_SECRET_KEY. Set AUTH_JWT_SKIP_VALIDATION=true only in local development environments where you do not have a token issuer available — all bearer values will be accepted without any signature check.

Variable Default Description
AUTH_JWT_SECRET_KEY your-secret-key-change-in-production HMAC signing key for token verification
AUTH_JWT_ISSUER platform-api Expected iss claim value
AUTH_JWT_SKIP_VALIDATION false Skip signature verification — development only
DEV_MODE false Suppresses the startup warning when AUTH_JWT_SKIP_VALIDATION=true

Local development with no token issuer:

export AUTH_JWT_SKIP_VALIDATION=true
export DEV_MODE=true
go run ./cmd/main.go

Production with HMAC verification:

export AUTH_JWT_SECRET_KEY=<strong-random-key>
export AUTH_JWT_ISSUER=https://your-token-issuer
go run ./cmd/main.go

Legacy variable names (still accepted, deprecated):

Old name New name
JWT_SECRET_KEY AUTH_JWT_SECRET_KEY
JWT_ISSUER AUTH_JWT_ISSUER
JWT_SKIP_VALIDATION AUTH_JWT_SKIP_VALIDATION
JWT_SKIP_PATHS AUTH_SKIP_PATHS

IDP Mode

Tokens are validated against any standards-compliant identity provider (Thunder, Asgardeo, Keycloak, Azure AD, Okta, etc.) using its JWKS endpoint. Set AUTH_IDP_ENABLED=true and supply at minimum AUTH_IDP_JWKS_URL and AUTH_IDP_ISSUER.

Variable Default Description
AUTH_IDP_ENABLED false Set to true to activate IDP mode
AUTH_IDP_NAME (empty) Optional label shown in startup logs (e.g. thunder, asgardeo)
AUTH_IDP_JWKS_URL (required) IDP's JWKS endpoint for public key retrieval
AUTH_IDP_ISSUER (required) Accepted JWT issuer
AUTH_IDP_AUDIENCE (empty) Accepted JWT audience. When set, the token's aud claim must contain this value; empty skips the check
AUTH_IDP_ORGANIZATION_CLAIM_NAME organization JWT claim holding the org UUID for the active session
AUTH_IDP_ORG_NAME_CLAIM_NAME org_name JWT claim for the org display name
AUTH_IDP_ORG_HANDLE_CLAIM_NAME org_handle JWT claim for the org URL-safe handle
AUTH_IDP_USER_ID_CLAIM_NAME sub JWT claim used as the canonical user identifier
AUTH_IDP_USERNAME_CLAIM_NAME username JWT claim for the human-readable username
AUTH_IDP_EMAIL_CLAIM_NAME email JWT claim for the user's email address
AUTH_IDP_SCOPE_CLAIM_NAME scope JWT claim carrying granted OAuth2 scopes
AUTH_IDP_VALIDATION_MODE scope Authorization mode: scope (validate scope claim directly) or role (expand IDP roles to platform roles)
AUTH_IDP_ROLES_CLAIM_PATH (empty) Dot-notation path to the roles claim (e.g. realm_access.roles). Required when AUTH_IDP_VALIDATION_MODE=role
AUTH_IDP_ROLE_MAPPINGS (empty) Comma-separated idp-role=platform-role pairs (e.g. PLATFORM_ADMIN=admin,PLATFORM_DEV=developer). When empty, IDP role values are used as-is

Example — Asgardeo:

export AUTH_IDP_ENABLED=true
export AUTH_IDP_NAME=asgardeo
export AUTH_IDP_JWKS_URL=https://api.asgardeo.io/t/<org>/oauth2/jwks
export AUTH_IDP_ISSUER=https://api.asgardeo.io/t/<org>/oauth2/token
export AUTH_IDP_AUDIENCE=<client-id>
export AUTH_IDP_ORGANIZATION_CLAIM_NAME=organizationId
export AUTH_IDP_VALIDATION_MODE=scope
export AUTH_IDP_ROLES_CLAIM_PATH=scope

Skip Paths

Path prefixes listed here bypass authentication entirely. Used for internal gateway traffic and health checks.

Variable Default
AUTH_SKIP_PATHS /health,/metrics,/api/internal/v1/ws/gateways/connect,...

To extend the default list:

export AUTH_SKIP_PATHS="/health,/metrics,/api/internal/v1/ws/gateways/connect,/my-custom-path"

Role-Based Access Control (RBAC)

Per-route scope checks are enforced when ENABLE_SCOPE_VALIDATION=true. Five built-in platform roles exist:

Role Persona Access level
admin Platform administrator Full access to all resources and operations
developer API designer Full API lifecycle; cannot manage gateways or subscription plans
publisher DevPortal manager Read APIs and publish/unpublish to DevPortals; cannot create or deploy
operator CI/CD service account Deploy and undeploy operations only; cannot create resources or manage credentials
viewer Auditor Read-only access to all resources
Variable Default Description
ENABLE_SCOPE_VALIDATION false Set to true to enforce per-route scope/role checks

In local JWT mode, scopes are read directly from the scope claim in the token.
In IDP mode with AUTH_IDP_VALIDATION_MODE=scope, scopes are read from the claim named by AUTH_IDP_SCOPE_CLAIM_NAME.
In IDP mode with AUTH_IDP_VALIDATION_MODE=role, IDP roles are resolved from AUTH_IDP_ROLES_CLAIM_PATH, mapped via AUTH_IDP_ROLE_MAPPINGS, and matched against the required roles for each route.


Database
Variable Default Description
DATABASE_DRIVER sqlite3 sqlite3 or postgres
DATABASE_DB_PATH ./data/api_platform.db SQLite file path (ignored for Postgres)
DATABASE_HOST localhost Postgres host
DATABASE_PORT 5432 Postgres port
DATABASE_NAME platform_api Postgres database name
DATABASE_USER (empty) Postgres username
DATABASE_PASSWORD (empty) Postgres password
DATABASE_SSL_MODE disable Postgres SSL mode (disable, require, verify-full)
DATABASE_EXECUTE_SCHEMA_DDL true Set to false when the DB user lacks DDL privileges
DATABASE_SUBSCRIPTION_TOKEN_ENCRYPTION_KEY (empty) 32-byte key (64 hex or 44 base64 chars) for AES-256-GCM token encryption.

Other Settings
Variable Default Description
PORT 9243 HTTP/HTTPS server port
LOG_LEVEL DEBUG Log verbosity (DEBUG, INFO, WARN, ERROR)
TLS_CERT_DIR ./data/certs Directory for TLS certificates
DEPLOYMENTS_MAX_PER_API_GATEWAY 20 Maximum deployments per API per gateway
DEPLOYMENTS_TRANSITIONAL_STATUS_ENABLED false Show DEPLOYING/UNDEPLOYING status before gateway ack
ARTIFACT_LIMITS_MAX_LLM_PROVIDERS_PER_ORG unlimited Max LLM providers per organization (0 or unset = unlimited)
ARTIFACT_LIMITS_MAX_LLM_PROXIES_PER_ORG unlimited Max LLM proxies per organization (0 or unset = unlimited)
ARTIFACT_LIMITS_MAX_MCP_PROXIES_PER_ORG unlimited Max MCP proxies per organization (0 or unset = unlimited)
ARTIFACT_LIMITS_MAX_WEBSUB_APIS_PER_ORG unlimited Max WebSub APIs per organization (0 or unset = unlimited)
ARTIFACT_LIMITS_MAX_WEBBROKER_APIS_PER_ORG unlimited Max WebBroker APIs per organization (0 or unset = unlimited)
GATEWAY_ENABLE_VERSION_VERIFICATION false Reject gateway connections with mismatched versions
API_KEY_HASHING_ALGORITHMS sha256 Comma-separated hash algorithms for API key storage

Documentation

See spec/ for product, architecture, design, and implementation documentation.

Directories

Path Synopsis
Package api provides primitives to interact with the openapi HTTP API.
Package api provides primitives to interact with the openapi HTTP API.
Package main — OSS build: no experimental plugins registered.
Package main — OSS build: no experimental plugins registered.
internal
apperror
Package apperror defines the typed application error that handlers, services, and repositories return instead of writing HTTP error responses inline.
Package apperror defines the typed application error that handlers, services, and repositories return instead of writing HTTP error responses inline.
deploymenttransform
Package deploymenttransform provides a generic, version-keyed registry for adapting canonical deployment artifact specs to the capability of a target gateway.
Package deploymenttransform provides a generic, version-keyed registry for adapting canonical deployment artifact specs to the capability of a target gateway.
dto
pagination
Package pagination holds the in-memory windowing primitive shared by the handler and service layers, so the two cannot drift apart.
Package pagination holds the in-memory windowing primitive shared by the handler and service layers, so the two cannot drift apart.
plugin
Package plugin defines the compile-time pluggable module system for platform-api.
Package plugin defines the compile-time pluggable module system for platform-api.
webhook
Package webhook implements the Platform API control-plane webhook receiver.
Package webhook implements the Platform API control-plane webhook receiver.
plugins

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL