Skip to main content
Custom API endpoints let you add your own HTTP endpoints to the Orchestrator. Use custom APIs to build health checks, webhook receivers, token exchange endpoints, or any custom endpoint that needs access to sessions, caches, and other Orchestrator services.

Request Lifecycle

Unlike other hooks that run during request processing, serveSE runs once when the Orchestrator starts up. Your extension registers HTTP route handlers that then execute whenever a matching request arrives.

Hooks

serveSE

Register custom HTTP endpoints on the Orchestrator. This hook runs at startup and gives you access to the router to define your own API routes. Use this to implement custom REST endpoints, webhook receivers, or internal service APIs. Signature:
func ServeAPI(api orchestrator.Orchestrator) error
App types: Top-level apis[] Config location: apis[].serveSE Parameters:
ParameterTypeDescription
apiorchestrator.OrchestratorAccess to sessions, caches, secrets, logging, router, and other Orchestrator services
Returns: error — return nil on success, or an error if the API handler setup fails. Examples:
When you need to receive webhooks at the Orchestrator and relay them to an external system — such as a SIEM, logging platform, or notification service — this extension registers a /webhooks/forward endpoint that accepts incoming requests and forwards them using a reusable HTTP client.
webhook-forwarder.go
package main

import (
    "fmt"
    "io"
    "net/http"
    "time"

    "github.com/strata-io/service-extension/orchestrator"
)

func ServeAPI(api orchestrator.Orchestrator) error {
    logger := api.Logger()

    // Create a reusable HTTP client at startup. Reusing clients pools
    // TCP connections and prevents resource exhaustion under load.
    apiHTTP := api.HTTP()
    err := apiHTTP.SetClient("forwarder", &http.Client{
        Timeout: 10 * time.Second,
    })
    if err != nil {
        return fmt.Errorf("failed to create HTTP client: %w", err)
    }

    // Read the destination URL from SE metadata.
    metadata := api.Metadata()
    targetURL := metadata["targetURL"].(string)

    // Read the auth token from the secret provider.
    sp := api.SecretProvider()
    authToken, err := sp.GetString("webhook-auth-token")
    if err != nil {
        return fmt.Errorf("failed to get auth token: %w", err)
    }

    router := api.Router()
    router.HandleFunc("/webhooks/forward", func(rw http.ResponseWriter, req *http.Request) {
        client, _ := apiHTTP.GetClient("forwarder")

        fwd, err := http.NewRequest(req.Method, targetURL, req.Body)
        if err != nil {
            logger.Error("se", "failed to create forward request", "error", err.Error())
            http.Error(rw, "internal error", http.StatusInternalServerError)
            return
        }
        fwd.Header.Set("Content-Type", req.Header.Get("Content-Type"))
        fwd.Header.Set("Authorization", "Bearer "+authToken)

        resp, err := client.Do(fwd)
        if err != nil {
            logger.Error("se", "failed to forward webhook", "error", err.Error())
            http.Error(rw, "forwarding failed", http.StatusBadGateway)
            return
        }
        defer resp.Body.Close()

        rw.WriteHeader(resp.StatusCode)
        io.Copy(rw, resp.Body)
    })

    logger.Info("se", "registered /webhooks/forward endpoint")
    return nil
}

Configuration

Custom API endpoints are defined under the apis top-level key in the deployment configuration.
maverics.yaml
apis:
  - name: my-custom-endpoint
    serveSE:
      funcName: ServeAPI
      file: /path/to/api-handler.go

Field Reference

KeyTypeDefaultRequiredDescription
apis[].namestringYesUnique name for the API endpoint
apis[].serveSEServiceExtensionYesService extension that handles requests to this endpoint
The serveSE field accepts the standard ServiceExtension object (funcName, code/file, metadata, goPath, allowedProtectedPackages).

Validation Rules

  • Each name must be unique across all apis[] entries
  • The serveSE field is required — an API endpoint without a handler is invalid

Example

A custom health check endpoint and a user info endpoint:
maverics.yaml
apis:
  - name: custom-health
    serveSE:
      funcName: HealthCheck
      file: /etc/maverics/extensions/health-check.go
      metadata:
        backendURL: "https://backend.example.com/health"

  - name: user-info
    serveSE:
      funcName: GetUserInfo
      file: /etc/maverics/extensions/user-info.go
Multiple custom APIs can be defined, each with its own service extension handler.