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

# Cancel Run API

> Cancel a running async job

Cancel a running or queued async job. Jobs that have already completed cannot be cancelled.

<ParamField path="job_id" type="string" required>
  The unique job identifier (e.g., `run_abc123`).
</ParamField>

## Response

<ResponseField name="job_id" type="string" required>
  Unique job identifier.
</ResponseField>

<ResponseField name="status" type="string" required>
  Updated job status (`cancelled`).
</ResponseField>

<ResponseField name="cancelled_at" type="string" required>
  ISO 8601 timestamp of cancellation.
</ResponseField>

<RequestExample>
  ```bash cURL theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
  curl -X POST http://127.0.0.1:8005/api/v1/runs/run_abc123/cancel
  ```

  ```python Python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
  import httpx

  job_id = "run_abc123"

  response = httpx.post(f"http://127.0.0.1:8005/api/v1/runs/{job_id}/cancel")

  if response.status_code == 200:
      result = response.json()
      print(f"Job {result['job_id']} cancelled")
  elif response.status_code == 400:
      print("Job already completed, cannot cancel")
  elif response.status_code == 404:
      print("Job not found")
  ```

  ```bash CLI theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
  praisonai run cancel run_abc123

  # JSON output
  praisonai run cancel run_abc123 --json
  ```
</RequestExample>

<ResponseExample>
  ```json 200 OK theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
  {
    "job_id": "run_abc123",
    "status": "cancelled",
    "cancelled_at": "2025-01-01T00:05:00Z"
  }
  ```

  ```json 400 Bad Request (Already Completed) theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
  {
    "detail": "Cannot cancel job with status: succeeded"
  }
  ```

  ```json 404 Not Found theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
  {
    "detail": "Job not found: run_abc123"
  }
  ```
</ResponseExample>

## Cancellation Behavior

* **Queued jobs**: Immediately marked as cancelled, never started
* **Running jobs**: Sent a cancellation signal; may take a moment to stop
* **Completed jobs**: Cannot be cancelled (returns 400 error)

## Example: Submit with Timeout and Cancel

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
import httpx
import time
import threading

API_URL = "http://127.0.0.1:8005"

def submit_with_client_timeout(prompt, timeout_seconds=60):
    # Submit job
    response = httpx.post(f"{API_URL}/api/v1/runs", json={"prompt": prompt})
    job_id = response.json()["job_id"]
    print(f"Submitted job: {job_id}")
    
    start_time = time.time()
    
    while True:
        # Check if we've exceeded our client-side timeout
        if time.time() - start_time > timeout_seconds:
            print(f"Client timeout reached, cancelling job...")
            httpx.post(f"{API_URL}/api/v1/runs/{job_id}/cancel")
            raise TimeoutError(f"Job {job_id} cancelled after {timeout_seconds}s")
        
        status = httpx.get(f"{API_URL}/api/v1/runs/{job_id}").json()
        
        if status["status"] == "succeeded":
            return httpx.get(f"{API_URL}/api/v1/runs/{job_id}/result").json()
        elif status["status"] in ("failed", "cancelled"):
            raise Exception(f"Job {status['status']}")
        
        time.sleep(status.get("retry_after", 2))

try:
    result = submit_with_client_timeout("Complex analysis task", timeout_seconds=30)
    print(f"Result: {result['result']}")
except TimeoutError as e:
    print(f"Timeout: {e}")
```

## Error Responses

| Status | Description                                             |
| ------ | ------------------------------------------------------- |
| `400`  | Job already completed (succeeded, failed, or cancelled) |
| `404`  | Job not found                                           |
| `500`  | Internal server error                                   |

## See Also

* [Get Run Status](/docs/api/praisonai/async-jobs/get-run-status)
* [Submit Run](/docs/api/praisonai/async-jobs/submit-run)
* [Async Jobs Overview](/docs/api/praisonai/async-jobs)
