Cancel Search Job
curl --request DELETE \
--url https://api.spidra.io/api/search/{jobId} \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.spidra.io/api/search/{jobId}"
headers = {"Authorization": "Bearer <token>"}
response = requests.delete(url, headers=headers)
print(response.text)const options = {method: 'DELETE', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.spidra.io/api/search/{jobId}', 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.spidra.io/api/search/{jobId}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "DELETE",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$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.spidra.io/api/search/{jobId}"
req, _ := http.NewRequest("DELETE", 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))
}HttpResponse<String> response = Unirest.delete("https://api.spidra.io/api/search/{jobId}")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.spidra.io/api/search/{jobId}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Delete.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"status": "cancelled",
"jobId": "abc-123"
}{
"status": "error",
"message": "Cannot cancel a job that has already completed."
}{
"status": "error",
"message": "<string>"
}{
"status": "error",
"message": "You do not have permission to access this job."
}{
"status": "error",
"message": "Search job not found"
}Search Endpoints
Cancel Search Job
Stop a search job that is queued or actively running.
DELETE
/
search
/
{jobId}
Cancel Search Job
curl --request DELETE \
--url https://api.spidra.io/api/search/{jobId} \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.spidra.io/api/search/{jobId}"
headers = {"Authorization": "Bearer <token>"}
response = requests.delete(url, headers=headers)
print(response.text)const options = {method: 'DELETE', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.spidra.io/api/search/{jobId}', 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.spidra.io/api/search/{jobId}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "DELETE",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$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.spidra.io/api/search/{jobId}"
req, _ := http.NewRequest("DELETE", 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))
}HttpResponse<String> response = Unirest.delete("https://api.spidra.io/api/search/{jobId}")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.spidra.io/api/search/{jobId}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Delete.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"status": "cancelled",
"jobId": "abc-123"
}{
"status": "error",
"message": "Cannot cancel a job that has already completed."
}{
"status": "error",
"message": "<string>"
}{
"status": "error",
"message": "You do not have permission to access this job."
}{
"status": "error",
"message": "Search job not found"
}This stops a search job that is queued or currently running. Search jobs usually resolve in a few seconds, but a degraded upstream network can occasionally make one run much longer than normal — use this to stop waiting on it rather than polling indefinitely.
Cancelling a job that has already reached a terminal state (
completed or failed) returns a 400.
Example Request
curl -X DELETE https://api.spidra.io/api/search/abc-123 \
-H "Authorization: Bearer YOUR_API_KEY"
import requests
requests.delete(
"https://api.spidra.io/api/search/abc-123",
headers={"Authorization": "Bearer YOUR_API_KEY"}
)
await fetch("https://api.spidra.io/api/search/abc-123", {
method: "DELETE",
headers: { Authorization: "Bearer YOUR_API_KEY" }
});
Response
{
"status": "cancelled",
"jobId": "abc-123"
}
What Polling Sees After Cancelling
A search job has no separate “cancelled” job state — cancelling either removes it from the queue before it started, or signals the running job to stop at its next checkpoint (between search sources/attempts, not mid-request):- If the job hadn’t started yet, a subsequent GET /search/ returns 404 (
JOB_NOT_FOUND). - If the job was already running, it keeps reporting
status: "active"for a brief moment, then settles tostatus: "failed"witherror: "Search cancelled".
DELETE response also includes a message field explaining that cancellation was requested and not yet applied.
A running search can only stop at a checkpoint: between search sources and attempts, and once the engines have answered but before the search is billed. If the search had already finished finding results, it completes normally and is charged as usual. The same applies to a search with scrapeOptions: if cancellation arrives while page content is being fetched, no new pages are fetched, but pages already started are billed like any other scrape. Always check GET /search/ for the final state.
No credits are charged for a search that ends as failed with error: "Search cancelled".Was this page helpful?

