Dapr — API Surface#
API types#
Dapr exposes four distinct API surfaces:
- REST/HTTP — the primary app-facing API on port 3500
- gRPC — full parity with HTTP, on port 50001 (external) and a separate internal port for sidecar-to-sidecar communication
- Pluggable component gRPC protocol — an extension system for third-party components
- No CLI —
daprdis 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 viachi.URLParam(r, ...)calls in span attribute handlers. - Route registration: Declarative
[]endpoints.Endpointslices built byconstruct*Endpoints()methods inpkg/api/http/http.go:144–162. EachEndpointstruct carriesMethods,Route,Version,Group,Handler, andSettings.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 onAPP_API_TOKENenv var, applied as a chi middleware globally. - Middleware chain (applied in order,
pkg/api/http/server.go:267–395):CleanPathMiddleware+StripSlashesMiddleware— path normalization- CORS middleware (configurable allowed origins)
- OpenTelemetry HTTP tracing middleware (when sampling rate > 0)
- Prometheus metrics middleware (
diag.DefaultHTTPMonitoring.HTTPMiddleware) - Max body size middleware (configurable)
- User-configured HTTP pipeline middleware (from component YAML
middleware.http.*) - API token auth middleware (when token is set)
Key HTTP endpoints#
| Building Block | Method | Route | Notes |
|---|---|---|---|
| State | GET | /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}/bulk | GetBulkState | |
| POST/PUT | /v1.0/state/{storeName}/transaction | ExecuteStateTransaction | |
| POST/PUT | /v1.0-alpha1/state/{storeName}/query | QueryStateAlpha1 | |
| Pub/Sub | POST/PUT | /v1.0/publish/{pubsubname}/* | PublishEvent |
| POST/PUT | /v1.0-alpha1/publish/bulk/{pubsubname}/* | BulkPublishEventAlpha1 | |
| POST/PUT | /v1.0/publish/bulk/{pubsubname}/* | BulkPublishEvent | |
| Bindings | POST/PUT | /v1.0/bindings/{name} | InvokeOutputBinding |
| Secrets | GET | /v1.0/secrets/{secretStoreName}/{key} | GetSecret |
| GET | /v1.0/secrets/{secretStoreName}/bulk | GetBulkSecret | |
| Actors | POST/PUT | /v1.0/actors/{actorType}/{actorId}/state | TransactSaveState |
| 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 | |
| Configuration | GET | /v1.0/configuration/{storeName} | GetConfiguration |
| GET | /v1.0/configuration/{storeName}/subscribe | SubscribeConfiguration (SSE) | |
| GET | /v1.0/configuration/{storeName}/{key}/unsubscribe | UnsubscribeConfiguration | |
| Workflow | GET | /v1.0/workflows/{workflowComponent}/{instanceID} | GetWorkflow |
| POST | /v1.0/workflows/{workflowComponent}/{workflowName}/start | StartWorkflow | |
| POST | /v1.0/workflows/{workflowComponent}/{instanceID}/terminate | TerminateWorkflow | |
| POST | /v1.0/workflows/{workflowComponent}/{instanceID}/raiseEvent/{eventName} | RaiseEvent | |
| POST | /v1.0/workflows/{workflowComponent}/{instanceID}/pause | PauseWorkflow | |
| POST | /v1.0/workflows/{workflowComponent}/{instanceID}/resume | ResumeWorkflow | |
| POST | /v1.0/workflows/{workflowComponent}/{instanceID}/purge | PurgeWorkflow | |
| Crypto | PUT | /v1.0/crypto/{component-name}/encrypt | EncryptAlpha1 (streaming) |
| PUT | /v1.0/crypto/{component-name}/decrypt | DecryptAlpha1 (streaming) | |
| Subtle Crypto | POST | /v1.0/subtlecrypto/{component-name}/key | SubtleGetKey |
| POST | /v1.0/subtlecrypto/{component-name}/encrypt | SubtleEncrypt | |
| POST | /v1.0/subtlecrypto/{component-name}/decrypt | SubtleDecrypt | |
| Distributed Lock | POST | /v1.0-alpha1/lock/{storeName} | TryLock |
| POST | /v1.0-alpha1/unlock/{storeName} | Unlock | |
| Jobs | POST | /v1.0-alpha1/jobs/{name} | ScheduleJob |
| GET | /v1.0-alpha1/jobs/{name} | GetJob | |
| DELETE | /v1.0-alpha1/jobs/{name} | DeleteJob | |
| Conversation | POST | /v1.0-alpha1/conversation/{llmName}/converse | ConverseAlpha1 (LLM) |
| Direct Messaging | ANY | /v1.0/invoke/{id}/method/{method:.*} | InvokeService |
| Metadata | GET | /v1.0/metadata | GetMetadata |
| PUT | /v1.0/metadata/{key} | SetMetadata | |
| Health | GET | /v1.0/healthz | Healthz (liveness) |
| GET | /v1.0/healthz/outbound | OutboundHealthz | |
| Shutdown | POST | /v1.0/shutdown | Shutdown |
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— mainDaprservice (all building-block RPCs)appcallback.proto—AppCallbackandAppCallbackAlphaservices (Dapr calls the app)actors.proto,pubsub.proto,workflow.proto,jobs.proto,ai.proto(message types)placement/v1/placement.proto— placement protocolsentry/v1/sentry.proto— CA certificate issuancescheduler/v1/scheduler.proto— job scheduling protocolcomponents/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: ShutdownAppCallback 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() → HealthCheckResponsegRPC interceptors#
Registered in pkg/api/grpc/server.go:282–329 as a chain using grpc-ecosystem/go-grpc-middleware:
metadata.SetMetadataInContextUnary— propagates gRPC metadata into context- OTel tracing interceptors (unary + stream, when enabled)
- Prometheus metrics interceptors (unary + stream)
- 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#
| Binary | Proto Service | Purpose |
|---|---|---|
placement | PlacementService | Actor hash ring distribution via bidirectional stream |
sentry | CA | X.509 certificate issuance (SignCertificate RPC) |
scheduler | Scheduler | Job scheduling, streaming triggers to daprd |
operator | Operator service | Config/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, Pingdaprd 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)#
| Flag | Default | Purpose |
|---|---|---|
--app-id | required | SPIFFE identity and service discovery name |
--mode | standalone | Runtime mode: standalone or kubernetes |
--app-port | — | Port the app listens on |
--app-protocol | http | Protocol to app: http, https, grpc, grpcs, h2c |
--dapr-http-port | 3500 | HTTP API port |
--dapr-grpc-port | 50001 | gRPC API port |
--dapr-internal-grpc-port | dynamic | Sidecar-to-sidecar gRPC port |
--sentry-address | — | Sentry CA address for mTLS |
--control-plane-address | — | Operator address (k8s mode) |
--enable-mtls | false | Enable mTLS between sidecars |
--resources-path | — | Component YAML directory (standalone) |
--app-max-concurrency | -1 | Max concurrent calls to app |
--enable-api-logging | false | Enable 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 settingssentry— CA backend (Kubernetes secrets, Vault), trust domain, cert TTLscheduler— etcd endpoints or embedded etcd mode, replication factoroperator— watch namespace, leader election, watchdog intervalinjector— webhook TLS, sidecar image, allowed service accounts