curl --request POST \
--url https://api.scrapebento.com/v1/public/scrape/research \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"topic": {
"title": "Lipstick color trends: key developments",
"summary": "Recent shifts in lipstick color preferences and launches.",
"keyMessages": [
{
"title": "Cherry red returns for fall",
"url": "https://example.com/cherry-red",
"snippet": "Brands are leaning into deep reds this season."
}
]
},
"targetKeywords": [
"lipstick",
"color",
"red",
"cherry"
],
"researchProfile": "simple",
"wait": false
}
'import requests
url = "https://api.scrapebento.com/v1/public/scrape/research"
payload = {
"topic": {
"title": "Lipstick color trends: key developments",
"summary": "Recent shifts in lipstick color preferences and launches.",
"keyMessages": [
{
"title": "Cherry red returns for fall",
"url": "https://example.com/cherry-red",
"snippet": "Brands are leaning into deep reds this season."
}
]
},
"targetKeywords": ["lipstick", "color", "red", "cherry"],
"researchProfile": "simple",
"wait": False
}
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({
topic: {
title: 'Lipstick color trends: key developments',
summary: 'Recent shifts in lipstick color preferences and launches.',
keyMessages: [
{
title: 'Cherry red returns for fall',
url: 'https://example.com/cherry-red',
snippet: 'Brands are leaning into deep reds this season.'
}
]
},
targetKeywords: ['lipstick', 'color', 'red', 'cherry'],
researchProfile: 'simple',
wait: false
})
};
fetch('https://api.scrapebento.com/v1/public/scrape/research', 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.scrapebento.com/v1/public/scrape/research",
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([
'topic' => [
'title' => 'Lipstick color trends: key developments',
'summary' => 'Recent shifts in lipstick color preferences and launches.',
'keyMessages' => [
[
'title' => 'Cherry red returns for fall',
'url' => 'https://example.com/cherry-red',
'snippet' => 'Brands are leaning into deep reds this season.'
]
]
],
'targetKeywords' => [
'lipstick',
'color',
'red',
'cherry'
],
'researchProfile' => 'simple',
'wait' => false
]),
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://api.scrapebento.com/v1/public/scrape/research"
payload := strings.NewReader("{\n \"topic\": {\n \"title\": \"Lipstick color trends: key developments\",\n \"summary\": \"Recent shifts in lipstick color preferences and launches.\",\n \"keyMessages\": [\n {\n \"title\": \"Cherry red returns for fall\",\n \"url\": \"https://example.com/cherry-red\",\n \"snippet\": \"Brands are leaning into deep reds this season.\"\n }\n ]\n },\n \"targetKeywords\": [\n \"lipstick\",\n \"color\",\n \"red\",\n \"cherry\"\n ],\n \"researchProfile\": \"simple\",\n \"wait\": false\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://api.scrapebento.com/v1/public/scrape/research")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"topic\": {\n \"title\": \"Lipstick color trends: key developments\",\n \"summary\": \"Recent shifts in lipstick color preferences and launches.\",\n \"keyMessages\": [\n {\n \"title\": \"Cherry red returns for fall\",\n \"url\": \"https://example.com/cherry-red\",\n \"snippet\": \"Brands are leaning into deep reds this season.\"\n }\n ]\n },\n \"targetKeywords\": [\n \"lipstick\",\n \"color\",\n \"red\",\n \"cherry\"\n ],\n \"researchProfile\": \"simple\",\n \"wait\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.scrapebento.com/v1/public/scrape/research")
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 \"topic\": {\n \"title\": \"Lipstick color trends: key developments\",\n \"summary\": \"Recent shifts in lipstick color preferences and launches.\",\n \"keyMessages\": [\n {\n \"title\": \"Cherry red returns for fall\",\n \"url\": \"https://example.com/cherry-red\",\n \"snippet\": \"Brands are leaning into deep reds this season.\"\n }\n ]\n },\n \"targetKeywords\": [\n \"lipstick\",\n \"color\",\n \"red\",\n \"cherry\"\n ],\n \"researchProfile\": \"simple\",\n \"wait\": false\n}"
response = http.request(request)
puts response.read_body{
"data": {
"jobId": "job_research_1",
"status": "succeeded",
"kind": "research",
"creditsCharged": 7,
"result": {
"researchRunId": "0f8c…",
"profile": "Simple",
"retrievedEvidence": [
{
"snippet": "Deep cherry reds dominated the autumn runway palettes.",
"url": "https://example.com/cherry-red",
"domain": "example.com",
"title": "Cherry red returns for fall",
"overallScore": 0.82,
"semanticScore": 0.71,
"keywordScore": 0.4,
"trustScore": 0.6,
"freshnessScore": 0.6,
"retrievalReason": "semantic-match",
"evidenceScope": "current-run"
}
],
"structuredFacts": [],
"claimEvidence": [
{
"claim": "Cherry red was the dominant fall runway color.",
"url": "https://example.com/cherry-red",
"domain": "example.com",
"evidenceSnippet": "Deep cherry reds dominated the autumn runway palettes.",
"verificationStatus": "verified",
"confidence": 0.8,
"sourceTrustScore": 0.6
}
],
"crawledDocuments": [
{
"documentId": "8f1c2e00-0000-0000-0000-000000000001",
"url": "https://example.com/cherry-red",
"domain": "example.com",
"title": "Cherry red returns for fall",
"lane": "external-search:google",
"providerCode": "",
"fetchStatus": "fetched",
"reused": false,
"fetchedAtUtc": "2026-07-09T06:10:11.000Z",
"outboundLinkCount": 12,
"excerpt": "Deep cherry reds dominated…",
"cleanedTextPreview": "Deep cherry reds dominated the autumn runway…",
"cleanedText": "Deep cherry reds dominated the autumn runway palettes this season…"
},
{
"documentId": "8f1c2e00-0000-0000-0000-000000000002",
"url": "https://doi.org/10.1000/example",
"domain": "doi.org",
"title": "Color trends in fashion",
"lane": "curated:crossref",
"providerCode": "crossref",
"fetchStatus": "abstract",
"reused": false,
"fetchedAtUtc": "2026-07-09T06:10:12.000Z",
"outboundLinkCount": 0,
"excerpt": "This review surveys seasonal color trends…",
"cleanedTextPreview": "This review surveys seasonal color trends…",
"cleanedText": "This review surveys seasonal color trends across two decades…"
}
],
"laneCandidates": [
{
"url": "https://example.com/cherry-red",
"title": "Cherry red returns for fall",
"lane": "external-search:google",
"score": 0.72,
"snippet": "Deep cherry reds dominated the autumn runway palettes.",
"sourceName": "example.com",
"providerCode": "",
"publishedAt": "2026-06-01T00:00:00.000Z"
}
],
"summary": {
"sourcesConsidered": 24,
"sourcesSelected": 6,
"documentsFetched": 5,
"abstractDocuments": 1,
"reusedDocuments": 0,
"acceptedClaimCount": 1,
"averageTrustScore": 0.66,
"currentRunEvidenceCount": 7,
"historicalEvidenceCount": 0,
"durationMs": 48210
}
}
}
}Run grounded multi-source research on a topic
Requires api.write. Plans providers by topic category, fans out across
web search + curated API providers (arXiv/PubMed/SEC/FRED/…) + direct and
trusted candidate URLs, crawls and cleans the top documents, embeds their
chunks into a per-organization pgvector corpus, retrieves top-K evidence
(semantic + keyword + trust/freshness hybrid, spanning this run and prior
runs), and extracts structured facts + grounded claims. Returns an evidence
pack. The heaviest scrape kind and long-running: it always answers
202 and is polled, because its minimum runtime is minutes and no
synchronous wait window could observe completion — wait: true is
accepted and ignored for this endpoint. Billed per profile:
scrape.research (simple/auto) or scrape.research_deep (complex).
seedUrls, trustedCandidates and topic.keyMessages are each capped
at 20 entries, and at most options.maxDocuments candidates are crawled
across every lane. options budgets are clamped server-side
(maxDocuments 15, maxSearchResults 25, finalTopK 50).
curl --request POST \
--url https://api.scrapebento.com/v1/public/scrape/research \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"topic": {
"title": "Lipstick color trends: key developments",
"summary": "Recent shifts in lipstick color preferences and launches.",
"keyMessages": [
{
"title": "Cherry red returns for fall",
"url": "https://example.com/cherry-red",
"snippet": "Brands are leaning into deep reds this season."
}
]
},
"targetKeywords": [
"lipstick",
"color",
"red",
"cherry"
],
"researchProfile": "simple",
"wait": false
}
'import requests
url = "https://api.scrapebento.com/v1/public/scrape/research"
payload = {
"topic": {
"title": "Lipstick color trends: key developments",
"summary": "Recent shifts in lipstick color preferences and launches.",
"keyMessages": [
{
"title": "Cherry red returns for fall",
"url": "https://example.com/cherry-red",
"snippet": "Brands are leaning into deep reds this season."
}
]
},
"targetKeywords": ["lipstick", "color", "red", "cherry"],
"researchProfile": "simple",
"wait": False
}
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({
topic: {
title: 'Lipstick color trends: key developments',
summary: 'Recent shifts in lipstick color preferences and launches.',
keyMessages: [
{
title: 'Cherry red returns for fall',
url: 'https://example.com/cherry-red',
snippet: 'Brands are leaning into deep reds this season.'
}
]
},
targetKeywords: ['lipstick', 'color', 'red', 'cherry'],
researchProfile: 'simple',
wait: false
})
};
fetch('https://api.scrapebento.com/v1/public/scrape/research', 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.scrapebento.com/v1/public/scrape/research",
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([
'topic' => [
'title' => 'Lipstick color trends: key developments',
'summary' => 'Recent shifts in lipstick color preferences and launches.',
'keyMessages' => [
[
'title' => 'Cherry red returns for fall',
'url' => 'https://example.com/cherry-red',
'snippet' => 'Brands are leaning into deep reds this season.'
]
]
],
'targetKeywords' => [
'lipstick',
'color',
'red',
'cherry'
],
'researchProfile' => 'simple',
'wait' => false
]),
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://api.scrapebento.com/v1/public/scrape/research"
payload := strings.NewReader("{\n \"topic\": {\n \"title\": \"Lipstick color trends: key developments\",\n \"summary\": \"Recent shifts in lipstick color preferences and launches.\",\n \"keyMessages\": [\n {\n \"title\": \"Cherry red returns for fall\",\n \"url\": \"https://example.com/cherry-red\",\n \"snippet\": \"Brands are leaning into deep reds this season.\"\n }\n ]\n },\n \"targetKeywords\": [\n \"lipstick\",\n \"color\",\n \"red\",\n \"cherry\"\n ],\n \"researchProfile\": \"simple\",\n \"wait\": false\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://api.scrapebento.com/v1/public/scrape/research")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"topic\": {\n \"title\": \"Lipstick color trends: key developments\",\n \"summary\": \"Recent shifts in lipstick color preferences and launches.\",\n \"keyMessages\": [\n {\n \"title\": \"Cherry red returns for fall\",\n \"url\": \"https://example.com/cherry-red\",\n \"snippet\": \"Brands are leaning into deep reds this season.\"\n }\n ]\n },\n \"targetKeywords\": [\n \"lipstick\",\n \"color\",\n \"red\",\n \"cherry\"\n ],\n \"researchProfile\": \"simple\",\n \"wait\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.scrapebento.com/v1/public/scrape/research")
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 \"topic\": {\n \"title\": \"Lipstick color trends: key developments\",\n \"summary\": \"Recent shifts in lipstick color preferences and launches.\",\n \"keyMessages\": [\n {\n \"title\": \"Cherry red returns for fall\",\n \"url\": \"https://example.com/cherry-red\",\n \"snippet\": \"Brands are leaning into deep reds this season.\"\n }\n ]\n },\n \"targetKeywords\": [\n \"lipstick\",\n \"color\",\n \"red\",\n \"cherry\"\n ],\n \"researchProfile\": \"simple\",\n \"wait\": false\n}"
response = http.request(request)
puts response.read_body{
"data": {
"jobId": "job_research_1",
"status": "succeeded",
"kind": "research",
"creditsCharged": 7,
"result": {
"researchRunId": "0f8c…",
"profile": "Simple",
"retrievedEvidence": [
{
"snippet": "Deep cherry reds dominated the autumn runway palettes.",
"url": "https://example.com/cherry-red",
"domain": "example.com",
"title": "Cherry red returns for fall",
"overallScore": 0.82,
"semanticScore": 0.71,
"keywordScore": 0.4,
"trustScore": 0.6,
"freshnessScore": 0.6,
"retrievalReason": "semantic-match",
"evidenceScope": "current-run"
}
],
"structuredFacts": [],
"claimEvidence": [
{
"claim": "Cherry red was the dominant fall runway color.",
"url": "https://example.com/cherry-red",
"domain": "example.com",
"evidenceSnippet": "Deep cherry reds dominated the autumn runway palettes.",
"verificationStatus": "verified",
"confidence": 0.8,
"sourceTrustScore": 0.6
}
],
"crawledDocuments": [
{
"documentId": "8f1c2e00-0000-0000-0000-000000000001",
"url": "https://example.com/cherry-red",
"domain": "example.com",
"title": "Cherry red returns for fall",
"lane": "external-search:google",
"providerCode": "",
"fetchStatus": "fetched",
"reused": false,
"fetchedAtUtc": "2026-07-09T06:10:11.000Z",
"outboundLinkCount": 12,
"excerpt": "Deep cherry reds dominated…",
"cleanedTextPreview": "Deep cherry reds dominated the autumn runway…",
"cleanedText": "Deep cherry reds dominated the autumn runway palettes this season…"
},
{
"documentId": "8f1c2e00-0000-0000-0000-000000000002",
"url": "https://doi.org/10.1000/example",
"domain": "doi.org",
"title": "Color trends in fashion",
"lane": "curated:crossref",
"providerCode": "crossref",
"fetchStatus": "abstract",
"reused": false,
"fetchedAtUtc": "2026-07-09T06:10:12.000Z",
"outboundLinkCount": 0,
"excerpt": "This review surveys seasonal color trends…",
"cleanedTextPreview": "This review surveys seasonal color trends…",
"cleanedText": "This review surveys seasonal color trends across two decades…"
}
],
"laneCandidates": [
{
"url": "https://example.com/cherry-red",
"title": "Cherry red returns for fall",
"lane": "external-search:google",
"score": 0.72,
"snippet": "Deep cherry reds dominated the autumn runway palettes.",
"sourceName": "example.com",
"providerCode": "",
"publishedAt": "2026-06-01T00:00:00.000Z"
}
],
"summary": {
"sourcesConsidered": 24,
"sourcesSelected": 6,
"documentsFetched": 5,
"abstractDocuments": 1,
"reusedDocuments": 0,
"acceptedClaimCount": 1,
"averageTrustScore": 0.66,
"currentRunEvidenceCount": 7,
"historicalEvidenceCount": 0,
"durationMs": 48210
}
}
}
}Authorizations
Send a workspace API token in the Authorization: Bearer <token> header.
Keys carry the satk_ prefix and spend your organization's credit
balance. GET /v1/public/balance reports what is left.
Test-mode keys (satk_test_), which drew on a separate self-refilling
allowance, have been retired and no longer authenticate.
Headers
Optional deduplication key, scoped to your organization. Re-sending a request with a key that was already used returns the original job instead of creating and charging for a second one.
Supersedes the idempotencyKey body field, which remains supported as
a deprecated alias. If both are present, this header wins.
255Body
Show child attributes
Show child attributes
Omit or null to auto-classify. "complex" selects the heavier deep tier.
simple, complex Show child attributes
Show child attributes
Show child attributes
Show child attributes
Response
The terminal evidence pack. Documented for the shape of result;
this endpoint always answers 202 in practice (see above).
- Option 1
- Option 2
Show child attributes
Show child attributes