Skip to content

HTTP Endpoints ​

worlds.HTTPHandler(world, prefix), which every World package wraps as HTTP(world), serves two endpoints under a prefix (default /v1/workflow). It does not execute deliveries.

RouteHandlerPurpose
POST <prefix>/rpcworlds.RPCHandlerCBOR RPC for clients and tools
<prefix>/webhooks/{token}worlds.WebhookHandlerwebhook requests

The Vercel World adds POST <prefix>/callbacks/qstash when QStash is configured. vercelworld.QStash(world) exposes that callback separately. Callback routes under <prefix>/callbacks/ are where a World mounts endpoints specific to it.

RPC ​

The RPC endpoint exposes the World and Client APIs. workflow.NewHTTPClient and the world-http adapter use it.

  • Request: POST with Content-Type: application/cbor (other types get 415), a body of at most 8 MiB:

    { method: string, input: <cbor>, specVersion?: int }
  • Response: 200 with Content-Type: application/cbor, including when the method fails:

    { output?: <cbor>, error?: { code: string, message: string, sentinel?: string } }

    Error codes are not_found, invalid_argument, conflict, cancelled, deadline_exceeded, and internal. sentinel names the worlds sentinel error the failure matches, such as run_not_found, so workflow.NewHTTPClient returns errors that match errors.Is as they would in process.

  • Waits: runs.waitForTerminalStatus and streams.getChunks wait at most 30 seconds per request. Clients repeat the request to wait longer.

  • Spec version: when specVersion is set and differs from the World's (worlds.SpecVersion, currently 1), the request fails with invalid_argument. Clients call client.spec first, which returns { specVersion, capabilities }.

Methods ​

GroupMethods
Worldworld.deploymentId
Runsruns.get, runs.list, runs.waitForTerminalStatus, runs.setAttributes
Stepssteps.get, steps.list
Eventsevents.create, events.createRun, events.createBatch, events.get, events.list, events.listByCorrelationID
Hookshooks.get, hooks.getByToken, hooks.list
Queuequeue.queue, queue.queueBatch, queue.cancel
Streamsstreams.write, streams.createWriteSession, streams.writeSession, streams.closeWriteSession, streams.writeMulti, streams.close, streams.getChunks, streams.getInfo, streams.list
Analyticsanalytics.runs.get, analytics.runs.list, analytics.attributes.list, analytics.steps.get, analytics.steps.list, analytics.events.get, analytics.events.getMany, analytics.events.list, analytics.events.listByCorrelationId, analytics.hooks.get, analytics.hooks.list, analytics.waits.get, analytics.waits.list
Clientclient.spec, client.runs.create, client.runs.cancel, client.runs.wake, client.streams.write, client.streams.writeMulti, client.streams.close, client.hooks.resume

Most methods return the World's Go types. The event writes return the Workflow SDK's result shapes instead: events.create and events.createRun return worlds.RPCEventResult, with the committed event and the run, step, or hook it changed, and events.createBatch returns worlds.RPCEventBatchResult, with one outcome per event. A batch the World refuses without an in-band fence is applied one event at a time, so each event reports its own status. Other batch failures are returned as the request's error. A run created without an ID is given one.

Unauthenticated

The RPC endpoint can start runs, append events, and read every payload. Never expose it publicly unless worlds.WithRPCToken or worlds.WithRPCMiddlewareprotects it.

Webhooks ​

<prefix>/webhooks/{token} resumes the webhook that owns token with the request.

SituationResponse
No active webhook owns the token, or its run finished404 Not Found
Method differs from WebhookOption.Method405 Method Not Allowed with Allow
Body over 128 KiB413 Request Entity Too Large
Default webhook202 Accepted
WebhookOption.Response setthat response
WebhookOption.ManualWaits for a step to call WebhookRequest.RespondWith.
Manual response times out504 Gateway Timeout
Webhook disposed or run terminated while waiting for a response410 Gone
Storage failure while waiting for a response500 Internal Server Error
Ownership changes during the requestRetryable 503 Service Unavailable. The request is not forwarded to the new owner.

The request's method, URL, headers, and body are recorded in a hook_received event and a delivery is queued so the run resumes.

The token is the only authorization. Serve WebhookHandler (or a World's Webhook(world)) publicly on its own if you need webhooks but want to keep RPC private.

Mounting under another path ​

go
mux := http.NewServeMux()
mux.Handle("/v1/workflow/", postgresworld.HTTP(world))
mux.Handle("/", app)

Or with a custom prefix, using the World package's HTTPPrefix (or worlds.HTTPHandler for your own World):

go
handler := postgresworld.HTTPPrefix(world, "/internal/workflow")

Whatever you choose, set the World's Config.BaseURL to the public URL of that prefix so webhook URLs are correct, and pass the same URL to workflow.NewHTTPClient.

Released under the MIT License.