Skip to main content
An invocation is a request to execute a handler. You can invoke handlers over HTTP with or without waiting for a response, and with or without an idempotency key. Make sure to first register the handler you want to invoke. The UI helps you with invoking your services. Open the UI at port 9070, register your service, click on the service, open the playground, and invoke your handlers from there.
Each invocation has its own unique ID and lifecycle. Have a look at managing invocations to learn how to manage the lifecycle of an invocation.

Request-response calls

You can invoke services over HTTP 1.1 or higher. Request/response bodies should be encoded as JSON. Invoke myHandler of MyService as follows:
Invoke myHandler of MyVirtualObject for myObjectKey as follows:
Call the run handler of the MyWorkflow as follows:
A workflow can be submitted only once. Resubmission of the same workflow will fail with “Previously accepted”. The invocation ID can be found in the request header x-restate-id. Follow the same pattern for calling the other handlers of the workflow.
Note that all invocations go first via the Restate Server. The server then forwards the request to the appropriate service. Therefore, localhost:8080 refers to ingress port of the Restate Server, not the service instance.
Restate <= 1.6: Use the path /{service}/{handler} or /{service}/{key}/{handler} instead.

Sending messages

If you do not want to wait for the response, you can send a message by using /restate/send/... instead of /restate/call/...:
Example output:
The response contains the Invocation ID. You can use this identifier to cancel or kill the invocation.
Restate <= 1.6: Use the path /{service}/{handler}/send or /{service}/{key}/{handler}/send instead.

Delayed messages

You can delay the message by adding a delay request parameter in ISO8601 notation or using humantime format:
Restate <= 1.6: Use the path /{service}/{handler}/send?delay= or /{service}/{key}/{handler}/send?delay= instead.

Using an idempotency key

You can send requests to Restate providing an idempotency key, through the Idempotency-Key header:
After the invocation completes, Restate persists the response for a retention period of one day (24 hours). If you re-invoke the service with the same idempotency key within 24 hours, Restate sends back the same response and doesn’t re-execute the request to the service. Check out the service configuration docs to tune the retention time.
With Restate and an idempotency key, you can make any service call idempotent, without any extra code or setup. This is a very powerful feature to ensure that your system stays consistent and doesn’t perform the same operation multiple times.
From Restate 1.7, Restate injects automatically idempotency keys inside the ingress, to enable internal safe retries. You can modify the behavior of this feature with the controlled-idempotent-sharding cluster feature. These idempotency keys will not deduplicate actual requests from ingress, since each call gets a distinct key. To achieve that, you still need to provide the idempotency key yourself in the ingress.

Retrying requests

A client can safely retry the following requests: On failure, Restate sets the x-restate-error-source header, to specify where the error comes from. Its value is one of:
  • invocation: the error comes from your handler, either by throwing or returning a TerminalError/TerminalException, or by killing or cancelling the invocation. You usually don’t want to retry these errors.
  • ingress (or absent): the error comes from the Restate ingress, or from a proxy between Restate and your client. Retry only when the status code signals a transient condition: 408, 425, 429, or any 5xx. Treat any other 4xx response, for example 404 Not Found or 400 Bad Request, as non-retryable.

Scopes

Scopes are part of the flow control feature. Scoped invocations are rejected unless the server is started with the experimental vqueues feature enabled (experimental-enable-vqueues = true).
A scope is an opaque key that assigns an invocation to scope, which Restate uses to apply flow control across invocations that share the same scope. Add a scope/{scopeKey} segment in front of the call or send verb:
For example, to call MyService/myHandler within the scope tenant-a:
To subdivide a scope further, add a limit key with the limit-key query parameter or the x-restate-limit-key header. A limit key has one or two /-separated levels and always requires a scope:
See flow control to learn how to configure concurrency limits for a scope and its limit keys.

Cancel

You can cancel an invocation as follows:
curl

Attach to an invocation

Restate allows you to retrieve the result of workflows and invocations that used an idempotency key. There are two options:
  • To attach to an invocation or workflow and wait for it to finish, use attach.
  • To peek at the output of an invocation or workflow, use output. This will return:
    • {"message":"not ready"} for ongoing invocations
    • The result for finished invocations
    • {"message":"not found"} for non-existing invocations

By invocation ID

If you already have the invocation ID, attach to it or read its output with a GET request:

By target

If you don’t have the invocation ID, send a POST request to /restate/attach or /restate/output with a JSON body describing the workflow or idempotency target. You can also address an invocation by its ID through the same body shape, as an alternative to the GET form above:
Use the same body shape against /restate/output to peek at the result. If the target was invoked within a scope, add the optional "scope" field to the body.

Looking up the invocation ID

To resolve a workflow or idempotency target into its invocation ID, send a POST request to /restate/lookup with the same body shape as above:
The response contains the invocation ID, which you can then pass to the GET attach and output endpoints:

OpenAPI support

Restate exposes for every service an OpenAPI 3.1 definition, to get it:
You can use this definition with any OpenAPI 3.1 compliant tool to generate clients for your service, such as openapi-generator. Depending on the SDKs, the rich input/output JSON schemas are included as well. At the moment, rich schemas are supported for: