Quickstart

Use the Runtype API to make an authenticated request and run an inline flow.

Before you begin

Before you start, prepare the following:

Test your API key

Verify your API key by requesting your profile. The following TypeScript example sends the request:

TypeScript
1const response = await fetch('https://api.runtype.com/v1/users/profile', {
2 headers: {
3 Authorization: 'Bearer ' + process.env.RUNTYPE_API_KEY,
4 },
5})
6const profile = await response.json()
7console.log(profile)

The following Python example sends the same request:

Python
1import os
2
3import requests
4
5response = requests.get(
6 'https://api.runtype.com/v1/users/profile',
7 headers={'Authorization': 'Bearer ' + os.environ['RUNTYPE_API_KEY']},
8)
9print(response.json())

Set RUNTYPE_API_KEY to your Runtype API key before you run either example.

The following cURL command sends the same request:

cURL
$curl https://api.runtype.com/v1/users/profile \
> -H "Authorization: Bearer YOUR_API_KEY"

Replace YOUR_API_KEY with your Runtype API key before you run the cURL command.

Define and run a flow

Send a POST request to /v1/dispatch with an inline flow definition. Set flowMode and recordMode to virtual to run without creating a persisted flow or record. The following TypeScript example sends the request and reads the Server-Sent Events (SSE) stream:

TypeScript
1const response = await fetch('https://api.runtype.com/v1/dispatch', {
2 method: 'POST',
3 headers: {
4 Authorization: 'Bearer ' + process.env.RUNTYPE_API_KEY,
5 'Content-Type': 'application/json',
6 },
7 body: JSON.stringify({
8 inputs: {
9 customerName: 'Example Organization',
10 topic: 'sales report',
11 },
12 flow: {
13 name: 'Customer Greeting',
14 steps: [
15 {
16 id: 'greeting',
17 name: 'Greeting',
18 type: 'prompt',
19 order: 1,
20 config: {
21 model: 'gpt-5.4-mini',
22 userPrompt: 'Greet {{customerName}} about their {{topic}}.',
23 outputVariable: 'greeting',
24 },
25 },
26 ],
27 },
28 options: {
29 flowMode: 'virtual',
30 recordMode: 'virtual',
31 streamResponse: true,
32 },
33 }),
34})
35
36const reader = response.body?.getReader()
37if (!reader) throw new Error('Response body is empty')
38
39const decoder = new TextDecoder()
40for (;;) {
41 const { done, value } = await reader.read()
42 if (done) break
43 console.log(decoder.decode(value))
44}

The following cURL command sends the same request:

cURL
$curl https://api.runtype.com/v1/dispatch \
> -H "Authorization: Bearer YOUR_API_KEY" \
> -H "Content-Type: application/json" \
> -d '{
> "inputs": {
> "customerName": "Example Organization",
> "topic": "sales report"
> },
> "flow": {
> "name": "Customer Greeting",
> "steps": [
> {
> "id": "greeting",
> "name": "Greeting",
> "type": "prompt",
> "order": 1,
> "config": {
> "model": "gpt-5.4-mini",
> "userPrompt": "Greet {{customerName}} about their {{topic}}.",
> "outputVariable": "greeting"
> }
> }
> ]
> },
> "options": {
> "flowMode": "virtual",
> "recordMode": "virtual",
> "streamResponse": true
> }
> }'

Replace YOUR_API_KEY with your Runtype API key before you run the cURL command.

Use inputs to pass transient variables that templates reference as {{ variableName }}. Use record.metadata when the data must persist with the record.

Read the response

Because streamResponse is true, the dispatch endpoint returns an SSE stream. The output is similar to the following:

SSE stream
event: execution_start
data: {"type":"execution_start","executionId":"exec_abc123","seq":0}
event: step_start
data: {"type":"step_start","executionId":"exec_abc123","seq":1}
event: text_start
data: {"type":"text_start","executionId":"exec_abc123","seq":2,"id":"text_1"}
event: text_delta
data: {"type":"text_delta","executionId":"exec_abc123","seq":3,"delta":"Hello!"}
event: text_complete
data: {"type":"text_complete","executionId":"exec_abc123","seq":4,"id":"text_1"}
event: step_complete
data: {"type":"step_complete","executionId":"exec_abc123","seq":5}
event: execution_complete
data: {"type":"execution_complete","executionId":"exec_abc123","seq":6}

Stream events

The stream uses event names such as execution_start, step_start, text_delta, tool_start, tool_input_complete, and execution_complete. The API reference documents the event fields.

In tool_start and tool_input_complete, the API redacts values injected for protected parameters as [REDACTED]. The hiddenParameterNames field identifies the protected fields. The tool receives the resolved values.

Use the SDK

Use the TypeScript SDK to build and run the same flow. Install the SDK package:

Install the SDK
$npm install @runtypelabs/sdk

The following TypeScript example builds a flow, passes input values, and runs it:

TypeScript
1import { FlowBuilder, RuntypeClient } from '@runtypelabs/sdk'
2
3const client = new RuntypeClient({
4 apiKey: process.env.RUNTYPE_API_KEY,
5})
6
7const result = await new FlowBuilder()
8 .createFlow({ name: 'Customer Greeting' })
9 .withInputs({
10 customerName: 'Alex',
11 accountType: 'premium',
12 })
13 .prompt({
14 name: 'Personalized Greeting',
15 model: 'gpt-5.4',
16 userPrompt: 'Greet {{customerName}} as a {{accountType}} customer.',
17 })
18 .run(client, { streamResponse: true })
19
20const greeting = await result.getResult('Personalized Greeting')
21console.log(greeting)

The withInputs method adds top-level variables that prompts reference as {{variableName}}. Use it for values that change between runs.

Validate before running

Call the validate method with an authenticated client to check an inline flow before running it. The method reports structural issues, undeclared-variable warnings, and model recommendations without creating or running the flow. The following TypeScript example reports validation errors:

TypeScript
1import { FlowBuilder, RuntypeClient } from '@runtypelabs/sdk'
2
3const client = new RuntypeClient({
4 apiKey: process.env.RUNTYPE_API_KEY,
5})
6
7const builder = new FlowBuilder().createFlow({ name: 'Customer Greeting' }).prompt({
8 name: 'Personalized Greeting',
9 model: 'gpt-5.4',
10 userPrompt: 'Create a greeting for {{customerName}}.',
11})
12
13const validation = await builder.validate(client)
14if (!validation.valid) {
15 for (const issue of validation.errors) {
16 console.error(issue.code, issue.message)
17 }
18}

The validate method calls the public validation endpoint and does not consume execution quota. Pass an authenticated client to run account checks for referenced tools, flows, and agents. Check validation.context.accountChecksPerformed to confirm whether those checks ran.

Import an existing product spec

If you have a product definition in JSON, use the Runtype import flow to preview and create it without defining each step. Choose the path that matches your input:

  • Use Importing products for Agent-to-Agent (A2A) cards, raw Full Product Objects (FPOs), or hosted JSON.
  • Use FPO templates to publish reusable FPO definitions with values collected during import.

The import flow supports /now and Deploy to Runtype buttons. It also supports integrations that submit complete product definitions to Runtype.

Next steps

Continue with one of these resources: