curl --request POST \
--url https://api.citadel.example/api/v1/runs/{id}/cancel \
--header 'Authorization: Bearer <token>'const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.citadel.example/api/v1/runs/{id}/cancel', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.citadel.example/api/v1/runs/{id}/cancel"
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, headers=headers)
print(response.text)package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.citadel.example/api/v1/runs/{id}/cancel"
req, _ := http.NewRequest("POST", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}{
"run_id": "0199a3d0-4b5c-7d6e-8f70-8192a3b4c5d6",
"workflow": "Payout",
"network": "mainnet",
"status": "cancelled",
"event": "payout",
"idempotency_key": "payout-982",
"failure_reason": "cancelled through the API",
"started_at": "2026-10-18T12:00:00Z",
"finished_at": "2026-10-18T12:02:10Z",
"outputs": {
"amount": "50000000",
"to": "TC6A9sQD2tCSaR1wcBXZtrvGkFyoLgRHHF"
}
}Cancel a workflow run
Stops a run you started by mistake, while nothing it asked for can be signed yet. The run
ends cancelled, with failure_reason: cancelled through the API, and is unwound the way a
failed run is: what its steps held goes back — a wallet it locked, a provider hold nobody
used — and what it waits for no longer wakes it. A pending approval it asked for closes, so
nobody can approve it any more. The loop iterations and the workflows it called stop with it.
The run.cancelled webhook follows. Cancelling it again answers the same 200.
Otherwise it is 409 not_cancellable, and nothing changes:
- a transaction the run authored has reached
authorized: it is on its way to your signer, and a signature cannot be called back. Follow the run to its end instead; - the run has ended (
completed,failed); - it is executing a step this moment. That lasts a moment: send the same call again;
- it runs inside another run (a loop iteration, a workflow another one called): cancel the run that started it.
A paid step (an energy rental, a screening) already handed to its provider is bought work: it is billed whether or not the run goes on.
It takes no network: the id is enough. Needs the events.write scope — the scope that
starts runs. A key limited to vaults is refused with 403 vault_limited.
curl --request POST \
--url https://api.citadel.example/api/v1/runs/{id}/cancel \
--header 'Authorization: Bearer <token>'const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.citadel.example/api/v1/runs/{id}/cancel', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.citadel.example/api/v1/runs/{id}/cancel"
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, headers=headers)
print(response.text)package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.citadel.example/api/v1/runs/{id}/cancel"
req, _ := http.NewRequest("POST", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}{
"run_id": "0199a3d0-4b5c-7d6e-8f70-8192a3b4c5d6",
"workflow": "Payout",
"network": "mainnet",
"status": "cancelled",
"event": "payout",
"idempotency_key": "payout-982",
"failure_reason": "cancelled through the API",
"started_at": "2026-10-18T12:00:00Z",
"finished_at": "2026-10-18T12:02:10Z",
"outputs": {
"amount": "50000000",
"to": "TC6A9sQD2tCSaR1wcBXZtrvGkFyoLgRHHF"
}
}Authorizations
An API key minted in the console (ctd_…). Authenticates; never authorizes funds. A key
carries scopes (read, wallets.write, transactions.write, events.write,
webhooks.write, policy.write) and may be limited to vaults, to IP addresses, and in
lifetime — see Authentication.
Path Parameters
Response
Cancelled — now, or by an earlier call. The run, the body GET /runs/{id} reads.
The network the data lives on. Required wherever it appears in a request — there is no
default network. One your installation does not serve: 422 network_not_served.
mainnet, testnet running, waiting, completed, failed, cancelled The name of the POST /events/{name} call that started the run, as the workflow listens on it; null for a run Citadel started (a deposit, a schedule) or another workflow called.
That call's idempotency key; null when it sent none, or when Citadel started the run.
What the steps produced.