curl --request DELETE \
--url https://api.scripe.io/v1/sources/{sourceId} \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.scripe.io/v1/sources/{sourceId}"
headers = {"Authorization": "Bearer <token>"}
response = requests.delete(url, headers=headers)
print(response.text)const options = {method: 'DELETE', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.scripe.io/v1/sources/{sourceId}', 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.scripe.io/v1/sources/{sourceId}",
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.scripe.io/v1/sources/{sourceId}"
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.scripe.io/v1/sources/{sourceId}")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.scripe.io/v1/sources/{sourceId}")
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{
"data": {
"phase": "proposal",
"sourceId": "src_a1b2c3d4e5f6g7h8",
"projectId": "proj_a1b2c3d4e5f6g7h8",
"toDelete": {
"topics": 123,
"knowledgeDocuments": 123,
"storedFile": true,
"hooksOfThoseTopics": true,
"transcriptParagraphsAndSentences": true,
"workspaceSharedKnowledgeDocuments": 123,
"knowledgeEmbeddings": true
},
"kept": {
"derivedPosts": 123,
"usageLedger": true
},
"warnings": [
"<string>"
],
"note": "<string>",
"confirmationToken": "<string>",
"tokenExpiresAt": 123,
"name": "<string>",
"status": "<string>",
"durationSeconds": 123,
"createdAt": "2023-11-07T05:31:56Z"
}
}{
"error": {
"code": "not_found",
"message": "<string>",
"request_id": "req_a1b2c3d4e5f6",
"docs_url": "<string>",
"details": "<unknown>"
}
}{
"error": {
"code": "not_found",
"message": "<string>",
"request_id": "req_a1b2c3d4e5f6",
"docs_url": "<string>",
"details": "<unknown>"
}
}{
"error": {
"code": "not_found",
"message": "<string>",
"request_id": "req_a1b2c3d4e5f6",
"docs_url": "<string>",
"details": "<unknown>"
}
}{
"error": {
"code": "not_found",
"message": "<string>",
"request_id": "req_a1b2c3d4e5f6",
"docs_url": "<string>",
"details": "<unknown>"
}
}{
"error": {
"code": "not_found",
"message": "<string>",
"request_id": "req_a1b2c3d4e5f6",
"docs_url": "<string>",
"details": "<unknown>"
}
}Delete a source (two-phase)
Permanently delete a source: the row, its full transcript (paragraphs and sentences), its topics and their hooks, its knowledge-base copy (document, chunks, and embeddings — knowledge search stops returning the content immediately), and the stored audio/video/file object. The storage quota those bytes held is released. This cannot be undone.
It is deliberately not total erasure, and the proposal and result both say so: posts generated from the source are the user’s content and are kept (their link to the source simply goes stale), and the internal usage-accounting ledger survives — deleting it would rewrite historical cost reporting.
Two-phase. A DELETE without confirmationToken deletes
nothing: it returns a proposal describing exactly what will be
removed and what survives, plus a confirmationToken (expires
~5 minutes). Show the proposal to the user; after they
explicitly confirm, repeat the same request with
?confirmationToken= to execute. A token is bound to this
source and this principal — a mismatched or expired token fails
400 invalid_request with details.reason: confirmation_invalid / confirmation_expired and deletes
nothing.
Emits source.deleted on execution (identity only, never the
transcript).
Requires the sources:destroy scope, which sources:write and
the write alias never imply — request it explicitly at
consent.
Workspace-shared knowledge. If any knowledge-base document
written from this transcript was shared with the whole company,
the delete additionally requires an admin — acting through an
OAuth grant — of the workspace that document is shared with,
which is not always the caller’s own. That is the same rule
delete_knowledge_doc applies to those rows, enforced in both
phases. Without it the call fails 403 admin_required and
nothing is deleted. The proposal names the count in
data.toDelete.workspaceSharedKnowledgeDocuments.
curl --request DELETE \
--url https://api.scripe.io/v1/sources/{sourceId} \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.scripe.io/v1/sources/{sourceId}"
headers = {"Authorization": "Bearer <token>"}
response = requests.delete(url, headers=headers)
print(response.text)const options = {method: 'DELETE', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.scripe.io/v1/sources/{sourceId}', 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.scripe.io/v1/sources/{sourceId}",
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.scripe.io/v1/sources/{sourceId}"
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.scripe.io/v1/sources/{sourceId}")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.scripe.io/v1/sources/{sourceId}")
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{
"data": {
"phase": "proposal",
"sourceId": "src_a1b2c3d4e5f6g7h8",
"projectId": "proj_a1b2c3d4e5f6g7h8",
"toDelete": {
"topics": 123,
"knowledgeDocuments": 123,
"storedFile": true,
"hooksOfThoseTopics": true,
"transcriptParagraphsAndSentences": true,
"workspaceSharedKnowledgeDocuments": 123,
"knowledgeEmbeddings": true
},
"kept": {
"derivedPosts": 123,
"usageLedger": true
},
"warnings": [
"<string>"
],
"note": "<string>",
"confirmationToken": "<string>",
"tokenExpiresAt": 123,
"name": "<string>",
"status": "<string>",
"durationSeconds": 123,
"createdAt": "2023-11-07T05:31:56Z"
}
}{
"error": {
"code": "not_found",
"message": "<string>",
"request_id": "req_a1b2c3d4e5f6",
"docs_url": "<string>",
"details": "<unknown>"
}
}{
"error": {
"code": "not_found",
"message": "<string>",
"request_id": "req_a1b2c3d4e5f6",
"docs_url": "<string>",
"details": "<unknown>"
}
}{
"error": {
"code": "not_found",
"message": "<string>",
"request_id": "req_a1b2c3d4e5f6",
"docs_url": "<string>",
"details": "<unknown>"
}
}{
"error": {
"code": "not_found",
"message": "<string>",
"request_id": "req_a1b2c3d4e5f6",
"docs_url": "<string>",
"details": "<unknown>"
}
}{
"error": {
"code": "not_found",
"message": "<string>",
"request_id": "req_a1b2c3d4e5f6",
"docs_url": "<string>",
"details": "<unknown>"
}
}Authorizations
Pass Authorization: Bearer scripe_sk_live_<...> (or
scripe_sk_test_<...> for test keys) on every request. Keys
are scoped to a single workspace and can be revoked from the
Scripe dashboard.
The same header also accepts an OAuth 2.1 access token
(scripe_oat_*); both credentials share one scope vocabulary
and every operation below documents the scope it requires.
An API key can hold every scope named on this surface except
webhooks:manage, which is grantable to OAuth tokens only
today — the webhook-endpoint operations answer
403 scope_missing to every API key. Operations that name no
scope accept any valid token of the workspace.
Headers
Pin the API version. Format YYYY-MM-DD. Omit to receive the
currently rolling default. Unknown versions return 400 version_unsupported.
"2026-08-10"
Path Parameters
"src_a1b2c3d4e5f6g7h8"
Query Parameters
Omit on the first call to receive the proposal. Repeat the call with the returned token to execute the delete.
Response
Without confirmationToken: the proposal (data.phase: "proposal") — nothing was deleted. With a valid token: the
deletion result (data.deleted: true).
- Option 1
- Option 2
Phase one of the two-phase delete — nothing has been deleted. Names the blast radius AND what deliberately survives, so a caller expecting total erasure learns otherwise before confirming.
Show child attributes
Show child attributes