Skip to main content

Dapr APIs

Catalyst's data plane speaks the same API surface as Dapr, the open-source distributed application runtime. Your application calls a small set of standard HTTP and gRPC endpoints (for example, /v1.0/state, /v1.0/publish, /v1.0/invoke), and the runtime handles the rest: routing to the right backend, applying identity and policies, retrying transient failures, emitting telemetry for Observability, and rotating mTLS certificates. The collection of those endpoints is what Dapr calls building blocks, and what this page calls the Dapr APIs.

Each API is implemented by a component: a YAML resource that names a backend and configures how to reach it. The application code is identical whether that component points at a Catalyst-managed store or your own infrastructure. Swapping a Redis component for a Postgres one, or a managed broker for Kafka, is a configuration change, not a code change. That decoupling is the central design idea you should carry forward from this page.

The API surface vs the SDK surface

There are two layers to be aware of when you build against Catalyst, and confusing them is a common source of friction.

The API surface is the set of stable HTTP and gRPC routes your application talks to. They look like POST /v1.0/state/{storeName}, POST /v1.0/publish/{pubsubName}/{topic}, POST /v1.0/invoke/{appId}/method/{methodName}. In a self-hosted Dapr setup this surface is exposed by a sidecar running alongside your app on localhost. In Catalyst it's exposed by the Catalyst data plane, reached over a TLS-secured connection from your application to the platform. The shape of the routes (paths, payloads, status codes) is identical in both. Your code is portable in both directions.

The SDK surface is the language-idiomatic wrapper around those routes: the official Dapr clients for Python, .NET, Go, Java, and JavaScript. SDKs do not add functionality; they exist so you can write await client.save_state(...) instead of constructing an HTTP request by hand, and so workflow and actor code can look like ordinary classes and async functions in your language. If no SDK fits your stack (say you're calling from a shell script or a language without an official client), calling the HTTP API directly is fully supported and produces the same result.

Per-language SDK guides live under Develop with the Dapr APIs. The raw HTTP API reference is auto-generated at Catalyst APIs.

How a call flows

Your app calls a method on a Dapr SDK, the SDK issues an HTTP or gRPC request to the Catalyst data plane, the data plane resolves the named component, and the component drives the underlying backend, whether that's your Redis, your Kafka, the LLM provider, or the managed key-value store inside Catalyst. Identity, policy enforcement, retries, and telemetry happen at the data-plane step. Your application code stays unaware of any of it.

The building-block catalogue

Catalyst exposes the following APIs today. Each row links to the Develop guide for SDK-level usage, and the Managed column shows whether Catalyst can provision the backing infrastructure for you or whether you supply your own.

APIWhat it doesManaged optionDevelop guide
State managementRead, write, query, and transact key-value stateCatalyst-managed key-value store (kvstore); 13 BYO backends including Redis, Postgres, DynamoDB, Cosmos DB, MongoDBDevelop with the Dapr APIs
Pub/Sub messagingPublish to topics and subscribe with at-least-once delivery, CloudEvents framing, and dead-letteringCatalyst-managed broker (pubsub); 10 BYO backends including Kafka, RabbitMQ, Pulsar, Azure Service Bus, AWS SNS/SQS, GCP Pub/SubDevelop with the Dapr APIs
Service invocationCall another app by App ID, with mTLS, identity propagation, and resiliency appliedRuntime-native (no component needed)Develop with the Dapr APIs
BindingsTrigger your app from external events (queue messages, blob uploads, cron) and push data out to external systemsBYO only; 12 backends including HTTP, Kafka, Postgres, S3, Azure Blob / Service Bus / Event HubsDevelop with the Dapr APIs
SecretsResolve secret values by name from a secret store, referenced from component YAML or from app codeBYO only; HashiCorp Vault, AWS Secrets Manager, Azure Key VaultManage secrets
ConfigurationRead and subscribe to dynamic configuration values from a configuration store, with change notificationsBYO only; Postgres, RedisDevelop with the Dapr APIs
ConversationUnified API for calling LLM providers with built-in retries and observability. The transport AI agents use under the hood.BYO; Anthropic, OpenAI, AWS Bedrock, Google AI, Mistral, DeepSeek, HuggingFace, OllamaDevelop AI agents
JobsSchedule one-off and recurring work (cron-style triggers and delayed execution) durably, surviving process restartsRuntime-native (backed by the Catalyst Postgres scheduler)Develop with the Dapr APIs
ActorsPer-entity stateful objects with single-threaded execution semantics; useful for modeling per-user, per-device, or per-session stateRequires any state component that supports the actorStateStore capabilityDevelop with the Dapr APIs
WorkflowsDurable orchestrations: the foundation of agents and long-running business processes; covered in depth under WorkflowsCatalyst-managed workflow storeDevelop workflows
Distributed lock (alpha)Mutex-style coordination across instances of the same appBYO; Redis onlyDevelop with the Dapr APIs

A few of these deserve a sentence beyond the table.

Service invocation is the only API where there is nothing for you to configure: there's no component, no backend to point at. Apps in the same Catalyst project reach each other by App ID, and the data plane handles discovery, mTLS, and resiliency. That makes it the cheapest way to break a system into multiple deployable units without inheriting service-mesh complexity.

Bindings are bidirectional but the two directions feel different. An input binding hooks an external event source (such as an S3 bucket, a queue, or a cron schedule) up to a callback in your app, so you write a handler and Catalyst invokes it when the event fires. An output binding lets you call a method like "post to this webhook" or "write to this queue" without learning each backend's SDK.

Actors sit on top of the state API. The Dapr actor runtime needs a state store flagged as actorStateStore: true (any of the supported state components can play that role), and the placement service that Catalyst runs takes care of distributing actor instances across your app's replicas. Actors and Workflows are both built on durable state. Actors are the right choice when you need per-entity locking and timers; workflows are the right choice when you need a long-running, multi-step orchestration. See Durable execution for the underlying mechanics.

Conversation looks like a special case but isn't. It's a Dapr building block like any other, with provider-specific components in place of state stores or brokers. Your code targets a single converse operation; the component decides whether you're hitting OpenAI, Bedrock, Anthropic, or a local Ollama instance.

Managed services vs bring your own

Every API in the catalogue above is backed by a component, and you choose where the backing infrastructure lives.

Catalyst-managed services are component implementations that point at infrastructure Catalyst provisions and runs for you inside the project boundary. Today three building blocks have a managed option:

  • State: the managed key-value store (kvstore)
  • Pub/Sub: the managed broker (pubsub)
  • Workflow: the managed workflow store

Managed services exist so you can start building immediately without standing up Redis or Kafka or Postgres. They're sized for development and getting-started workloads. Each managed resource carries a storage cap and per-project quotas detailed in Plans and support. Production traffic typically outgrows them.

Bring your own means you author a component that points at your own infrastructure (your Redis cluster, your Kafka brokers, your Vault, your LLM provider, your Postgres). This is required for any building block without a managed option (bindings, secrets, configuration, conversation, distributed lock, actors), and it's the recommended pattern for state and pub/sub in production. You retain full control over capacity, retention, encryption, and provider choice.

Because the component sits between your code and the backend, switching between managed and BYO (or between two BYO backends) is a YAML change. Application code never moves. See Managed services for the full list of what's provisioned and the boundaries Catalyst enforces around it.

Choosing the right API

The same job can often be done several ways — Workflow versus Actors plus Jobs, Service invocation versus Pub/Sub, and so on. When two APIs both fit, prefer the higher-level one: it encodes the failure-handling rules you'd otherwise write yourself. For a full decision guide keyed by the job you're trying to do, see Choosing the right Dapr API.

Tunables and limits

Several categories of limit apply to traffic crossing the Catalyst data plane. These are quoted at the project and managed-resource level; exact numbers and the latest values live in Plans and support.

  • Per-project quotas: number of projects, App IDs, components, and subscriptions you can create.
  • Managed resource caps: storage size for the managed key-value store, broker, and workflow store.
  • Request sizing: maximum request body size and per-request timeout for data-plane calls.
  • Throughput: per-App ID request rate and per-project daily volume.
  • Data retention: how long metrics and logs are kept before rolling off.

If you expect to brush against any of these, switch the relevant API from the managed option to a BYO component. Your own Redis, Kafka, or Postgres lifts the per-resource caps and shifts retention to your operational control.

Dapr OSS features not currently in Catalyst

Two Dapr open source features are not exposed in Catalyst today: the Cryptography building block (encrypt/decrypt operations against a key vault), and the rate limiting HTTP middleware. If you have a use case that depends on either, raise it with Diagrid support.

See also