curl --request POST \
--url https://app.searchable.com/api/mcp/projects/{projectId}/prompts \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"prompts": [
{
"text": "<string>",
"isBranded": true,
"topicIds": [
"<string>"
]
}
]
}
'import requests
url = "https://app.searchable.com/api/mcp/projects/{projectId}/prompts"
payload = { "prompts": [
{
"text": "<string>",
"isBranded": True,
"topicIds": ["<string>"]
}
] }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({prompts: [{text: '<string>', isBranded: true, topicIds: ['<string>']}]})
};
fetch('https://app.searchable.com/api/mcp/projects/{projectId}/prompts', 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://app.searchable.com/api/mcp/projects/{projectId}/prompts",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'prompts' => [
[
'text' => '<string>',
'isBranded' => true,
'topicIds' => [
'<string>'
]
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://app.searchable.com/api/mcp/projects/{projectId}/prompts"
payload := strings.NewReader("{\n \"prompts\": [\n {\n \"text\": \"<string>\",\n \"isBranded\": true,\n \"topicIds\": [\n \"<string>\"\n ]\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://app.searchable.com/api/mcp/projects/{projectId}/prompts")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"prompts\": [\n {\n \"text\": \"<string>\",\n \"isBranded\": true,\n \"topicIds\": [\n \"<string>\"\n ]\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.searchable.com/api/mcp/projects/{projectId}/prompts")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"prompts\": [\n {\n \"text\": \"<string>\",\n \"isBranded\": true,\n \"topicIds\": [\n \"<string>\"\n ]\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"prompts": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"text": "<string>",
"topics": [
{
"id": "<string>",
"name": "<string>"
}
],
"lastUpdated": "<string>",
"locations": [
{
"id": "<string>",
"countryCode": "<string>",
"city": "<string>",
"region": "<string>",
"latitude": 123,
"longitude": 123
}
],
"usesFallbackLocation": true,
"currentRevision": 123,
"topicId": "<string>",
"topicName": "<string>",
"createdAt": "2023-11-07T05:31:56Z",
"isFromOnboarding": true,
"isCustomized": true,
"isTracked": true,
"fallbackLocation": null,
"projectId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"intentCategory": "<string>",
"promptType": "<string>",
"isBranded": true,
"keywordSearchVolume": 123,
"keywordDifficulty": 123,
"updatedAt": "2023-11-07T05:31:56Z"
}
],
"created": 123,
"success": true
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"code": "unauthorized",
"error": "<string>",
"message": "<string>",
"howToFix": "<string>",
"requestId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"requiresUpgrade": true,
"retryable": true,
"timeout": true,
"quotaExceeded": true,
"current": 123,
"limit": 123,
"bulkLimitExceeded": true,
"requested": 123,
"maxAllowed": 123,
"details": {
"formErrors": [
"<string>"
],
"fieldErrors": {}
}
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"code": "unauthorized",
"error": "<string>",
"message": "<string>",
"howToFix": "<string>",
"requestId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"requiresUpgrade": true,
"retryable": true,
"timeout": true,
"quotaExceeded": true,
"current": 123,
"limit": 123,
"bulkLimitExceeded": true,
"requested": 123,
"maxAllowed": 123,
"details": {
"formErrors": [
"<string>"
],
"fieldErrors": {}
}
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"code": "unauthorized",
"error": "<string>",
"message": "<string>",
"howToFix": "<string>",
"requestId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"requiresUpgrade": true,
"retryable": true,
"timeout": true,
"quotaExceeded": true,
"current": 123,
"limit": 123,
"bulkLimitExceeded": true,
"requested": 123,
"maxAllowed": 123,
"details": {
"formErrors": [
"<string>"
],
"fieldErrors": {}
}
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"code": "unauthorized",
"error": "<string>",
"message": "<string>",
"howToFix": "<string>",
"requestId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"requiresUpgrade": true,
"retryable": true,
"timeout": true,
"quotaExceeded": true,
"current": 123,
"limit": 123,
"bulkLimitExceeded": true,
"requested": 123,
"maxAllowed": 123,
"details": {
"formErrors": [
"<string>"
],
"fieldErrors": {}
}
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"code": "unauthorized",
"error": "<string>",
"message": "<string>",
"howToFix": "<string>",
"requestId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"requiresUpgrade": true,
"retryable": true,
"timeout": true,
"quotaExceeded": true,
"current": 123,
"limit": 123,
"bulkLimitExceeded": true,
"requested": 123,
"maxAllowed": 123,
"details": {
"formErrors": [
"<string>"
],
"fieldErrors": {}
}
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"code": "unauthorized",
"error": "<string>",
"message": "<string>",
"howToFix": "<string>",
"requestId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"requiresUpgrade": true,
"retryable": true,
"timeout": true,
"quotaExceeded": true,
"current": 123,
"limit": 123,
"bulkLimitExceeded": true,
"requested": 123,
"maxAllowed": 123,
"details": {
"formErrors": [
"<string>"
],
"fieldErrors": {}
}
}Add prompts
Add 1-10 prompts in one call. They’re tracked straight away (isTracked: true), as when you add prompts in the app: the project’s next scheduled run checks them, and they count toward the prompt allowance. The whole batch is checked against the allowance first; one that does not fit adds nothing and returns 403 quota_exceeded, so archive some prompts first or add fewer. Requires a connection minted with the prompt:draft capability (not the bare write scope). NOT atomic across items: each prompt is created independently, so a failure partway through (for example another write taking the allowance’s last room) leaves the earlier items created (created in the response says how many). Any topicIds must belong to the same project as the prompt; one that does not is refused with 404 not_found, indistinguishable from a topic id that does not exist. Supports Idempotency-Key replay; a reused key with a different body returns 409 idempotency_conflict.
curl --request POST \
--url https://app.searchable.com/api/mcp/projects/{projectId}/prompts \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"prompts": [
{
"text": "<string>",
"isBranded": true,
"topicIds": [
"<string>"
]
}
]
}
'import requests
url = "https://app.searchable.com/api/mcp/projects/{projectId}/prompts"
payload = { "prompts": [
{
"text": "<string>",
"isBranded": True,
"topicIds": ["<string>"]
}
] }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({prompts: [{text: '<string>', isBranded: true, topicIds: ['<string>']}]})
};
fetch('https://app.searchable.com/api/mcp/projects/{projectId}/prompts', 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://app.searchable.com/api/mcp/projects/{projectId}/prompts",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'prompts' => [
[
'text' => '<string>',
'isBranded' => true,
'topicIds' => [
'<string>'
]
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://app.searchable.com/api/mcp/projects/{projectId}/prompts"
payload := strings.NewReader("{\n \"prompts\": [\n {\n \"text\": \"<string>\",\n \"isBranded\": true,\n \"topicIds\": [\n \"<string>\"\n ]\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://app.searchable.com/api/mcp/projects/{projectId}/prompts")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"prompts\": [\n {\n \"text\": \"<string>\",\n \"isBranded\": true,\n \"topicIds\": [\n \"<string>\"\n ]\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.searchable.com/api/mcp/projects/{projectId}/prompts")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"prompts\": [\n {\n \"text\": \"<string>\",\n \"isBranded\": true,\n \"topicIds\": [\n \"<string>\"\n ]\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"prompts": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"text": "<string>",
"topics": [
{
"id": "<string>",
"name": "<string>"
}
],
"lastUpdated": "<string>",
"locations": [
{
"id": "<string>",
"countryCode": "<string>",
"city": "<string>",
"region": "<string>",
"latitude": 123,
"longitude": 123
}
],
"usesFallbackLocation": true,
"currentRevision": 123,
"topicId": "<string>",
"topicName": "<string>",
"createdAt": "2023-11-07T05:31:56Z",
"isFromOnboarding": true,
"isCustomized": true,
"isTracked": true,
"fallbackLocation": null,
"projectId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"intentCategory": "<string>",
"promptType": "<string>",
"isBranded": true,
"keywordSearchVolume": 123,
"keywordDifficulty": 123,
"updatedAt": "2023-11-07T05:31:56Z"
}
],
"created": 123,
"success": true
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"code": "unauthorized",
"error": "<string>",
"message": "<string>",
"howToFix": "<string>",
"requestId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"requiresUpgrade": true,
"retryable": true,
"timeout": true,
"quotaExceeded": true,
"current": 123,
"limit": 123,
"bulkLimitExceeded": true,
"requested": 123,
"maxAllowed": 123,
"details": {
"formErrors": [
"<string>"
],
"fieldErrors": {}
}
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"code": "unauthorized",
"error": "<string>",
"message": "<string>",
"howToFix": "<string>",
"requestId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"requiresUpgrade": true,
"retryable": true,
"timeout": true,
"quotaExceeded": true,
"current": 123,
"limit": 123,
"bulkLimitExceeded": true,
"requested": 123,
"maxAllowed": 123,
"details": {
"formErrors": [
"<string>"
],
"fieldErrors": {}
}
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"code": "unauthorized",
"error": "<string>",
"message": "<string>",
"howToFix": "<string>",
"requestId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"requiresUpgrade": true,
"retryable": true,
"timeout": true,
"quotaExceeded": true,
"current": 123,
"limit": 123,
"bulkLimitExceeded": true,
"requested": 123,
"maxAllowed": 123,
"details": {
"formErrors": [
"<string>"
],
"fieldErrors": {}
}
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"code": "unauthorized",
"error": "<string>",
"message": "<string>",
"howToFix": "<string>",
"requestId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"requiresUpgrade": true,
"retryable": true,
"timeout": true,
"quotaExceeded": true,
"current": 123,
"limit": 123,
"bulkLimitExceeded": true,
"requested": 123,
"maxAllowed": 123,
"details": {
"formErrors": [
"<string>"
],
"fieldErrors": {}
}
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"code": "unauthorized",
"error": "<string>",
"message": "<string>",
"howToFix": "<string>",
"requestId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"requiresUpgrade": true,
"retryable": true,
"timeout": true,
"quotaExceeded": true,
"current": 123,
"limit": 123,
"bulkLimitExceeded": true,
"requested": 123,
"maxAllowed": 123,
"details": {
"formErrors": [
"<string>"
],
"fieldErrors": {}
}
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"code": "unauthorized",
"error": "<string>",
"message": "<string>",
"howToFix": "<string>",
"requestId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"requiresUpgrade": true,
"retryable": true,
"timeout": true,
"quotaExceeded": true,
"current": 123,
"limit": 123,
"bulkLimitExceeded": true,
"requested": 123,
"maxAllowed": 123,
"details": {
"formErrors": [
"<string>"
],
"fieldErrors": {}
}
}Authorizations
A Searchable API key, created under Settings → Workspace → Integrations. Send as Authorization: Bearer sea_xxxxx. Every key carries one or more scopes (read, write, admin) and may optionally be bound to a single project — see Getting started.
Headers
Optional client-generated key (e.g. a UUID). Retrying with the same key within 24h replays the original stored response (X-Idempotent-Replay: true) instead of repeating the side effect. See Idempotency.
Path Parameters
The project id.
Body
1 - 10 elementsShow child attributes
Show child attributes