> ## 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.

# Async Code Execution with Webhooks

> Execute very long-running code and receive results via webhook callback using the HopX VM Agent API. Run code asynchronously for long-running tasks and receive execution results via webhook when complete. Learn how to use POST /execute/async endpoint with webhook configuration. Includes request examples and webhook setup.

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

```
POST /execute/async
```

## Request

### Headers

```
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

```bash theme={null}
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)

```json theme={null}
{
  "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

```json theme={null}
{
  "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"
}
```

### Callback Headers

| 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

```python theme={null}
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

```javascript theme={null}
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

```bash theme={null}
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

```bash theme={null}
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
  }'
```

### Custom Callback Headers

```bash theme={null}
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"
    }
  }'
```

## Related

* **[Async Execution with Webhooks](/core-concepts/code-execution/async-webhooks)** - Learn about async execution
* **[Background Execution](/api/vm-agent/execute-background)** - Shorter background tasks
* **[List Processes](/api/vm-agent/list-processes)** - Check process status
* **SDK**: [sandbox.run\_code\_async()](/sdk/python/sandbox#run_code_async) - Python SDK method
* [CLI Code Execution](/cli/commands/run) - Execute code from CLI

## Next Steps

* **[Background Execution](/api/vm-agent/execute-background)** - Shorter background tasks
* **[List Processes](/api/vm-agent/list-processes)** - Check process status
* **[Execute Code](/api/vm-agent/execute)** - Simple synchronous execution
