Dapr — API Surface#

API types#

Dapr exposes four distinct API surfaces:

  1. REST/HTTP — the primary app-facing API on port 3500
  2. gRPC — full parity with HTTP, on port 50001 (external) and a separate internal port for sidecar-to-sidecar communication
  3. Pluggable component gRPC protocol — an extension system for third-party components
  4. No CLIdaprd is not a user-facing CLI tool; it is configured entirely via flags injected by the Kubernetes admission webhook or dapr CLI wrapper

REST/HTTP API#

  • Router: go-chi/chi (v5). Confirmed via chi.URLParam(r, ...) calls in span attribute handlers.
  • Route registration: Declarative []endpoints.Endpoint slices built by construct*Endpoints() methods in pkg/api/http/http.go:144–162. Each Endpoint struct carries Methods, Route, Version, Group, Handler, and Settings.Name. The router registers them all at startup.
  • Versioning: Three version prefixes active simultaneously:
    • /v1.0/ — stable GA endpoints
    • /v1.0-alpha1/ — preview endpoints (jobs, lock, query-state, bulk-publish, workflow, conversation)
    • /v1.0-beta1/ — intermediate stability (workflow)
  • Authentication: Optional API token auth (APITokenAuthMiddleware) keyed on APP_API_TOKEN env var, applied as a chi middleware globally.
  • Middleware chain (applied in order, pkg/api/http/server.go:267–395):
    1. CleanPathMiddleware + StripSlashesMiddleware — path normalization
    2. CORS middleware (configurable allowed origins)
    3. OpenTelemetry HTTP tracing middleware (when sampling rate > 0)
    4. Prometheus metrics middleware (diag.DefaultHTTPMonitoring.HTTPMiddleware)
    5. Max body size middleware (configurable)
    6. User-configured HTTP pipeline middleware (from component YAML middleware.http.*)
    7. API token auth middleware (when token is set)

Key HTTP endpoints#

Building BlockMethodRouteNotes
StateGET/v1.0/state/{storeName}/{key}GetState
POST/PUT/v1.0/state/{storeName}SaveState (bulk array body)
DELETE/v1.0/state/{storeName}/{key}DeleteState
POST/PUT/v1.0/state/{storeName}/bulkGetBulkState
POST/PUT/v1.0/state/{storeName}/transactionExecuteStateTransaction
POST/PUT/v1.0-alpha1/state/{storeName}/queryQueryStateAlpha1
Pub/SubPOST/PUT/v1.0/publish/{pubsubname}/*PublishEvent
POST/PUT/v1.0-alpha1/publish/bulk/{pubsubname}/*BulkPublishEventAlpha1
POST/PUT/v1.0/publish/bulk/{pubsubname}/*BulkPublishEvent
BindingsPOST/PUT/v1.0/bindings/{name}InvokeOutputBinding
SecretsGET/v1.0/secrets/{secretStoreName}/{key}GetSecret
GET/v1.0/secrets/{secretStoreName}/bulkGetBulkSecret
ActorsPOST/PUT/v1.0/actors/{actorType}/{actorId}/stateTransactSaveState
GET/v1.0/actors/{actorType}/{actorId}/state/{key}GetActorState
ANY/v1.0/actors/{actorType}/{actorId}/method/{method}InvokeMethod
POST/PUT/v1.0/actors/{actorType}/{actorId}/reminders/{name}RegisterReminder
DELETE/v1.0/actors/{actorType}/{actorId}/reminders/{name}UnregisterReminder
GET/v1.0/actors/{actorType}/{actorId}/reminders/{name}GetReminder
POST/PUT/v1.0/actors/{actorType}/{actorId}/timers/{name}RegisterTimer
DELETE/v1.0/actors/{actorType}/{actorId}/timers/{name}UnregisterTimer
ConfigurationGET/v1.0/configuration/{storeName}GetConfiguration
GET/v1.0/configuration/{storeName}/subscribeSubscribeConfiguration (SSE)
GET/v1.0/configuration/{storeName}/{key}/unsubscribeUnsubscribeConfiguration
WorkflowGET/v1.0/workflows/{workflowComponent}/{instanceID}GetWorkflow
POST/v1.0/workflows/{workflowComponent}/{workflowName}/startStartWorkflow
POST/v1.0/workflows/{workflowComponent}/{instanceID}/terminateTerminateWorkflow
POST/v1.0/workflows/{workflowComponent}/{instanceID}/raiseEvent/{eventName}RaiseEvent
POST/v1.0/workflows/{workflowComponent}/{instanceID}/pausePauseWorkflow
POST/v1.0/workflows/{workflowComponent}/{instanceID}/resumeResumeWorkflow
POST/v1.0/workflows/{workflowComponent}/{instanceID}/purgePurgeWorkflow
CryptoPUT/v1.0/crypto/{component-name}/encryptEncryptAlpha1 (streaming)
PUT/v1.0/crypto/{component-name}/decryptDecryptAlpha1 (streaming)
Subtle CryptoPOST/v1.0/subtlecrypto/{component-name}/keySubtleGetKey
POST/v1.0/subtlecrypto/{component-name}/encryptSubtleEncrypt
POST/v1.0/subtlecrypto/{component-name}/decryptSubtleDecrypt
Distributed LockPOST/v1.0-alpha1/lock/{storeName}TryLock
POST/v1.0-alpha1/unlock/{storeName}Unlock
JobsPOST/v1.0-alpha1/jobs/{name}ScheduleJob
GET/v1.0-alpha1/jobs/{name}GetJob
DELETE/v1.0-alpha1/jobs/{name}DeleteJob
ConversationPOST/v1.0-alpha1/conversation/{llmName}/converseConverseAlpha1 (LLM)
Direct MessagingANY/v1.0/invoke/{id}/method/{method:.*}InvokeService
MetadataGET/v1.0/metadataGetMetadata
PUT/v1.0/metadata/{key}SetMetadata
HealthGET/v1.0/healthzHealthz (liveness)
GET/v1.0/healthz/outboundOutboundHealthz
ShutdownPOST/v1.0/shutdownShutdown

Public-facing subset (no auth required): metadata and health endpoints only.


gRPC API#

  • Proto files: dapr/proto/runtime/v1/ — split across multiple files by concern:
    • dapr.proto — main Dapr service (all building-block RPCs)
    • appcallback.protoAppCallback and AppCallbackAlpha services (Dapr calls the app)
    • actors.proto, pubsub.proto, workflow.proto, jobs.proto, ai.proto (message types)
    • placement/v1/placement.proto — placement protocol
    • sentry/v1/sentry.proto — CA certificate issuance
    • scheduler/v1/scheduler.proto — job scheduling protocol
    • components/v1/ — pluggable component interfaces (state, pubsub, bindings, secretstore)

Main Dapr service (~50 RPCs)#

State:          GetState, GetBulkState, SaveState, DeleteState, DeleteBulkState,
                ExecuteStateTransaction, QueryStateAlpha1
Pub/Sub:        PublishEvent, BulkPublishEvent, BulkPublishEventAlpha1 (deprecated),
                SubscribeTopicEventsAlpha1 (bidirectional stream)
Bindings:       InvokeBinding
Secrets:        GetSecret, GetBulkSecret
Actors:         GetActorState, ExecuteActorStateTransaction, InvokeActor,
                RegisterActorTimer, UnregisterActorTimer,
                RegisterActorReminder, UnregisterActorReminder, GetActorReminder,
                UnregisterActorRemindersByType, ListActorReminders
Configuration:  GetConfiguration, GetConfigurationAlpha1,
                SubscribeConfiguration, SubscribeConfigurationAlpha1 (server stream),
                UnsubscribeConfiguration, UnsubscribeConfigurationAlpha1
Distributed Lock: TryLockAlpha1, UnlockAlpha1
Crypto:         EncryptAlpha1, DecryptAlpha1 (client/server streams)
                SubtleGetKeyAlpha1, SubtleEncryptAlpha1, SubtleDecryptAlpha1,
                SubtleWrapKeyAlpha1, SubtleUnwrapKeyAlpha1,
                SubtleSignAlpha1, SubtleVerifyAlpha1
Workflow:       StartWorkflowAlpha1/Beta1, GetWorkflowAlpha1/Beta1,
                PurgeWorkflowAlpha1/Beta1, TerminateWorkflowAlpha1/Beta1,
                PauseWorkflowAlpha1/Beta1, ResumeWorkflowAlpha1/Beta1,
                RaiseEventWorkflowAlpha1/Beta1
Jobs:           ScheduleJobAlpha1, GetJobAlpha1, DeleteJobAlpha1,
                DeleteJobsByPrefixAlpha1, ListJobsAlpha1
Conversation:   ConverseAlpha1, ConverseAlpha2 (LLM)
Direct Invoke:  InvokeService (deprecated; use proxy mode)
Metadata:       GetMetadata, SetMetadata
Shutdown:       Shutdown

AppCallback service (Dapr → App)#

The app must implement this service if it uses gRPC protocol:

OnInvoke(InvokeRequest) → InvokeResponse          — service-to-service invocation
ListTopicSubscriptions() → ListTopicSubscriptionsResponse
OnTopicEvent(TopicEventRequest) → TopicEventResponse
OnBulkTopicEvent(TopicEventBulkRequest) → TopicEventBulkResponse
ListInputBindings() → ListInputBindingsResponse
OnBindingEvent(BindingEventRequest) → BindingEventResponse
OnJobEventAlpha1(JobEventRequest) → JobEventResponse
HealthCheck() → HealthCheckResponse

gRPC interceptors#

Registered in pkg/api/grpc/server.go:282–329 as a chain using grpc-ecosystem/go-grpc-middleware:

  1. metadata.SetMetadataInContextUnary — propagates gRPC metadata into context
  2. OTel tracing interceptors (unary + stream, when enabled)
  3. Prometheus metrics interceptors (unary + stream)
  4. API token auth interceptors (unary + stream, when token is set)

Internal gRPC service (sidecar-to-sidecar)#

A separate server (port configurable, default dynamic) runs ServiceInvocation from dapr/proto/internals/v1/. This handles actor routing and direct service invocation between daprd instances, protected by mTLS.

Control plane gRPC services#

BinaryProto ServicePurpose
placementPlacementServiceActor hash ring distribution via bidirectional stream
sentryCAX.509 certificate issuance (SignCertificate RPC)
schedulerSchedulerJob scheduling, streaming triggers to daprd
operatorOperator serviceConfig/component CRD streaming to daprd

Plugin / Extension system#

Pluggable components via gRPC#

The most significant extensibility mechanism is the pluggable component protocol defined in dapr/proto/components/v1/. Third-party components implement a gRPC server that speaks:

StateStore service:      Init, Features, Delete, Get, Set, Ping, BulkDelete, BulkGet, BulkSet
TransactionalStateStore: Transact
QueriableStateStore:     Query
PubSub service:          Init, Features, Subscribe, Publish, BulkSubscribe, BulkPublish, Ping
InputBinding service:    Init, Ping, Read
OutputBinding service:   Init, Ping, Invoke, ListOperations
SecretStore service:     Init, Features, Get, BulkGet, Ping

daprd discovers these via Unix domain socket (in Kubernetes) or TCP. This allows components written in any language (not just Go) to be plugged in — a Python Redis extension, a Rust S3 binding, etc. The components-contrib built-in components use the same interface internally but are linked in at compile time via the registry.

HTTP middleware pipeline#

Users declare middleware.http.* components in their component YAML. These are loaded by the Processor at runtime and assembled into a middleware.HTTP chain that is inserted into the chi router as a middleware group (r.Use(s.middleware)). Extension points: rate limiting, OAuth2, Bearer JWT, Sentinel, WASM custom middleware.

Built-in component registry#

cmd/daprd/components/ uses blank imports to register all components-contrib implementations into typed registries (pkg/components/state, pkg/components/pubsub, etc.). The DAPR_SIDECAR_FLAVOR build tag selects allcomponents.go vs stablecomponents.go, producing different binary sizes.


CLI (flag-based, not user-facing)#

Dapr’s binaries do not use Cobra. All use spf13/pflag with binary-specific FlagSet objects:

daprd flags (partial, cmd/daprd/options/options.go)#

FlagDefaultPurpose
--app-idrequiredSPIFFE identity and service discovery name
--modestandaloneRuntime mode: standalone or kubernetes
--app-portPort the app listens on
--app-protocolhttpProtocol to app: http, https, grpc, grpcs, h2c
--dapr-http-port3500HTTP API port
--dapr-grpc-port50001gRPC API port
--dapr-internal-grpc-portdynamicSidecar-to-sidecar gRPC port
--sentry-addressSentry CA address for mTLS
--control-plane-addressOperator address (k8s mode)
--enable-mtlsfalseEnable mTLS between sidecars
--resources-pathComponent YAML directory (standalone)
--app-max-concurrency-1Max concurrent calls to app
--enable-api-loggingfalseEnable per-request API audit logging

In Kubernetes, these flags are injected by the injector admission webhook — users never type them.

Other binaries#

  • placement — HA mode, Raft port, initial cluster, TLS settings
  • sentry — CA backend (Kubernetes secrets, Vault), trust domain, cert TTL
  • scheduler — etcd endpoints or embedded etcd mode, replication factor
  • operator — watch namespace, leader election, watchdog interval
  • injector — webhook TLS, sidecar image, allowed service accounts