> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cyberun.cloud/llms.txt
> Use this file to discover all available pages before exploring further.

# 快速开始

> 从代码运行第一个工作流 —— 提交任务、跟随完成、获取输出。

本页是从「我已经有 `sk-` 密钥」到「我已经把工作流输出存到本地」
之间最短的一条路径。三次调用：

1. `POST /r/workflows/slug/{slug}/run` —— 提交任务。返回
   `202 Accepted` 和 `task_id`；任务异步执行，所以不要断言为
   `200` 状态码。
2. `GET /r/tasks/{taskId}/events`（SSE）或 `GET /r/tasks/{taskId}`
   （轮询） —— 等待完成。
3. `GET /r/tasks/{taskId}/result` —— 获取下载 URL。

如果还没有 `sk-` 密钥，参见
[生成 API 密钥](/zh/cloud/guides/api-key)。

## 查询工作流

工作流的 `parameters` 数组告诉你 run 请求里需要传哪些键。

```bash theme={null}
curl -s -H "Authorization: Bearer sk-..." \
  https://core.cyberun.cloud/api/v1/r/workflows | jq
```

```bash theme={null}
# 或按 slug 查询，含完整参数定义
curl -s -H "Authorization: Bearer sk-..." \
  https://core.cyberun.cloud/api/v1/r/workflows/slug/text-to-image | jq
```

使用 `slug@version`（例如 `text-to-image@2`）可以锁定到指定的
[工作流快照](/zh/cloud/guides/workflow-snapshots)。

## 端到端：SSE

推荐路径。进入终态后流自动关闭。

<CodeGroup>
  ```python Python theme={null}
  import json, requests

  API_KEY = "sk-..."
  BASE = "https://core.cyberun.cloud/api/v1/r"
  HEADERS = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}

  # 1. 提交
  run = requests.post(
      f"{BASE}/workflows/slug/text-to-image/run",
      headers=HEADERS,
      json={"parameters": {"prompt": "a sunset over mountains, 4k", "steps": 30}},
  ).json()
  task_id = run["task_id"]
  print("task:", task_id)

  # 2. 订阅事件流
  event_type = None
  with requests.get(
      f"{BASE}/tasks/{task_id}/events",
      headers={"Authorization": f"Bearer {API_KEY}"},
      stream=True,
  ) as stream:
      for line in stream.iter_lines(decode_unicode=True):
          if not line:
              continue
          if line.startswith("event:"):
              event_type = line[6:].strip()
          elif line.startswith("data:"):
              data = json.loads(line[5:].strip())
              if event_type == "progress":
                  pct = int(data["progress"] * 100)
                  print(f"  {pct}% ({data.get('step_current')}/{data.get('step_total')})")
              elif event_type in ("completed", "failed", "cancelled"):
                  print(event_type)
                  break

  # 3. 取结果
  result = requests.get(f"{BASE}/tasks/{task_id}/result", headers=HEADERS).json()
  # `download_url` 是单个主输出（代理任务）。云端分发的任务改为填充
  # `download_urls`，这是一个按输出标识符为键的映射。
  urls = [result["download_url"]] if result.get("download_url") else list(result.get("download_urls", {}).values())
  for i, url in enumerate(urls):
      with open(f"output_{i}.png", "wb") as f:
          f.write(requests.get(url).content)
      print(f"saved output_{i}.png")
  ```

  ```bash curl theme={null}
  # 1. 提交
  TASK_ID=$(curl -s -X POST \
    -H "Authorization: Bearer sk-..." \
    -H "Content-Type: application/json" \
    -d '{"parameters":{"prompt":"a sunset over mountains, 4k","steps":30}}' \
    https://core.cyberun.cloud/api/v1/r/workflows/slug/text-to-image/run \
    | jq -r '.task_id')
  echo "task: $TASK_ID"

  # 2. 订阅事件流（看到 `completed` 后按 Ctrl+C）
  curl -N -H "Authorization: Bearer sk-..." \
    https://core.cyberun.cloud/api/v1/r/tasks/$TASK_ID/events

  # 3. 取结果
  curl -s -H "Authorization: Bearer sk-..." \
    https://core.cyberun.cloud/api/v1/r/tasks/$TASK_ID/result | jq
  ```

  ```ts Node.js theme={null}
  const API_KEY = process.env.CYBERUN_KEY!;
  const BASE = 'https://core.cyberun.cloud/api/v1/r';
  const headers = {
  	Authorization: `Bearer ${API_KEY}`,
  	'Content-Type': 'application/json'
  };

  // 1. 提交
  const run = await fetch(`${BASE}/workflows/slug/text-to-image/run`, {
  	method: 'POST',
  	headers,
  	body: JSON.stringify({
  		parameters: { prompt: 'a sunset over mountains, 4k', steps: 30 }
  	})
  }).then((r) => r.json());
  const taskId = run.task_id;
  console.log('task:', taskId);

  // 2. 订阅事件流
  const stream = await fetch(`${BASE}/tasks/${taskId}/events`, {
  	headers: { Authorization: `Bearer ${API_KEY}` }
  });
  const reader = stream.body!.getReader();
  const decoder = new TextDecoder();
  let buffer = '';
  let eventType = '';

  streamLoop: while (true) {
  	const { done, value } = await reader.read();
  	if (done) break;
  	buffer += decoder.decode(value, { stream: true });
  	const lines = buffer.split('\n');
  	buffer = lines.pop() ?? '';

  	for (const line of lines) {
  		if (line.startsWith('event:')) {
  			eventType = line.slice(6).trim();
  		} else if (line.startsWith('data:')) {
  			const data = JSON.parse(line.slice(5).trim());
  			if (eventType === 'progress') {
  				console.log(`  ${Math.round(data.progress * 100)}%`);
  			} else if (eventType === 'completed' || eventType === 'failed' || eventType === 'cancelled') {
  				console.log(eventType);
  				break streamLoop;
  			}
  		}
  	}
  }

  // 3. 取结果
  const result = await fetch(`${BASE}/tasks/${taskId}/result`, { headers }).then((r) => r.json());
  console.log('download:', result.download_url);
  ```
</CodeGroup>

## 端到端：轮询

当 SSE 不方便时使用 —— 受限网络、超时较短的 Serverless 函数、
不需要实时进度的批处理。

```python theme={null}
import time, requests

API_KEY = "sk-..."
BASE = "https://core.cyberun.cloud/api/v1/r"
HEADERS = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}

run = requests.post(
    f"{BASE}/workflows/slug/text-to-image/run",
    headers=HEADERS,
    json={"parameters": {"prompt": "hello"}},
).json()
task_id = run["task_id"]

while True:
    task = requests.get(f"{BASE}/tasks/{task_id}", headers=HEADERS).json()
    print(task["task_status"])
    if task["task_status"] in ("completed", "failed", "cancelled"):
        break
    time.sleep(3)

result = requests.get(f"{BASE}/tasks/{task_id}/result", headers=HEADERS).json()
print(result)
```

## 接下来读什么

<CardGroup cols={2}>
  <Card title="订阅任务事件流（SSE）" icon="radio" href="/zh/api-reference/streaming-events">
    完整的事件类型参考和兜底策略。
  </Card>

  <Card title="上传输入文件" icon="upload" href="/zh/api-reference/file-upload">
    含文件参数的工作流需要从预签名端点拿到 `file_key`。
  </Card>

  <Card title="调用容器服务" icon="container" href="/zh/api-reference/containers">
    访问托管在团队代理上的长时运行服务。
  </Card>

  <Card title="Webhooks" icon="webhook" href="/zh/cloud/guides/webhooks">
    以推送方式接收终态事件，无需保持流式连接或轮询。
  </Card>
</CardGroup>
