Documentation Index
Fetch the complete documentation index at: https://docs.hopx.ai/llms.txt
Use this file to discover all available pages before exploring further.
Execute very long-running code (>5 minutes) and receive results via webhook callback when complete. Perfect for tasks that take hours or need to run independently of your connection.
Endpoint
Request
Authorization: Bearer YOUR_JWT_TOKEN
Content-Type: application/json
Body Parameters
| Parameter | Type | Required | Description |
|---|
code | string | Yes | Code to execute |
callback_url | string | Yes | URL to POST results to when complete |
language | string | No | Language (default: python) |
timeout | integer | No | Max execution time in seconds (default: 3600) |
working_dir | string | No | Working directory |
env | object | No | Environment variables |
callback_headers | object | No | Custom headers for callback request |
callback_signature_secret | string | No | Secret to sign callback payload (HMAC-SHA256) |
Example Request
curl -X POST https://sandbox_abc123xyz.hopx.dev/execute/async \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"code": "import time\nfor i in range(3600):\n if i % 60 == 0:\n print(f\"Progress: {i//60} minutes\")\n time.sleep(1)\nprint(\"Complete!\")",
"callback_url": "https://your-server.com/webhook",
"language": "python",
"timeout": 7200,
"callback_signature_secret": "your-secret-key"
}'
Response
Success (200 OK)
{
"execution_id": "exec_abc123",
"status": "queued",
"callback_url": "https://your-server.com/webhook"
}
Response Fields
| Field | Type | Description |
|---|
execution_id | string | Execution ID for tracking |
status | string | Initial status (queued) |
callback_url | string | Webhook URL that will receive results |
Callback Behavior
When execution completes, the API POSTs results to your callback_url:
Callback Request
POST https://your-server.com/webhook
Content-Type: application/json
X-HopX-Signature: sha256=abc123...
X-HopX-Timestamp: 1706400000
Callback Payload
{
"execution_id": "exec_abc123",
"status": "completed",
"success": true,
"stdout": "Progress: 0 minutes\nProgress: 1 minutes\n...\nComplete!\n",
"stderr": "",
"exit_code": 0,
"execution_time": 3600.5,
"started_at": "2025-01-28T00:00:00Z",
"completed_at": "2025-01-28T01:00:00Z"
}
| Header | Description |
|---|
X-HopX-Signature | HMAC-SHA256 signature of payload (if secret provided) |
X-HopX-Timestamp | Unix timestamp of callback |
| Custom headers | From callback_headers in request |
Status Codes
| Code | Description |
|---|
| 200 | Execution queued |
| 400 | Invalid request (missing callback_url, invalid URL) |
| 401 | Unauthorized |
| 500 | Failed to queue execution |
Verify Webhook Signature
To verify the webhook signature:
Python
import hmac
import hashlib
import json
def verify_webhook(payload_bytes, signature, secret):
"""Verify HMAC-SHA256 signature"""
expected_signature = hmac.new(
secret.encode('utf-8'),
payload_bytes,
hashlib.sha256
).hexdigest()
# Remove 'sha256=' prefix if present
if signature.startswith('sha256='):
signature = signature[7:]
return hmac.compare_digest(signature, expected_signature)
# In your webhook handler
@app.route('/webhook', methods=['POST'])
def webhook():
signature = request.headers.get('X-HopX-Signature')
timestamp = request.headers.get('X-HopX-Timestamp')
payload_bytes = request.get_data()
if not verify_webhook(payload_bytes, signature, 'your-secret-key'):
return 'Invalid signature', 401
data = json.loads(payload_bytes)
print(f"Execution {data['execution_id']}: {data['status']}")
return 'OK', 200
JavaScript
const crypto = require('crypto');
function verifyWebhook(payloadString, signature, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payloadString)
.digest('hex');
// Remove 'sha256=' prefix if present
const actualSignature = signature.startsWith('sha256=')
? signature.slice(7)
: signature;
return crypto.timingSafeEqual(
Buffer.from(actualSignature),
Buffer.from(expectedSignature)
);
}
// In your webhook endpoint
app.post('/webhook', express.raw({type: 'application/json'}), (req, res) => {
const signature = req.headers['x-HopX-signature'];
const timestamp = req.headers['x-HopX-timestamp'];
const payloadString = req.body.toString('utf8');
if (!verifyWebhook(payloadString, signature, 'your-secret-key')) {
return res.status(401).send('Invalid signature');
}
const data = JSON.parse(payloadString);
console.log(`Execution ${data.execution_id}: ${data.status}`);
res.send('OK');
});
Use Cases
Long-Running Model Training
curl -X POST https://sandbox_abc123xyz.hopx.dev/execute/async \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"code": "import tensorflow as tf\nimport time\n\nprint(\"Starting model training...\")\nmodel = tf.keras.Sequential([...])\nmodel.fit(X_train, y_train, epochs=100, batch_size=32)\nmodel.save(\"/workspace/trained_model.h5\")\nprint(\"Training complete!\")",
"callback_url": "https://your-server.com/training-complete",
"language": "python",
"timeout": 14400,
"callback_signature_secret": "your-secret-key"
}'
Batch Data Processing
curl -X POST https://sandbox_abc123xyz.hopx.dev/execute/async \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"code": "import pandas as pd\nimport glob\n\nprint(\"Processing batch files...\")\nall_files = glob.glob(\"/workspace/data/*.csv\")\ndfs = [pd.read_csv(f) for f in all_files]\ncombined = pd.concat(dfs, ignore_index=True)\ncombined.to_csv(\"/workspace/combined_result.csv\")\nprint(f\"Processed {len(all_files)} files\")",
"callback_url": "https://your-server.com/batch-complete",
"language": "python",
"timeout": 7200
}'
curl -X POST https://sandbox_abc123xyz.hopx.dev/execute/async \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"code": "print(\"Task complete\")",
"callback_url": "https://your-server.com/webhook",
"language": "python",
"callback_headers": {
"X-Custom-Header": "my-value",
"X-Task-ID": "task-123"
}
}'
Next Steps