---
title: "Client"
description: "A Client is how your application talks to Dex from outside a Worker. An HTTP"
canonical_url: "https://docs.superdurable.io/concepts/client/"
source: "docs/content/concepts/client.mdx"
locale: "en"
---

# Client

A **Client** is how your application talks to Dex from outside a Worker. An HTTP
handler, a background job, or a script uses it. The Client sends requests to
Dex Server. It does not run Flow code. Workers do that.

## When to use a Client

Use a Client at the boundary between your application and its Flows:

- <a id="start-a-flow"></a>**Start** a Flow when a request begins a business
  process. See [Start a Flow](https://docs.superdurable.io/reference/server/runtime-client.md#start-a-flow).
- <a id="invoke-an-rpc"></a><a id="read-and-write-flow-state"></a>**Call an RPC**
  to send a command to a Flow, or to read a view that needs Flow logic. See
  [Invoke an RPC](https://docs.superdurable.io/reference/server/runtime-client.md#invoke-an-rpc).
- <a id="read-attributes"></a>**Read Attributes** when you only need stored
  values. See [Read Attributes](https://docs.superdurable.io/reference/server/runtime-client.md#read-attributes).
- **Wait** for a Flow to finish, a Step to complete, or an Attribute to reach a
  value.
- **Search** for Flows by Flow type, status, or indexed Attributes.
- <a id="stop-a-flow"></a>**Operate** a Flow: describe it, stop it, skip a
  Timer, update its configuration, or time travel it. See
  [Stop a Flow](https://docs.superdurable.io/reference/server/runtime-client.md#stop-a-flow).

<a id="related-primitives"></a>

## How it relates to the other Primitives

- [Flow](https://docs.superdurable.io/concepts/flow.md): **StartFlow** creates a Flow run under a **Flow ID** that you
  choose. The Flow ID is the business identity, such as an order number. Dex
  creates the Run ID. Later calls address the Flow by its Flow ID.
- [RPC](https://docs.superdurable.io/concepts/primitives/rpc.md): change a running Flow through RPCs. To change Attribute,
  AttributeMap, Channel, or ChannelMap state, define a typed RPC for each
  command and call it with **InvokeRPC**. Validation, authorization, locks, and
  transactions then stay inside the Flow.
- [Attribute](https://docs.superdurable.io/concepts/primitives/attribute.md): **GetAttributes** reads stored values
  directly from the server. No Worker runs. Use an RPC instead when the read
  needs Flow-side validation, authorization, Channel messages, a derived view,
  or Attribute locks.
- [Step](https://docs.superdurable.io/concepts/step.md): **WaitForStepCompletion** blocks until a Step
  completes. **WaitForAttributeMatch** blocks until an Attribute reaches a
  value. Use them to answer a request only after the Flow has made progress.
  See [Responsive Update](https://docs.superdurable.io/design-patterns/responsive-update.md).
- [Stream](https://docs.superdurable.io/concepts/primitives/stream.md): a Stream carries live updates, such as
  progress, to a UI. It is best effort. Read durable state again when it
  matters.
- Search: **SearchFlows** finds Flows with a search query, such as one on the
  Flow type or an indexed Attribute. **DescribeFlow** reads the status of one
  known Flow ID.

## Guarantees

- When **StartFlow** returns, Dex has stored the Flow. It runs even if your
  process exits.
- **GetAttributes** returns values that Dex saved together, at one point in
  time. It never returns changes that Dex has not saved yet.
- A wait checks the Flow's saved state. It returns when the condition holds, when the
  Flow closes, or when its request timeout expires. A later call waits again
  from the current state.
- A wait is not a final result. Read the Flow result or the business state to
  decide what happened.
- An error that says the Flow is closing does not prove that an earlier request
  succeeded. Read the Flow's stored state before you act again.

## Example

This handler starts a Flow. The query string supplies the Flow ID and the start
input.

**Python**

```python
flow_id = required_query("workflowId")
run_id = await app_state.client.start_flow(
    app_state.client_apis,
    flow_id,
    required_query("keyword"),
    start_options(),
)
return started_flow(flow_id, run_id)
```

Example: [examples/python/dex_examples/primitives/client-apis/controller.py](https://github.com/superdurable/dex/tree/main/examples/python/dex_examples/primitives/client-apis/controller.py)

**Go**

```go
runID, err := controller.client.StartFlow(
	request.Request.Context(),
	controller.flow,
	flowID,
	keyword,
	primitiveStartOptions(),
)
httputil.Respond(request, gin.H{"flowID": flowID, "runID": runID}, err)
```

Example: [examples/go/primitives/client-apis/controller.go](https://github.com/superdurable/dex/tree/main/examples/go/primitives/client-apis/controller.go)

**Java**

```java
final String runId =
        client.startFlow(flow, workflowId, keyword, ExampleFlows.startOptions());
```

Example: [examples/java/src/main/java/io/superdurable/dex/primitives/clientapis/ClientApisController.java](https://github.com/superdurable/dex/tree/main/examples/java/src/main/java/io/superdurable/dex/primitives/clientapis/ClientApisController.java)

**TypeScript**

```typescript
const runId = await client.startFlow(clientApisFlow, workflowId, keyword, startOptions());
response.json({ flowID: workflowId, runID: runId });
```

Example: [examples/typescript/src/primitives/client-apis/controller.ts](https://github.com/superdurable/dex/tree/main/examples/typescript/src/primitives/client-apis/controller.ts)

**Rust**

```rust
let flow = ClientApisFlow::default();
client
    .start_flow(&flow, &flow_id, keyword)
    .map(|run_id| StartResponse { flow_id, run_id })
```

Example: [examples/rust/src/primitives/client_apis/controller.rs](https://github.com/superdurable/dex/tree/main/examples/rust/src/primitives/client_apis/controller.rs)

Run it from the
[examples playground](https://github.com/superdurable/dex/tree/main/examples/playground).
For a Client that waits for a change and then calls a read RPC, see
[Wait for Attribute Match](https://docs.superdurable.io/design-patterns/responsive-update/attribute-match.md).

## Reference

- [Client requests](https://docs.superdurable.io/reference/server/runtime-client.md) describes how the server
  handles each call: Attribute reads, waits, timeouts and limits, search, and
  operator calls.
- [StartFlowOptions](https://docs.superdurable.io/reference/python/start-flow-options.md) covers the start options, such
  as ID reuse and request idempotency.
- [Client](https://docs.superdurable.io/reference/python/client.md) in each SDK reference lists the Client
  calls in that language. The SDK doc comments give their parameters and errors.
