Temporal — API Surface#

API types#

Multiple, layered: gRPC (public + internal), REST/HTTP (via grpc-gateway proxy), Nexus HTTP, CLI (urfave/cli), and a Go embedding library.


gRPC API#

Temporal exposes three tiers of gRPC APIs:

Tier 1: Public client-facing services (defined in go.temporal.io/api — external module)#

These are the services that application developers and SDK clients interact with. Both are registered on the Frontend Service’s public gRPC listener.

WorkflowService (go.temporal.io/api/workflowservice/v1)#

The primary public API — ~60 RPCs covering the complete workflow lifecycle:

Namespace management:

  • RegisterNamespace, DescribeNamespace, ListNamespaces, UpdateNamespace, DeprecateNamespace

Workflow lifecycle:

  • StartWorkflowExecution, ExecuteMultiOperation
  • DescribeWorkflowExecution, RequestCancelWorkflowExecution
  • TerminateWorkflowExecution, DeleteWorkflowExecution
  • ResetWorkflowExecution, SignalWorkflowExecution, SignalWithStartWorkflowExecution
  • QueryWorkflow, UpdateWorkflowExecution, PollWorkflowExecutionUpdate
  • GetWorkflowExecutionHistory, GetWorkflowExecutionHistoryReverse
  • UpdateWorkflowExecutionOptions (versioning override)
  • PauseWorkflowExecution, UnpauseWorkflowExecution

Worker polling (SDK internal):

  • PollWorkflowTaskQueue, RespondWorkflowTaskCompleted, RespondWorkflowTaskFailed
  • PollActivityTaskQueue, RecordActivityTaskHeartbeat, RecordActivityTaskHeartbeatById
  • RespondActivityTaskCompleted, RespondActivityTaskCompletedById
  • RespondActivityTaskFailed, RespondActivityTaskFailedById
  • RespondActivityTaskCanceled, RespondActivityTaskCanceledById
  • RespondQueryTaskCompleted, ResetStickyTaskQueue

Activity management (new):

  • UpdateActivityOptions, PauseActivity, UnpauseActivity, ResetActivity

Visibility / search:

  • ListWorkflowExecutions, ListOpenWorkflowExecutions, ListClosedWorkflowExecutions
  • ListArchivedWorkflowExecutions, ScanWorkflowExecutions, CountWorkflowExecutions
  • GetSearchAttributes

Schedule management:

  • CreateSchedule, DescribeSchedule, UpdateSchedule, DeleteSchedule
  • PatchSchedule, ListSchedules, ListScheduleMatchingTimes

Task queue:

  • DescribeTaskQueue, ListTaskQueuePartitions, ResetStickyTaskQueue
  • UpdateWorkerBuildIdCompatibility, GetWorkerBuildIdCompatibility
  • UpdateWorkerVersioningRules, GetWorkerVersioningRules
  • GetWorkerTaskReachability, ShutdownWorker
  • UpdateTaskQueueConfig, FetchWorkerConfig, UpdateWorkerConfig

Batch operations:

  • StartBatchOperation, StopBatchOperation, DescribeBatchOperation, ListBatchOperations

Worker deployment:

  • RecordWorkerHeartbeat, ListWorkers, DescribeWorker

Nexus task polling (SDK internal):

  • PollNexusTaskQueue, RespondNexusTaskCompleted, RespondNexusTaskFailed

Workflow rules (experimental):

  • CreateWorkflowRule, DescribeWorkflowRule, DeleteWorkflowRule, ListWorkflowRules, TriggerWorkflowRule

Cluster info:

  • GetClusterInfo, GetSystemInfo

OperatorService (go.temporal.io/api/operatorservice/v1)#

Cluster administration operations, also served on the Frontend’s public gRPC port:

  • AddSearchAttributes, RemoveSearchAttributes, ListSearchAttributes
  • DeleteNamespace
  • AddOrUpdateRemoteCluster, RemoveRemoteCluster, ListClusters
  • CreateNexusEndpoint, UpdateNexusEndpoint, DeleteNexusEndpoint, GetNexusEndpoint, ListNexusEndpoints

Tier 2: Internal server-to-server services (defined in proto/internal/ in this repo)#

These are not exposed to clients; they use internal gRPC on separate ports and carry no auth.

HistoryService (api/historyservice/v1) — ~55 RPCs#

The core shard-level execution engine API. All workflow state mutations flow through here from Frontend:

  • Workflow task/activity lifecycle: StartWorkflowExecution, RecordWorkflowTaskStarted, RecordActivityTaskStarted, RespondWorkflowTaskCompleted, RespondActivityTask*
  • Signals/queries: SignalWorkflowExecution, QueryWorkflow, UpdateWorkflowExecution, PollWorkflowExecutionUpdate
  • History access: GetWorkflowExecutionHistory, GetWorkflowExecutionHistoryReverse, GetWorkflowExecutionRawHistory, GetWorkflowExecutionRawHistoryV2
  • Replication: ReplicateEventsV2, ReplicateWorkflowState, SyncShardStatus, SyncActivity, StreamWorkflowReplicationMessages (bidirectional streaming)
  • DLQ/task management: GetDLQMessages, PurgeDLQMessages, MergeDLQMessages, GetDLQTasks, DeleteDLQTasks, AddTasks, ListTasks
  • New CHASM operations: CompleteNexusOperation, CompleteNexusOperationChasm, InvokeStateMachineMethod, StartNexusOperation, CancelNexusOperation
  • Activity control: PauseActivity, UnpauseActivity, ResetActivity, UpdateActivityOptions
  • Workflow control: PauseWorkflowExecution, UnpauseWorkflowExecution

MatchingService (api/matchingservice/v1) — ~30 RPCs#

Task queue dispatch and worker management:

  • Core dispatch: AddWorkflowTask, AddActivityTask, PollWorkflowTaskQueue, PollActivityTaskQueue
  • Query: QueryWorkflow, RespondQueryTaskCompleted
  • Nexus: DispatchNexusTask, PollNexusTaskQueue, RespondNexusTaskCompleted, RespondNexusTaskFailed
  • Task queue management: DescribeTaskQueue, DescribeTaskQueuePartition, ListTaskQueuePartitions
  • Worker versioning: UpdateWorkerBuildIdCompatibility, GetWorkerBuildIdCompatibility, UpdateWorkerVersioningRules, GetWorkerVersioningRules
  • Nexus endpoint management: CreateNexusEndpoint, UpdateNexusEndpoint, DeleteNexusEndpoint, ListNexusEndpoints
  • Worker lifecycle: CancelOutstandingPoll, CancelOutstandingWorkerPolls, RecordWorkerHeartbeat, ListWorkers, DescribeWorker
  • Replication: ApplyTaskQueueUserDataReplicationEvent, ReplicateTaskQueueUserData
  • Fairness: UpdateFairnessState

AdminService (api/adminservice/v1) — ~40 RPCs#

Debug and operational tooling, exposed only to admin clients:

  • Internal state inspection: DescribeMutableState, DescribeHistoryHost, GetShard, CloseShard, GetWorkflowExecutionRawHistory*
  • Replication management: GetReplicationMessages, GetNamespaceReplicationMessages, GetDLQReplicationMessages, ResendReplicationTasks, StreamWorkflowReplicationMessages
  • DLQ management: GetDLQMessages, PurgeDLQMessages, MergeDLQMessages, GetDLQTasks, PurgeDLQTasks, MergeDLQTasks, DescribeDLQJob, CancelDLQJob
  • Cluster management: DescribeCluster, ListClusters, ListClusterMembers, AddOrUpdateRemoteCluster, RemoveRemoteCluster
  • Maintenance: RebuildMutableState, ImportWorkflowExecution, RefreshWorkflowTasks, DeleteWorkflowExecution, SyncWorkflowState
  • Admin batch: StartAdminBatchOperation
  • Task queue debug: GetTaskQueueTasks, DescribeTaskQueuePartition, ForceUnloadTaskQueuePartition
  • Queues: AddTasks, ListQueues, ListHistoryTasks, RemoveTask
  • Schedule migration: MigrateSchedule (V1 workflow → V2 CHASM)
  • Health: DeepHealthCheck

Tier 3: CHASM library services (new, in chasm/lib/)#

Proto-defined services for the new CHASM-backed execution model, registered via chasm.Library.RegisterServices(*grpc.Server):

  • SchedulerService (chasm/lib/scheduler): CHASM-based schedule management
  • ActivityService (chasm/lib/activity): CHASM-based activity execution
  • TestService (chasm/lib/tests): Test infrastructure

REST/HTTP API#

  • Router: gorilla/mux as the outer router; grpc-gateway v2 (github.com/grpc-ecosystem/grpc-gateway/v2/runtime.ServeMux) as the inner handler
  • Implementation: HTTPAPIServer (service/frontend/http_api_server.go) listens on a separate port (configurable via rpcConfig.HTTPPort). Requests are bridged to gRPC via an inline client connection (newInlineClientConn) that passes through the full gRPC interceptor chain — no network round-trip.
  • Route registration: Auto-generated from the proto HTTP annotations via grpc-gateway. Routes map 1:1 to WorkflowService and OperatorService methods. The custom Nexus routes and OpenAPI handler take precedence via explicit gorilla/mux registration.
  • Services registered:
    • WorkflowServiceworkflowservice.RegisterWorkflowServiceHandlerClient
    • OperatorServiceoperatorservice.RegisterOperatorServiceHandlerClient
  • Content negotiation: Four marshalers in priority order: indented proto-JSON, compact proto-JSON, indented legacy JSON, compact legacy JSON (all custom temporalProtoMarshaler).
  • TLS: Optional; uses the same TLS config as the gRPC frontend listener.
  • Authentication: Passes through the full gRPC interceptor chain (including auth); the Authorization header is forwarded.

Nexus HTTP API#

Temporal exposes a dedicated HTTP endpoint for Nexus protocol task dispatch (separate from the standard REST gateway):

  • Handler: NexusHTTPHandler (service/frontend/nexus_http_handler.go)
  • SDK: github.com/nexus-rpc/sdk-go/nexus — uses the Nexus SDK’s HTTP handler
  • Routes (via gorilla/mux):
    • /{namespace}/{task-queue}/... — dispatch by namespace + task queue (legacy)
    • /endpoint/{endpoint}/... — dispatch by Nexus endpoint name
  • Protocol: Standard Nexus HTTP protocol. The handler pre-processes requests (endpoint lookup, auth, rate limits) then delegates to the Nexus SDK handler which dispatches to Matching service via DispatchNexusTask.

gRPC Interceptor Chain (Frontend)#

All frontend gRPC requests (both gRPC and REST-via-gateway) pass through this ordered chain:

  1. TelemetryInterceptor — tracing, metrics tagging, request/response logging
  2. ServiceErrorInterceptor — maps internal errors to gRPC status codes
  3. FrontendServiceErrorInterceptor — additional frontend-specific error mapping
  4. HealthInterceptor — rejects requests when service is not healthy
  5. RateLimitInterceptor — global cluster-level rate limiting
  6. NamespaceRateLimitInterceptor — per-namespace rate limiting (configurable via dynamic config)
  7. ConcurrentRequestLimitInterceptor — per-namespace concurrency limits
  8. NamespaceValidatorInterceptor — validates namespace exists and is active
  9. NamespaceHandoverInterceptor — blocks requests during namespace handover (cross-cluster failover)
  10. NamespaceLogInterceptor — structured logging per namespace
  11. BusinessIDInterceptor — extracts workflow/run IDs for structured log context
  12. RedirectionInterceptor — redirects requests to the correct cluster during multi-cluster operation
  13. SDKVersionInterceptor — records SDK version from client headers for metrics
  14. CallerInfoInterceptor — attaches caller identity (name, version, type) to context
  15. MaskInternalErrorDetailsInterceptor — strips internal error details from external responses
  16. SlowRequestLoggerInterceptor — logs requests that exceed a configurable latency threshold
  17. Custom interceptors (from WithChainedFrontendGrpcInterceptors) — appended after built-in chain
  18. RetryableInterceptor — automatic retries for transient errors (last in chain)

Internal services (History, Matching) have a shorter chain: telemetry, service error, health only.


Authentication#

  • Mechanism: Pluggable via WithAuthorizer(authorization.Authorizer) and WithClaimMapper(func(*config.Config) authorization.ClaimMapper) server options
  • Default: JWT-based via go.temporal.io/server/common/authorization. The ClaimMapper extracts claims from the JWT; the Authorizer makes allow/deny decisions per RPC.
  • Audience validation: Configurable via WithAudienceGetter
  • No-auth mode: --allow-no-auth flag required when no authorizer is configured (a safety gate)
  • gRPC metadata: Authorization header is passed through from HTTP to gRPC via header forwarding rules

CLI#

  • Framework: urfave/cli v2
  • Binary: temporal-server (built from cmd/server/main.go)
  • Commands:
CommandDescription
startStart one or more Temporal services
validate-dynamic-configValidate dynamic config YAML file(s) against known keys and types
render-configLoad and render config template to stdout
  • Global flags:

    • --config-file <path> / TEMPORAL_CONFIG_FILE: primary config loading
    • --config <dir>, --env <name>, --zone <name>: legacy config loading (deprecated)
    • --allow-no-auth: permit running without an authorizer
  • start flags:

    • --service <name> (repeatable) / TEMPORAL_SERVICES: services to start (default: all four)

The CLI is minimal by design — Temporal’s operational surface is dominated by the gRPC/REST APIs, not CLI commands. Operators use tctl (a separate tool) or the Temporal Cloud UI for day-to-day operations.


Go Library API (Embedding)#

Temporal can be embedded in Go programs via the temporal package (go.temporal.io/server/temporal), useful for test servers and development environments.

  • Public packages: temporal (top-level embedding API)
  • API style: Functional options pattern

Core interface:

type Server interface {
    Start() error
    Stop() error
}
func NewServer(opts ...ServerOption) (Server, error)

Key ServerOption functions:

FunctionPurpose
WithConfig(*config.Config)Supply pre-loaded config struct
WithConfigLoader(dir, env, zone string)Load config from a directory
WithServerConfigFilePath(path)Load config from a single file
ForServices(names []string)Select which services to start
WithStaticHosts(map)Disable Ringpop; use static addresses
InterruptOn(<-chan any)Block Start() until signal received
WithLogger(log.Logger)Custom logger
WithAuthorizer(authorization.Authorizer)Custom auth plugin
WithClaimMapper(func(*config.Config) ClaimMapper)Custom JWT claim extraction
WithAudienceGetter(func(*config.Config) JWTAudienceMapper)Custom audience validation
WithTLSConfigFactory(TLSConfigProvider)Custom TLS
WithDynamicConfigClient(dynamicconfig.Client)Custom dynamic config backend
WithCustomDataStoreFactory(AbstractDataStoreFactory)Custom persistence backend (experimental)
WithCustomVisibilityStoreFactory(VisibilityStoreFactory)Custom visibility backend
WithCustomHistoryArchiverFactory(...)Custom history archiver
WithCustomVisibilityArchiverFactory(...)Custom visibility archiver
WithClientFactoryProvider(client.FactoryProvider)Custom inter-service client factory
WithSearchAttributesMapper(searchattribute.Mapper)Search attribute alias mapping
WithChainedFrontendGrpcInterceptors(...grpc.UnaryServerInterceptor)Append custom interceptors
WithCustomMetricsHandler(metrics.Handler)Custom metrics sink
WithElasticsearchHttpClient(*http.Client)Custom ES HTTP client
WithPersistenceServiceResolver(resolver.ServiceResolver)Address resolution for DB services

Backward compatibility: No explicit versioning strategy in code, but the ServerOption interface is designed for stability — new options are added as new functions, old code continues to work.


Plugin / Extension System#

Temporal’s extensibility is interface-based, surfaced through the ServerOption embedding API:

Extension PointInterfacePurpose
Authorizationauthorization.AuthorizerAllow/deny per RPC
Claim mappingauthorization.ClaimMapperJWT claim extraction
Persistencepersistenceclient.AbstractDataStoreFactoryCustom storage backend
Visibilityvisibility.VisibilityStoreFactoryCustom search/visibility backend
History archivalprovider.CustomHistoryArchiverFactoryCustom history archive destination
Visibility archivalprovider.CustomVisibilityArchiverFactoryCustom visibility archive destination
Metricsmetrics.HandlerCustom metrics sink (Prometheus, Datadog, etc.)
gRPC interceptorsgrpc.UnaryServerInterceptorCustom middleware in the Frontend chain
Dynamic configdynamicconfig.ClientCustom feature flag / config backend
Search attributessearchattribute.MapperAlias ↔ field name translation

The CHASM subsystem adds a second extension point for new execution model components. chasm.Library implementors (RegisterServices(*grpc.Server)) can contribute new state machine types and gRPC services to the cluster.


Key observations#

  1. Three-tier API architecture: Public client APIs (WorkflowService/OperatorService in external module) → Internal inter-service APIs (HistoryService/MatchingService in this repo) → Admin APIs (AdminService). The external module boundary enforces API stability — the server implements a stable interface it does not own.

  2. REST is a thin transcoding layer: The HTTP API is not a separately maintained REST API; it is mechanically derived from the gRPC proto annotations via grpc-gateway. The inline client connection design means REST requests traverse the full gRPC interceptor chain without a network hop, giving REST and gRPC identical middleware behavior.

  3. Nexus HTTP is a first-class protocol: The Nexus HTTP handler is not a REST wrapper over workflow APIs; it is a separate protocol (the CNCF Nexus spec) for composable async operations. It coexists on the same HTTP port as the REST gateway but has dedicated routing.

  4. The temporal embedding package is a well-designed escape hatch: The functional options API makes it easy to replace any subsystem (persistence, auth, metrics, archival) for testing or custom deployments, without forking the server. This is heavily used by temporalio/temporal-go-tests and testing frameworks.

  5. ~60 public RPCs, ~130 total RPCs across services: The API surface is large but well-organized — public vs. internal vs. admin separation makes the blast radius of any change clear.

  6. API categories via proto options: All RPCs carry an api_category option (API_CATEGORY_STANDARD, API_CATEGORY_LONG_POLL, API_CATEGORY_SYSTEM). This is used for rate limiting — long-poll RPCs and system RPCs get different quota budgets, preventing polling traffic from starving user-initiated calls.