Skip to main content
Stream real-time build logs using Server-Sent Events (SSE). Logs are streamed as they are generated during the build process.

Endpoint

GET /v1/templates/build/{build_id}/logs

Request

Headers

Authorization: Bearer your_api_key_here
Accept: text/event-stream

Path Parameters

ParameterTypeRequiredDescription
build_idstring✅ YesBuild job ID returned from build request

Response

Status Code: 200 OK
Content-Type: text/event-stream
The response is a Server-Sent Events (SSE) stream:
event: log
data: {"level": "INFO", "message": "Starting build...", "timestamp": "2025-11-05T22:00:03Z"}

event: log
data: {"level": "INFO", "message": "Installing packages...", "timestamp": "2025-11-05T22:00:05Z"}

event: log
data: {"level": "ERROR", "message": "Package installation failed", "timestamp": "2025-11-05T22:00:10Z"}

event: done
data: {"status": "active"}
Log Event Format: Each log event contains:
{
  "level": "INFO",
  "message": "Log message text",
  "timestamp": "2025-11-05T22:00:03Z"
}
Log Levels:
  • DEBUG - Debug information
  • INFO - Informational messages
  • WARN - Warning messages
  • ERROR - Error messages

Examples

  • cURL
  • Python
  • JavaScript
curl -N -H "Authorization: Bearer hopx_live_..." \
  -H "Accept: text/event-stream" \
  https://api.hopx.dev/v1/templates/build/489/logs
Note: The -N flag disables buffering for real-time streaming.

Complete Example with Status Polling

Combine logs with status polling:
import requests
import json
import time

def stream_build_logs(build_id, api_key):
    """Stream build logs until build completes"""
    url = f"https://api.hopx.dev/v1/templates/build/{build_id}/logs"
    
    response = requests.get(
        url,
        headers={
            "Authorization": f"Bearer {api_key}",
            "Accept": "text/event-stream"
        },
        stream=True
    )
    
    for line in response.iter_lines():
        if line:
            line = line.decode('utf-8')
            if line.startswith('event: '):
                event_type = line[7:]  # Remove 'event: ' prefix
            elif line.startswith('data: '):
                data = json.loads(line[6:])  # Remove 'data: ' prefix
                
                if event_type == 'log':
                    level = data.get('level', 'INFO')
                    message = data.get('message', '')
                    print(f"[{level}] {message}")
                elif event_type == 'done':
                    print(f"✅ Build complete: {data.get('status')}")
                    break

# Usage
stream_build_logs("489", api_key)

Error Responses

404 Not Found - Build ID not found
HTTP/1.1 404 Not Found
Content-Type: application/json

{
  "error": "Build not found",
  "message": "Build ID '489' does not exist"
}
401 Unauthorized - Invalid API key
HTTP/1.1 401 Unauthorized
Content-Type: application/json

{
  "error": "Unauthorized",
  "message": "Invalid API key"
}

Notes

  • Logs are streamed in real-time as they are generated
  • The stream continues until the build completes or fails
  • Use Accept: text/event-stream header for SSE format
  • For HTTP clients that don’t support SSE, the logs are still streamed but may be buffered

Next Steps