curl -N \
-H "Authorization: Bearer YOUR_API_KEY" \
"https://api.crewship.dev/v1/runs/run_xyz789abc/events"
const response = await fetch('https://api.crewship.dev/v1/runs/run_xyz789abc/events', {
headers: {
Authorization: 'Bearer YOUR_API_KEY',
},
})
const reader = response.body.getReader()
const decoder = new TextDecoder()
let buffer = ''
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('data: ')) {
const event = JSON.parse(line.slice(6))
console.log(event.type, event)
if (['complete', 'run.completed', 'run.failed'].includes(event.type)) {
console.log('Run finished')
return
}
}
}
}
data: {"type":"run.started","data":{"entrypoint":"default"}}
data: {"type":"task.started","data":{"task":"Research AI trends","agent":"Researcher"}}
data: {"type":"log","data":{"message":"Found 15 relevant results"}}
data: {"type":"task.completed","data":{"task":"Research AI trends","agent":"Researcher"}}
data: {"type":"artifact","data":{"name":"report.md"}}
data: {"type":"run.completed","data":{"status":"succeeded"}}
data: {"type":"heartbeat","status":"running"}
data: {"type":"heartbeat","status":"running"}
data: {"type":"complete","status":"succeeded","output":{"result":"Generated report..."},"error":null}
Runs
Stream Events
Stream real-time events from a run using Server-Sent Events (SSE)
GET
/
v1
/
runs
/
{id}
/
events
curl -N \
-H "Authorization: Bearer YOUR_API_KEY" \
"https://api.crewship.dev/v1/runs/run_xyz789abc/events"
const response = await fetch('https://api.crewship.dev/v1/runs/run_xyz789abc/events', {
headers: {
Authorization: 'Bearer YOUR_API_KEY',
},
})
const reader = response.body.getReader()
const decoder = new TextDecoder()
let buffer = ''
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('data: ')) {
const event = JSON.parse(line.slice(6))
console.log(event.type, event)
if (['complete', 'run.completed', 'run.failed'].includes(event.type)) {
console.log('Run finished')
return
}
}
}
}
data: {"type":"run.started","data":{"entrypoint":"default"}}
data: {"type":"task.started","data":{"task":"Research AI trends","agent":"Researcher"}}
data: {"type":"log","data":{"message":"Found 15 relevant results"}}
data: {"type":"task.completed","data":{"task":"Research AI trends","agent":"Researcher"}}
data: {"type":"artifact","data":{"name":"report.md"}}
data: {"type":"run.completed","data":{"status":"succeeded"}}
data: {"type":"heartbeat","status":"running"}
data: {"type":"heartbeat","status":"running"}
data: {"type":"complete","status":"succeeded","output":{"result":"Generated report..."},"error":null}
Path Parameters
string
required
Run ID (e.g.,
run_xyz789abc)Event Format
Events are sent as SSEdata messages with JSON payloads:
data: {"type":"run.started","data":{"entrypoint":"default"}}
data: {"type":"task.started","data":{"task":"Research AI trends","agent":"Researcher"}}
data: {"type":"log","data":{"message":"Found 15 relevant results"}}
Event Types
When the runner machine is reachable, you receive detailed events from the crew execution:| Type | Description |
|---|---|
run.started | Run execution began |
run.completed | Run finished successfully |
run.failed | Run encountered an error |
task.started | A task began execution |
task.completed | A task finished |
agent.action | An agent performed an action |
tool_use | A tool was invoked |
log | Log message from the crew |
artifact | An artifact was produced |
| Type | Description |
|---|---|
heartbeat | Periodic status update while the run is in progress |
complete | Run reached a terminal state (succeeded, failed, canceled) |
error | An error occurred (e.g., run not found) |
timeout | The SSE connection timed out |
curl -N \
-H "Authorization: Bearer YOUR_API_KEY" \
"https://api.crewship.dev/v1/runs/run_xyz789abc/events"
const response = await fetch('https://api.crewship.dev/v1/runs/run_xyz789abc/events', {
headers: {
Authorization: 'Bearer YOUR_API_KEY',
},
})
const reader = response.body.getReader()
const decoder = new TextDecoder()
let buffer = ''
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('data: ')) {
const event = JSON.parse(line.slice(6))
console.log(event.type, event)
if (['complete', 'run.completed', 'run.failed'].includes(event.type)) {
console.log('Run finished')
return
}
}
}
}
data: {"type":"run.started","data":{"entrypoint":"default"}}
data: {"type":"task.started","data":{"task":"Research AI trends","agent":"Researcher"}}
data: {"type":"log","data":{"message":"Found 15 relevant results"}}
data: {"type":"task.completed","data":{"task":"Research AI trends","agent":"Researcher"}}
data: {"type":"artifact","data":{"name":"report.md"}}
data: {"type":"run.completed","data":{"status":"succeeded"}}
data: {"type":"heartbeat","status":"running"}
data: {"type":"heartbeat","status":"running"}
data: {"type":"complete","status":"succeeded","output":{"result":"Generated report..."},"error":null}
Notes
- If the run is already in a terminal state (
succeeded,failed,canceled), a singlecompleteevent is returned immediately - If the runner machine is reachable, events are proxied directly from the machine in real time
- If the machine is not reachable, the API falls back to polling the database every 2 seconds and sending
heartbeatevents - The connection times out after 30 minutes
⌘I