curl --request POST \
--url https://api.example.com/api/interactions/{interaction_id}/cancel \
--header 'x-api-key: <api-key>'import requests
url = "https://api.example.com/api/interactions/{interaction_id}/cancel"
headers = {"x-api-key": "<api-key>"}
response = requests.post(url, headers=headers)
print(response.text)const options = {method: 'POST', headers: {'x-api-key': '<api-key>'}};
fetch('https://api.example.com/api/interactions/{interaction_id}/cancel', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/api/interactions/{interaction_id}/cancel",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_HTTPHEADER => [
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/api/interactions/{interaction_id}/cancel"
req, _ := http.NewRequest("POST", url, nil)
req.Header.Add("x-api-key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.example.com/api/interactions/{interaction_id}/cancel")
.header("x-api-key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/api/interactions/{interaction_id}/cancel")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"data": {
"interaction_id": "<string>",
"status": "<string>"
}
}{
"error": "<string>",
"code": "<string>"
}{
"error": "<string>",
"code": "<string>"
}{
"error": "<string>",
"code": "<string>"
}{
"error": "<string>",
"code": "<string>"
}Cancel a pending interaction
Cancel a pending interaction — WITHDRAW one specific ask without answering or deleting its thread.
The mirror of answer_interaction for the terminal-without-an-answer case: it
takes the pending question’s whole run down through the status-gated kill seam
(kill_park) — every open ask of the run, nested runs and the callers waiting on it —
so NO continuation fires — nothing of the run is resumed — and the removed event
rides tagged reason="cancelled" so a live operator surface tells a deliberate
withdrawal apart from a timeout/expiry removal. A door that started the run is delivered
the withdrawn terminal: nothing is said to the person.
Status-gated exactly like the answer door: only a PENDING (or parked) question cancels.
A question already answered (its state retained) is a loud 409 conflict; a
question whose state is GONE — expired, already cancelled, or never existed (all
leave no distinguishable tombstone, the same limit the answer door has) — is a 404.
Idempotent at the store seam: the teardown re-run on a withdrawn question is a
clean no-op, so a re-cancel simply reports the question gone (404) rather than
double-tearing anything down. It is a TEARDOWN door, so unlike the user-facing answer
door it accepts a CALLER ask (to="caller") as well as a user ask, and unlike the
answer door it is answer-format-AGNOSTIC: an EXTERNAL ask is a pending ask an operator
may withdraw, so it is cancellable too.
The teardown withdraws the channel delivery through the delivering channel’s withdraw
member, so the channel’s hold on the person’s address is released and that address is free
for the next ask when this door returns; the rest of the run’s takedown is durable and
finishes behind the door. The question already sent stays on the medium: a
participant who still answers it reaches the callback door, finds the state gone and gets a
404, which the inbound ladder maps to a fresh bridged turn.
Audience gate identical to answer_interaction (after the existence/status guards):
a question’s audience identity OR any unrestricted caller (the operator can always
withdraw a stuck question) may cancel; every other restricted caller is a loud 403.
curl --request POST \
--url https://api.example.com/api/interactions/{interaction_id}/cancel \
--header 'x-api-key: <api-key>'import requests
url = "https://api.example.com/api/interactions/{interaction_id}/cancel"
headers = {"x-api-key": "<api-key>"}
response = requests.post(url, headers=headers)
print(response.text)const options = {method: 'POST', headers: {'x-api-key': '<api-key>'}};
fetch('https://api.example.com/api/interactions/{interaction_id}/cancel', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/api/interactions/{interaction_id}/cancel",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_HTTPHEADER => [
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/api/interactions/{interaction_id}/cancel"
req, _ := http.NewRequest("POST", url, nil)
req.Header.Add("x-api-key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.example.com/api/interactions/{interaction_id}/cancel")
.header("x-api-key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/api/interactions/{interaction_id}/cancel")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"data": {
"interaction_id": "<string>",
"status": "<string>"
}
}{
"error": "<string>",
"code": "<string>"
}{
"error": "<string>",
"code": "<string>"
}{
"error": "<string>",
"code": "<string>"
}{
"error": "<string>",
"code": "<string>"
}
